From e4535002e27bd225f4adfa8c2dde754411c7d931 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 11:32:57 +0200 Subject: [PATCH 01/75] Add anvil file support --- Cargo.toml | 3 +- valence_anvil/Cargo.toml | 20 + valence_anvil/examples/java_region.rs | 183 +++++++++ valence_anvil/src/error.rs | 128 +++++++ valence_anvil/src/lib.rs | 524 ++++++++++++++++++++++++++ valence_anvil/src/palette.rs | 67 ++++ 6 files changed, 924 insertions(+), 1 deletion(-) create mode 100644 valence_anvil/Cargo.toml create mode 100644 valence_anvil/examples/java_region.rs create mode 100644 valence_anvil/src/error.rs create mode 100644 valence_anvil/src/lib.rs create mode 100644 valence_anvil/src/palette.rs diff --git a/Cargo.toml b/Cargo.toml index fff0ff4f3..ed7b617d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ sha2 = "0.10.6" thiserror = "1.0.35" url = { version = "2.2.2", features = ["serde"] } uuid = { version = "1.1.2", features = ["serde"] } -valence_nbt = "0.3.0" +valence_nbt = {path = "valence_nbt"} vek = "0.15.8" [dependencies.tokio] @@ -71,6 +71,7 @@ num = "0.4.0" [workspace] members = [ "valence_nbt", + "valence_anvil", "packet_inspector", "performance_tests/players" ] diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml new file mode 100644 index 000000000..588af4f6e --- /dev/null +++ b/valence_anvil/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "valence_anvil" +description = "A library for Minecraft's Anvil world format." +documentation = "https://docs.rs/valence_anvil/" +repository = "https://github.com/valence_anvil/valence/tree/main/valence_anvil" +readme = "README.md" +license = "MIT" +keywords = ["anvil", "minecraft", "serialization"] +version = "0.1.0" +authors = ["Ryan Johnson ", "TerminatorNL "] +edition = "2021" + +[dependencies] +valence = {path = ".."} +valence_nbt = {path = "../valence_nbt"} +rayon = "1.5.3" +async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} +byteorder = "1" +tokio = {version = "1", features = ["fs", "io-util", "full"]} +futures = "0.3.24" \ No newline at end of file diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs new file mode 100644 index 000000000..25c5edc96 --- /dev/null +++ b/valence_anvil/examples/java_region.rs @@ -0,0 +1,183 @@ +extern crate valence; + +use std::net::SocketAddr; +use std::path::PathBuf; +use std::str::FromStr; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use valence::async_trait; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::client::{handle_event_default, GameMode}; +use valence::config::{Config, ServerListPing}; +use valence::dimension::DimensionId; +use valence::entity::{EntityId, EntityKind}; +use valence::player_list::PlayerListId; +use valence::server::{Server, SharedServer, ShutdownResult}; +use valence::text::{Color, TextFormat}; +use valence::util::chunks_in_view_distance; +use valence_anvil::AnvilWorld; + +pub fn main() -> ShutdownResult { + let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + + println!("World folder: {:?}", world_folder.canonicalize()); + + valence::start_server( + Game { + player_count: AtomicUsize::new(0), + anvil_world: AnvilWorld::new(world_folder), + }, + None, + ) +} + +struct Game { + player_count: AtomicUsize, + anvil_world: AnvilWorld, +} + +const MAX_PLAYERS: usize = 10; +const WORLD_FOLDER: &'static str = "./test_data/"; + +#[async_trait] +impl Config for Game { + type ServerState = Option; + type ClientState = EntityId; + type EntityState = (); + type WorldState = (); + /// If the chunk should stay loaded at the end of the tick. + type ChunkState = bool; + type PlayerListState = (); + + fn max_connections(&self) -> usize { + // We want status pings to be successful even if the server is full. + MAX_PLAYERS + 64 + } + + async fn server_list_ping( + &self, + _server: &SharedServer, + _remote_addr: SocketAddr, + _protocol_version: i32, + ) -> ServerListPing { + ServerListPing::Respond { + online_players: self.player_count.load(Ordering::SeqCst) as i32, + max_players: MAX_PLAYERS as i32, + player_sample: Default::default(), + description: "Hello Valence!".color(Color::AQUA), + favicon_png: Some( + include_bytes!("../../assets/logo-64x64.png") + .as_slice() + .into(), + ), + } + } + + fn init(&self, server: &mut Server) { + server.worlds.insert(DimensionId::default(), ()); + server.state = Some(server.player_lists.insert(()).0); + } + + fn update(&self, server: &mut Server) { + let (world_id, world) = server.worlds.iter_mut().next().unwrap(); + + server.clients.retain(|_, client| { + if client.created_this_tick() { + if self + .player_count + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |count| { + (count < MAX_PLAYERS).then_some(count + 1) + }) + .is_err() + { + client.disconnect("The server is full!".color(Color::RED)); + return false; + } + + match server + .entities + .insert_with_uuid(EntityKind::Player, client.uuid(), ()) + { + Some((id, _)) => client.state = id, + None => { + client.disconnect("Conflicting UUID"); + return false; + } + } + + client.spawn(world_id); + client.set_flat(true); + client.set_game_mode(GameMode::Spectator); + client.teleport([0.0, 200.0, 0.0], 0.0, 0.0); + client.set_player_list(server.state.clone()); + + if let Some(id) = &server.state { + server.player_lists.get_mut(id).insert( + client.uuid(), + client.username(), + client.textures().cloned(), + client.game_mode(), + 0, + None, + ); + } + + client.send_message("Welcome to the terrain example!".italic()); + } + + if client.is_disconnected() { + self.player_count.fetch_sub(1, Ordering::SeqCst); + if let Some(id) = &server.state { + server.player_lists.get_mut(id).remove(client.uuid()); + } + server.entities.remove(client.state); + + return false; + } + + if let Some(entity) = server.entities.get_mut(client.state) { + while handle_event_default(client, entity).is_some() {} + } + + let dist = client.view_distance(); + let p = client.position(); + + let new_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist).filter(|pos| { + if let Some(existing) = world.chunks.get_mut(*pos) { + existing.state = true; + false + } else { + true + } + }); + + let future = self.anvil_world.load_chunks(new_chunks); + let parsed_chunks = futures::executor::block_on(future).unwrap(); + for (pos, chunk) in parsed_chunks { + if let Some(chunk) = chunk { + world.chunks.insert(pos, chunk, true); + } else { + let mut blank_chunk = UnloadedChunk::new(16); + blank_chunk.set_block_state( + 0, + 0, + 0, + valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + ); + world.chunks.insert(pos, blank_chunk, true); + } + } + true + }); + + // Remove chunks outside the view distance of players. + world.chunks.retain(|_, chunk| { + if chunk.state { + chunk.state = false; + true + } else { + false + } + }); + } +} \ No newline at end of file diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs new file mode 100644 index 000000000..1da656e8f --- /dev/null +++ b/valence_anvil/src/error.rs @@ -0,0 +1,128 @@ +use std::error::Error as StdError; +use std::fmt::{Display, Formatter}; +use std::io; + +use valence::ident::Ident; + +/// Errors that can occur when encoding or decoding. +#[derive(Debug)] +pub struct Error { + /// Box this to keep the size of `Result` small. + cause: Box, +} + +impl Error { + pub(crate) fn unknown_compression_scheme(mode: u8) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::UnknownCompressionScheme(mode))), + } + } + + pub(crate) fn invalid_chunk_size(size: usize) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidChunkSize(size))), + } + } + + pub(crate) fn missing_nbt_value(key: &'static str) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::MissingNBT(key))), + } + } + + pub(crate) fn invalid_nbt(message: &'static str) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidNBT(message))), + } + } + + pub(crate) fn invalid_palette() -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidPalette)), + } + } + + pub(crate) fn unknown_type(ident: Ident) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::UnknownType(ident))), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match &*self.cause { + Cause::Io(e) => Some(e), + _ => None, + } + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + Self { + cause: Box::new(Cause::Io(e)), + } + } +} +impl From for Error { + fn from(e: valence::nbt::Error) -> Self { + Self { + cause: Box::new(Cause::NBT(e)), + } + } +} + +impl From> for Error { + fn from(e: valence::ident::IdentError) -> Self { + Self { + cause: Box::new(Cause::IdentityError(e)), + } + } +} + +#[derive(Debug)] +pub enum Cause { + Io(io::Error), + Parse(ParseError), + NBT(valence::nbt::Error), + IdentityError(valence::ident::IdentError), +} + +#[derive(Debug)] +pub enum ParseError { + UnknownCompressionScheme(u8), + InvalidChunkSize(usize), + MissingNBT(&'static str), + InvalidNBT(&'static str), + InvalidPalette, + UnknownType(Ident), +} + +#[derive(Debug)] +pub enum SerializeError { + // ChunkTooLarge +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &*self.cause { + Cause::Io(e) => e.fmt(f), + Cause::Parse(err) => err.fmt(f), + Cause::NBT(e) => e.fmt(f), + Cause::IdentityError(e) => e.fmt(f), + } + } +} + +impl Display for ParseError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { + write!(f, "Parse failed") + } +} + +impl Display for SerializeError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { + write!(f, "Serialization failed") + } +} \ No newline at end of file diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs new file mode 100644 index 000000000..be47f9469 --- /dev/null +++ b/valence_anvil/src/lib.rs @@ -0,0 +1,524 @@ +mod error; +mod palette; + +use std::collections::BTreeMap; +use std::fmt::{Debug, Formatter, Result as FmtResult}; +use std::io::{SeekFrom}; +use std::path::{Path, PathBuf}; + +use async_compression::tokio::bufread::ZlibDecoder; +use async_compression::tokio::write::GzipDecoder; +use byteorder::{BigEndian, ByteOrder}; +use tokio::fs::File; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWriteExt}; +use tokio::sync::Mutex; +use valence::biome::BiomeId; +use valence::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::ident::Ident; +use valence::nbt::{Compound, List, Value}; + +use crate::error::Error; +use crate::palette::DataFormat; + +#[derive(Debug)] +pub struct AnvilWorld { + world_root: PathBuf, + region_files: Mutex>>>, +} + +impl AnvilWorld { + pub fn new(directory: PathBuf) -> Self { + Self { + world_root: directory, + region_files: Mutex::new(BTreeMap::new()), + } + } + + pub async fn load_chunks>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut map = BTreeMap::>::new(); + for pos in positions.into_iter() { + let region_pos = RegionPos::from(pos); + map.entry(region_pos) + .and_modify(|v| v.push(pos)) + .or_insert(vec![pos]); + } + + let mut result_vec = Vec::<(ChunkPos, Option)>::new(); + let mut lock = self.region_files.lock().await; + for (region_pos, chunk_pos_vec) in map.into_iter() { + if let Some(region) = lock.entry(region_pos).or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path).await?).await?) + } else { + None + } + }) { + // A region file exists, and it is loaded. + result_vec.extend(region.parse_chunks(chunk_pos_vec).await?); + } else { + // No region file exists, there is no data to load here. + result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); + } + } + + Ok(result_vec) + } +} + +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] +pub struct RegionPos { + x: i32, + z: i32, +} + +impl From for RegionPos { + fn from(pos: ChunkPos) -> Self { + Self { + x: pos.x >> 5, + z: pos.z >> 5, + } + } +} + +impl RegionPos { + pub fn path(self, world_root: impl AsRef) -> PathBuf { + world_root + .as_ref() + .join("region") + .join(format!("r.{}.{}.mca", self.x, self.z)) + } +} + +#[derive(Debug)] +pub struct Region { + source: Mutex, + offset: u64, + header: AnvilHeader, +} + +impl Region { + /// Convenience method, creates a Region object from the given file. + pub async fn from_file(source: File) -> Result { + Self::from_seek(Mutex::new(source), 0).await + } +} + +impl Region { + /// Creates a Region object using the incoming stream. The offset defines + /// the position of the header start. + pub async fn from_seek(source: Mutex, offset: u64) -> Result { + let mut lock = source.lock().await; + lock.seek(SeekFrom::Start(offset)).await?; + let header = AnvilHeader::parse(&mut *lock).await?; + drop(lock); + + Ok(Self { + source, + offset, + header, + }) + } + + async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { + let seek_pos = self + .header + .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); + + let mut lock = self.source.lock().await; + + lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) + .await?; + + if seek_pos.len() == 0 { + return Ok(None); + } + + let compressed_chunk_size = { + let mut buf = [0u8; 4]; + lock.read_exact(&mut buf).await?; + BigEndian::read_u32(&buf) as usize + }; + + if compressed_chunk_size == 0 { + return Err(Error::invalid_chunk_size(compressed_chunk_size)); + } + + let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; + let uncompressed_buffer = compression + .read_to_vec(&mut *lock, compressed_chunk_size - 1) + .await?; + Ok(Some(uncompressed_buffer)) + } + + pub async fn parse_chunks>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut results = Vec::<(ChunkPos, Option)>::new(); + + for pos in positions.into_iter() { + let chunk_data = self.read_chunk_data(pos).await?; + if let Some(chunk_data) = chunk_data { + let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; + let parsed_chunk = Self::parse_chunk_nbt(&mut nbt)?; + results.push((pos, Some(parsed_chunk))); + } else { + results.push((pos, None)); + } + } + + Ok(results) + } + + fn parse_chunk_nbt(nbt: &mut Compound) -> Result { + fn take_assume(compound: &mut Compound, key: &'static str) -> Result + where + Option: From, + { + match compound.remove(key) { + None => Err(Error::missing_nbt_value(key)), + Some(value) => { + if let Some(value) = Option::::from(value) { + Ok(value) + } else { + Err(Error::invalid_nbt(key)) + } + } + } + } + + fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option + where + Option: From, + { + match compound.remove(key) { + None => None, + Some(value) => Option::::from(value), + } + } + + // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; + // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; + // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; +// + // let _status: String = take_assume(nbt, "Status")?; + // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; + + if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { + let mut y_max = 0i8; + let mut y_min = 0i8; + + for chunk_nbt in nbt_sections.iter() { + if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { + y_max = y_max.max(*section_y); + y_min = y_min.min(*section_y); + } else { + return Err(Error::missing_nbt_value("sections/*/Y")); + } + } + + // Max should always be equal or higher than 'lower'. Therefore, this is positive. + let section_height = ((y_max - y_min) as usize * 16) + 16; + let y_raise = isize::from(-y_min) * 16; + + //Parsing sections + let mut chunk = UnloadedChunk::new(section_height); + for mut nbt_section in nbt_sections.into_iter() { + let chunk_y_offset: isize = + isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; + + // Block states + let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; + let parsed_block_state_palette: Vec = + if let Some(Value::List(List::Compound(nbt_palette_vec))) = + nbt_block_states.remove("palette") + { + let mut palette_vec: Vec = + Vec::with_capacity(nbt_palette_vec.len()); + for mut nbt_palette in nbt_palette_vec { + let block_id = valence::ident::Ident::new(take_assume::( + &mut nbt_palette, + "Name", + )?)?; + let block_kind = + if let Some(block_kind) = BlockKind::from_str(block_id.path()) { + block_kind + } else { + return Err(Error::unknown_type(block_id)); + }; + let mut block_state = BlockState::from_kind(block_kind); + if let Some(Value::Compound(nbt_palette_properties)) = + nbt_palette.remove("Properties") + { + for (property_name, property_value) in nbt_palette_properties { + if let Value::String(property_value) = property_value { + let property_name = PropName::from_str(&property_name); + let property_value = PropValue::from_str(&property_value); + if let (Some(property_name), Some(property_value)) = + (property_name, property_value) + { + block_state = + block_state.set(property_name, property_value); + } else { + return Err(Error::invalid_nbt( + "sections/*/block_states/Properties/*/property \ + value is not recognized.", + )); + } + } else { + return Err(Error::invalid_nbt( + "sections/*/block_states/Properties/*/property value \ + is invalid.", + )); + } + } + } + palette_vec.push(block_state); + } + palette_vec + } else { + return Err(Error::invalid_nbt("sections/*/palette")); + }; + + // Block state palette + palette::parse_palette::( + &parsed_block_state_palette, + take_assume_optional(&mut nbt_block_states, "data"), + 4, + &mut |data| { + match data { + DataFormat::All(state) => { + if !state.is_air() { + for x in 0..16 { + for y in 0..16isize { + for z in 0..16 { + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + } + } + } + DataFormat::Palette(index, state) => { + let y = (index >> 8 & 0b1111) as isize; + let z = index >> 4 & 0b1111; + let x = index & 0b1111; + + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + Ok(()) + }, + )?; + + // Biome palette + let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; + let parsed_biome_palette: Vec = + if let Some(Value::List(List::String(biome_names))) = + nbt_biomes.remove("palette") + { + let mut biomes: Vec = Vec::with_capacity(biome_names.len()); + for biome in biome_names { + let _identity_IMPLEMENT_ME = Ident::new(biome)?; + + //TODO: EXTRACT BIOME IDs + //TODO: BiomeId::from_str(identity.path()); + biomes.push(BiomeId::default()); + } + biomes + } else { + return Err(Error::invalid_nbt("sections/*/palette.")); + }; + + palette::parse_palette::( + &parsed_biome_palette, + take_assume_optional(&mut nbt_biomes, "data"), + 0, + &mut |data| { + match data { + DataFormat::All(biome) => { + for x in 0..4 { + for y in 0..4isize { + for z in 0..4 { + chunk.set_biome( + x, + (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, + z, + biome, + ); + } + } + } + } + DataFormat::Palette(index, biome) => { + let y = (index >> 4 & 0b11) as isize; + let z = index >> 2 & 0b11; + let x = index & 0b11; + + let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); + chunk.set_biome( + x, + final_y as usize, + z, + biome, + ); + } + } + Ok(()) + }, + )?; + } + + //sections + + Ok(chunk) + } else { + return Err(Error::invalid_nbt("sections tag invalid.")); + } + } +} + +#[derive(Copy, Clone, Debug)] +struct AnvilHeader { + offsets: [ChunkLocation; 1024], + timestamps: [ChunkTimestamp; 1024], +} + +impl AnvilHeader { + /// Parses the header bytes from the current position + async fn parse(source: &mut R) -> Result { + let mut offsets = [ChunkLocation::zero(); 1024]; + for offset in &mut offsets { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + offset.load(buf); + } + let mut timestamps = [ChunkTimestamp::zero(); 1024]; + for timestamp in &mut timestamps { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + timestamp.load(buf); + } + Ok(Self { + offsets, + timestamps, + }) + } + + #[inline(always)] + fn offset(&self, x: usize, z: usize) -> &ChunkLocation { + &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] + } + + #[inline(always)] + fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { + &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] + } +} + +/// The location of the chunk inside the region file. +#[derive(Copy, Clone, Debug)] +struct ChunkLocation { + offset_sectors: u32, + len_sectors: u8, +} + +impl ChunkLocation { + const fn zero() -> Self { + Self { + offset_sectors: 0, + len_sectors: 0, + } + } + + const fn offset(&self) -> u64 { + self.offset_sectors as u64 * 1024 * 4 + } + + const fn len(&self) -> usize { + self.len_sectors as usize * 1024 * 4 + } + + fn load(&mut self, chunk: [u8; 4]) { + self.offset_sectors = BigEndian::read_u24(&chunk[..3]); + self.len_sectors = chunk[3]; + } +} + +/// The timestamp when the chunk was last modified in seconds since epoch. +#[derive(Copy, Clone)] +struct ChunkTimestamp(u32); + +impl Debug for ChunkTimestamp { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}s", self.0) + } +} + +impl ChunkTimestamp { + const fn zero() -> Self { + Self(0) + } + + fn load(&mut self, chunk: [u8; 4]) { + self.0 = BigEndian::read_u32(&chunk) + } +} + +#[derive(Debug, Copy, Clone)] +enum CompressionScheme { + GZip = 1, + Zlib = 2, + Raw = 3, +} + +impl CompressionScheme { + fn from_raw(mode: u8) -> Result { + match mode { + 1 => Ok(Self::GZip), + 2 => Ok(Self::Zlib), + 3 => Ok(Self::Raw), + mode => Err(Error::unknown_compression_scheme(mode)), + } + } + + async fn read_to_vec( + self, + source: &mut R, + length: usize, + ) -> Result, std::io::Error> { + let mut raw_data = vec![0u8; length]; + source.read_exact(&mut raw_data).await?; + match self { + CompressionScheme::GZip => { + let mut decoder = GzipDecoder::new(Vec::::new()); + decoder.write_all(&mut raw_data).await?; + decoder.shutdown().await?; + Ok(decoder.into_inner()) + } + CompressionScheme::Zlib => { + let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); + let mut vec = Vec::::new(); + decoder.read_to_end(&mut vec).await?; + Ok(vec) + } + CompressionScheme::Raw => { + Ok(raw_data) + } + } + } +} \ No newline at end of file diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs new file mode 100644 index 000000000..3113e5fc9 --- /dev/null +++ b/valence_anvil/src/palette.rs @@ -0,0 +1,67 @@ +use crate::error::Error; +use std::ops::BitXor; + +pub enum DataFormat { + All(T), + Palette(usize, T), +} + +pub fn parse_palette< + T: Copy, + F: (FnMut(DataFormat) -> Result<(), Error>) +>( + source: &Vec, + data: Option>, + min_bits: usize, + fun: &mut F, +) -> Result<(), Error> { + let palette_len = source.len(); + if let Some(data) = data { + if palette_len < 2 || data.is_empty() { + fun(DataFormat::All(source[0]))?; + Ok(()) + } else { + let choice_len = palette_len - 1; //Corrects for the absence of a non-choice: null is not an option. + let bits_per_index = usize::max( + (usize::BITS - choice_len.leading_zeros()) as usize, + min_bits, + ); + let entries_per_integer = i64::BITS as usize / bits_per_index; + + let mut entry_mask = (u64::MAX << bits_per_index).bitxor(u64::MAX); + let mut mask_fields: Vec<(u64, usize)> = vec![(0u64, 0usize); entries_per_integer]; + for i in 0..mask_fields.len() { + mask_fields[i] = (entry_mask, (i * bits_per_index)); + entry_mask = entry_mask << bits_per_index; + } + + let mut index: usize = 0; + for integer in data { + let integer = integer as u64; + for (mask, rev_shift) in &mask_fields { + let palette_index_unshifted = (integer & mask) as usize; + let palette_index_shifted = palette_index_unshifted >> rev_shift; + + // Uncomment the following to aid in debugging. + // println!("IN + // \t{integer:064b}\nMSK\t{mask:064b}({bits_per_index})\nRES\ + // t{palette_index_unshifted:064b}\nSFT\t{palette_index_shifted:064b} + // ({rev_shift} - {trailing_bits})\n"); + if palette_index_shifted > choice_len { + //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", + // palette_index_shifted, choice_len, + // bits_per_index, source, source.len()); + return Err(crate::error::Error::invalid_palette()); + } else { + fun(DataFormat::Palette(index, source[palette_index_shifted]))?; + index += 1; + } + } + } + Ok(()) + } + } else { + fun(DataFormat::All(source[0]))?; + Ok(()) + } +} \ No newline at end of file From 1e24edbee8388e7aa1ca679d21eb2ebf81476a5c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 15:48:59 +0200 Subject: [PATCH 02/75] Java part: Biome parsing --- extracted/biomes.json | 5483 +++++++++++++++++ .../main/java/rs/valence/extractor/Main.java | 2 +- .../valence/extractor/extractors/Biomes.java | 106 + 3 files changed, 5590 insertions(+), 1 deletion(-) create mode 100644 extracted/biomes.json create mode 100644 extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java diff --git a/extracted/biomes.json b/extracted/biomes.json new file mode 100644 index 000000000..da9810e47 --- /dev/null +++ b/extracted/biomes.json @@ -0,0 +1,5483 @@ +[ + { + "name": "minecraft:the_void", + "id": 0, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:plains", + "id": 1, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:sunflower_plains", + "id": 2, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_plains", + "id": 3, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.07, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:ice_spikes", + "id": 4, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.07, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:desert", + "id": 5, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:swamp", + "id": 6, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "swamp", + "foliage": 6975545, + "fog": 12638463, + "sky": 7907327, + "water_fog": 2302743, + "water": 6388580 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:mangrove_swamp", + "id": 7, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "swamp", + "foliage": 9285927, + "fog": 12638463, + "sky": 7907327, + "water_fog": 5077600, + "water": 3832426 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:forest", + "id": 8, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:flower_forest", + "id": 9, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:birch_forest", + "id": 10, + "weather": { + "precipitation": "rain", + "temperature": 0.6, + "downfall": 0.6 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8037887, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:dark_forest", + "id": 11, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "dark_forest", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_birch_forest", + "id": 12, + "weather": { + "precipitation": "rain", + "temperature": 0.6, + "downfall": 0.6 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8037887, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_pine_taiga", + "id": 13, + "weather": { + "precipitation": "rain", + "temperature": 0.3, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8168447, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_spruce_taiga", + "id": 14, + "weather": { + "precipitation": "rain", + "temperature": 0.25, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233983, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:taiga", + "id": 15, + "weather": { + "precipitation": "rain", + "temperature": 0.25, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233983, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_taiga", + "id": 16, + "weather": { + "precipitation": "snow", + "temperature": -0.5, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8625919, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:savanna", + "id": 17, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:savanna_plateau", + "id": 18, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_hills", + "id": 19, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_gravelly_hills", + "id": 20, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_forest", + "id": 21, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_savanna", + "id": 22, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:jungle", + "id": 23, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:sparse_jungle", + "id": 24, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:bamboo_jungle", + "id": 25, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:badlands", + "id": 26, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:eroded_badlands", + "id": 27, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:wooded_badlands", + "id": 28, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:meadow", + "id": 29, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 937679 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:grove", + "id": 30, + "weather": { + "precipitation": "snow", + "temperature": -0.2, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8495359, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_slopes", + "id": 31, + "weather": { + "precipitation": "snow", + "temperature": -0.3, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8560639, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_peaks", + "id": 32, + "weather": { + "precipitation": "snow", + "temperature": -0.7, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8756735, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:jagged_peaks", + "id": 33, + "weather": { + "precipitation": "snow", + "temperature": -0.7, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8756735, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:stony_peaks", + "id": 34, + "weather": { + "precipitation": "rain", + "temperature": 1.0, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7776511, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:river", + "id": 35, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_river", + "id": 36, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:beach", + "id": 37, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_beach", + "id": 38, + "weather": { + "precipitation": "snow", + "temperature": 0.05, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:stony_shore", + "id": 39, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:warm_ocean", + "id": 40, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 270131, + "water": 4445678 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:lukewarm_ocean", + "id": 41, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 267827, + "water": 4566514 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_lukewarm_ocean", + "id": 42, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 267827, + "water": 4566514 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:ocean", + "id": 43, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_ocean", + "id": 44, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:cold_ocean", + "id": 45, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_cold_ocean", + "id": 46, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_ocean", + "id": 47, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_frozen_ocean", + "id": 48, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:mushroom_fields", + "id": 49, + "weather": { + "precipitation": "rain", + "temperature": 0.9, + "downfall": 1.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:dripstone_caves", + "id": 50, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:lush_caves", + "id": 51, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_dark", + "id": 52, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:nether_wastes", + "id": 53, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 3344392, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:warped_forest", + "id": 54, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 1705242, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:crimson_forest", + "id": 55, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 3343107, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:soul_sand_valley", + "id": 56, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 1787717, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:basalt_deltas", + "id": 57, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 6840176, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:the_end", + "id": 58, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_highlands", + "id": 59, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_midlands", + "id": 60, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:small_end_islands", + "id": 61, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_barrens", + "id": 62, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + } +] \ No newline at end of file diff --git a/extractor/src/main/java/rs/valence/extractor/Main.java b/extractor/src/main/java/rs/valence/extractor/Main.java index 4990c4d9a..97f52f1ea 100644 --- a/extractor/src/main/java/rs/valence/extractor/Main.java +++ b/extractor/src/main/java/rs/valence/extractor/Main.java @@ -37,7 +37,7 @@ public static T magicallyInstantiate(Class clazz) { public void onInitialize() { LOGGER.info("Starting extractors..."); - var extractors = new Extractor[]{new Blocks(), new Entities(), new EntityData(), new Packets(), new Items(), new Enchants()}; + var extractors = new Extractor[]{new Blocks(), new Entities(), new EntityData(), new Packets(), new Items(), new Enchants(), new Biomes()}; Path outputDirectory; try { diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java new file mode 100644 index 000000000..2a452f0f8 --- /dev/null +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -0,0 +1,106 @@ +package rs.valence.extractor.extractors; + +import com.google.gson.*; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.registry.BuiltinRegistries; +import rs.valence.extractor.Main; + +import java.util.LinkedList; +import java.util.Optional; + +public class Biomes implements Main.Extractor { + public Biomes() { + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private JsonElement optional_to_json(Optional var){ + if(var.isEmpty()){ + return JsonNull.INSTANCE; + }else{ + var value = var.get(); + if(value instanceof Boolean){ + return new JsonPrimitive((Boolean) value); + }else if(value instanceof Integer){ + return new JsonPrimitive((Integer) value); + }else if(value instanceof Float){ + return new JsonPrimitive((Float) value); + }else if(value instanceof Long){ + return new JsonPrimitive((Long) value); + }else if(value instanceof Number){ + return new JsonPrimitive((Number) value); + }else{ + throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); + } + } + } + + @Override + public String fileName() { + return "biomes.json"; + } + + @Override + public JsonElement extract() { + var results = new LinkedList(); + for (var biome_key : BuiltinRegistries.BIOME.getKeys()){ + var identifier = biome_key.getValue(); + var biome = BuiltinRegistries.BIOME.get(identifier); + assert biome != null; + + var biomeJson = new JsonObject(); + + var weatherJson = new JsonObject(); + weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); + weatherJson.addProperty("temperature", biome.getTemperature()); + weatherJson.addProperty("downfall", biome.getDownfall()); + + var colorJson = new JsonObject(); + var biome_effects = biome.getEffects(); + colorJson.add("grass", optional_to_json(biome_effects.getGrassColor())); + colorJson.addProperty("grass_modifier", biome_effects.getGrassColorModifier().getName()); + colorJson.add("foliage", optional_to_json(biome_effects.getFoliageColor())); + colorJson.addProperty("fog", biome_effects.getFogColor()); + colorJson.addProperty("sky", biome_effects.getSkyColor()); + colorJson.addProperty("water_fog", biome_effects.getWaterFogColor()); + colorJson.addProperty("water", biome_effects.getWaterColor()); + + var spawnSettingsJson = new JsonObject(); + var spawnSettings = biome.getSpawnSettings(); + spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); + + var spawn_groups = new JsonArray(); + for (var spawn_group : SpawnGroup.values()){ + var group = new JsonObject(); + group.addProperty("name", spawn_group.getName()); + group.addProperty("capacity", spawn_group.getCapacity()); + group.addProperty("despawn_range_start", spawn_group.getDespawnStartRange()); + group.addProperty("despawn_range_immediate", spawn_group.getImmediateDespawnRange()); + group.addProperty("is_peaceful", spawn_group.isPeaceful()); + group.addProperty("is_rare", spawn_group.isRare()); + + spawn_groups.add(group); + } + spawnSettingsJson.add("groups", spawn_groups); + + biomeJson.addProperty("name",identifier.toString()); + biomeJson.addProperty("id",BuiltinRegistries.BIOME.getRawId(biome)); + biomeJson.add("weather", weatherJson); + biomeJson.add("color", colorJson); + biomeJson.add("spawn_settings", spawnSettingsJson); + + results.add(biomeJson); + } + + results.sort((one, two) -> { + try{ + return one.get("id").getAsInt() - two.get("id").getAsInt(); + }catch (Exception e){ + throw new RuntimeException(e); + } + }); + + var biomesJson = new JsonArray(results.size()); + results.forEach(biomesJson::add); + return biomesJson; + } +} From eb57badea84a848ce54d8ae753428e6b819a3d6c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 22:09:32 +0200 Subject: [PATCH 03/75] Rust part: Biome parsing --- build/biome.rs | 375 +++++++++++++++++++++++++++++++++++++++++++++++++ build/main.rs | 2 + src/biomes.rs | 4 + src/lib.rs | 1 + 4 files changed, 382 insertions(+) create mode 100644 build/biome.rs create mode 100644 src/biomes.rs diff --git a/build/biome.rs b/build/biome.rs new file mode 100644 index 000000000..e8e5157d5 --- /dev/null +++ b/build/biome.rs @@ -0,0 +1,375 @@ +use std::collections::{BTreeMap}; + +use heck::{ToPascalCase, ToSnakeCase}; +use proc_macro2::{Ident, TokenStream}; +use quote::{quote}; +use serde::Deserialize; + +use crate::ident; + +#[derive(Deserialize, Debug)] +pub struct ParsedBiome { + id: u16, + name: String, + weather: ParsedBiomeWeather, + color: ParsedBiomeColor, + spawn_settings: ParsedBiomeSpawnSettings, +} + +#[derive(Debug)] +pub struct RenamedBiome { + id: u16, + name: String, + rustified_name: Ident, + weather: ParsedBiomeWeather, + color: ParsedBiomeColor, + spawn_settings: ParsedBiomeSpawnSettings, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeWeather { + precipitation: String, + temperature: f32, + downfall: f32, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeColor { + grass_modifier: String, + grass: Option, + foliage: Option, + fog: i32, + sky: i32, + water_fog: i32, + water: i32, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeSpawnSettings { + probability: f32, + groups: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeGroupSpawnSettings { + name: String, + capacity: i32, + despawn_range_start: i32, + despawn_range_immediate: i32, + is_peaceful: bool, + is_rare: bool, +} + +pub fn build() -> anyhow::Result { + let biomes: Vec = serde_json::from_str(include_str!("../extracted/biomes.json"))?; + + let biomes = biomes + .into_iter() + .map(|biome| RenamedBiome { + id: biome.id, + rustified_name: ident(&biome.name.replace("minecraft:", "").to_pascal_case()), + name: biome.name, + weather: biome.weather, + color: biome.color, + spawn_settings: biome.spawn_settings, + }) + .collect::>(); + + let mut precipitation_types = BTreeMap::<&str, Ident>::new(); + let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); + let mut biome_group_spawn_types = BTreeMap::<&str, (Ident, Ident)>::new(); + for biome in biomes.iter() { + precipitation_types + .entry(biome.weather.precipitation.as_str()) + .or_insert_with(|| ident(biome.weather.precipitation.to_pascal_case())); + grass_modifier_types + .entry(biome.color.grass_modifier.as_str()) + .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); + for group in biome.spawn_settings.groups.iter() { + biome_group_spawn_types + .entry(group.name.as_str()) + .or_insert_with(|| { + ( + ident({ + let mut identity = group.name.to_snake_case(); + identity.insert_str(0, "group_"); + identity + }), + ident({ + let mut identity = group.name.to_pascal_case(); + identity.push_str("SpawnSettings"); + identity + }), + ) + }); + } + } + + fn option_to_quote(input: &Option) -> TokenStream { + match input { + Some(value) => quote!(Some(#value)), + None => quote!(None), + } + } + + let biome_kind_definitions = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let id = biome.id as isize; + quote! { + #rustified_name = #id, + } + }) + .collect::(); + + let biomekind_id_to_variant_lookup = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let id = &biome.id; + quote! { + #id => Some(Self::#rustified_name), + } + }) + .collect::(); + + let precipitation_names = precipitation_types + .iter() + .map(|(_, rust_id)| { + quote! { + pub #rust_id, + } + }) + .collect::(); + + let grass_modifier_names = grass_modifier_types + .iter() + .map(|(_, rust_id)| { + quote! { + pub #rust_id, + } + }) + .collect::(); + + let biomekind_names = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let name = &biome.name; + quote! { + Self::#rustified_name => #name, + } + }) + .collect::(); + + let biome_spawn_settings_fields = biome_group_spawn_types + .iter() + .map(|(_, (field, ident))| { + quote! { + pub #field: #ident, + } + }) + .collect::(); + + let biome_spawn_settings_structs = biome_group_spawn_types.iter().map(|(_, (_, ident))| ident); + + let biomekind_weather = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let precipitation = precipitation_types + .get(biome.weather.precipitation.as_str()) + .expect("Could not find previously generated precipitation"); + let downfall = &biome.weather.downfall; + let temperature = &biome.weather.temperature; + quote! { + Self::#rustified_name => BiomeWeather { + precipitation: Precipitation::#precipitation, + downfall: #downfall, + temperature: #temperature, + }, + } + }) + .collect::(); + + let biomekind_color = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let grass_modifier = grass_modifier_types + .get(biome.color.grass_modifier.as_str()) + .expect("Could not find previously generated grass modifier"); + let grass = option_to_quote(&biome.color.grass); + let foliage = option_to_quote(&biome.color.foliage); + let fog = &biome.color.fog; + let sky = &biome.color.sky; + let water_fog = &biome.color.water_fog; + let water = &biome.color.water; + quote! { + Self::#rustified_name => BiomeColor { + grass_modifier: GrassModifier::#grass_modifier, + grass: #grass, + foliage: #foliage, + fog: #fog, + sky: #sky, + water_fog: #water_fog, + water: #water, + }, + } + }) + .collect::(); + + let biomekind_spawn_settings_arms = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let probability = biome.spawn_settings.probability; + + let fields = biome.spawn_settings.groups.iter().map(|parsed_biome|{ + let (_, (field, declaration)) = biome_group_spawn_types.iter().find(|(name,_)| parsed_biome.name.as_str() == **name).expect("Could not find previously generated spawn type"); + let capacity = &parsed_biome.capacity; + let despawn_range_start = &parsed_biome.despawn_range_start; + let despawn_range_immediate = &parsed_biome.despawn_range_immediate; + let is_peaceful = &parsed_biome.is_peaceful; + let is_rare = &parsed_biome.is_rare; + quote! { + #field: #declaration{ + capacity: #capacity, + despawn_range_start: #despawn_range_start, + despawn_range_immediate: #despawn_range_immediate, + is_peaceful: #is_peaceful, + is_rare: #is_rare + } + } + }); + quote! { + Self::#rustified_name => VanillaBiomeSpawnSettings { + probability: #probability, + #( #fields ),* + }, + } + }) + .collect::(); + + Ok(quote! { + pub trait BiomeSpawnSettings { + fn capacity(&self) -> i32; + fn despawn_range_start(&self) -> i32; + fn despawn_range_immediate(&self) -> i32; + fn is_peaceful(&self) -> bool; + fn is_rare(&self) -> bool; + } + + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct BiomeWeather { + pub precipitation: Precipitation, + pub temperature: f32, + pub downfall: f32, + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum Precipitation { + #precipitation_names + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct BiomeColor { + pub grass_modifier: GrassModifier, + pub grass: Option, + pub foliage: Option, + pub fog: i32, + pub sky: i32, + pub water_fog: i32, + pub water: i32, + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum GrassModifier { + #grass_modifier_names + } + + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct VanillaBiomeSpawnSettings { + pub probability: f32, + #biome_spawn_settings_fields + } + + #( #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct #biome_spawn_settings_structs { + pub capacity: i32, + pub despawn_range_start: i32, + pub despawn_range_immediate: i32, + pub is_peaceful: bool, + pub is_rare: bool, + } + + impl BiomeSpawnSettings for #biome_spawn_settings_structs{ + fn capacity(&self) -> i32 { + self.capacity + } + fn despawn_range_start(&self) -> i32 { + self.despawn_range_start + } + fn despawn_range_immediate(&self) -> i32 { + self.despawn_range_immediate + } + fn is_peaceful(&self) -> bool { + self.is_peaceful + } + fn is_rare(&self) -> bool { + self.is_rare + } + } )* + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum BiomeKind { + #biome_kind_definitions + } + + impl BiomeKind { + /// Constructs an `BiomeKind` from a raw biome ID. + /// + /// If the given ID is invalid, `None` is returned. + pub const fn from_raw(id: u16) -> Option { + match id { + #biomekind_id_to_variant_lookup + _ => None + } + } + + /// Returns the raw biome ID. + pub const fn to_raw(self) -> u16 { + self as u16 + } + + /// Returns the biome name with both the namespace and path (eg: minecraft:plains) + pub const fn name(self) -> &'static str { + match self{ + #biomekind_names + } + } + + /// Gets the biome weather settings + pub const fn weather(self) -> BiomeWeather { + match self{ + #biomekind_weather + } + } + + /// Gets the biome color settings + pub const fn color(self) -> BiomeColor { + match self{ + #biomekind_color + } + } + + /// Gets the biome spawn settings + pub const fn spawn_settings(self) -> VanillaBiomeSpawnSettings { + match self{ + #biomekind_spawn_settings_arms + } + } + } + }) +} diff --git a/build/main.rs b/build/main.rs index d098a37ec..89e1d1f80 100644 --- a/build/main.rs +++ b/build/main.rs @@ -5,6 +5,7 @@ use std::{env, fs}; use anyhow::Context; use proc_macro2::{Ident, Span}; +mod biome; mod block; mod enchant; mod entity; @@ -20,6 +21,7 @@ pub fn main() -> anyhow::Result<()> { (block::build, "block.rs"), (item::build, "item.rs"), (enchant::build, "enchant.rs"), + (biome::build, "biome.rs"), ]; let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?; diff --git a/src/biomes.rs b/src/biomes.rs new file mode 100644 index 000000000..dd8f04eb5 --- /dev/null +++ b/src/biomes.rs @@ -0,0 +1,4 @@ +// biome.rs exposes constant values provided by the build script. +// All biome variants are located in `BiomeKind`. You can use the +// associated const fn functions of `BiomeKind` to access details about a biome type. +include!(concat!(env!("OUT_DIR"), "/biome.rs")); \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c6a142911..66c2cad90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -126,6 +126,7 @@ pub mod text; pub mod username; pub mod util; pub mod world; +pub mod biomes; /// Use `valence::prelude::*` to import the most commonly used items from the /// library. From 66459425bce95fa3086fa66adae46d09628a7d95 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 22:48:43 +0200 Subject: [PATCH 04/75] Rework biome extraction: Spawn rates --- extracted/biomes.json | 9370 +++++++++-------- .../valence/extractor/extractors/Biomes.java | 24 +- 2 files changed, 5226 insertions(+), 4168 deletions(-) diff --git a/extracted/biomes.json b/extracted/biomes.json index da9810e47..c979de145 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -18,72 +18,16 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -105,72 +49,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -192,72 +180,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -279,72 +311,98 @@ }, "spawn_settings": { "probability": 0.07, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -366,72 +424,98 @@ }, "spawn_settings": { "probability": 0.07, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -453,72 +537,92 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 19 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:husk", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -540,72 +644,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -627,72 +775,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -714,72 +889,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -801,72 +1014,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -888,72 +1139,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -975,72 +1258,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1062,72 +1377,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1149,72 +1496,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 25 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1236,72 +1633,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1323,72 +1770,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1410,72 +1907,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1497,72 +2044,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1584,72 +2175,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1671,72 +2312,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1758,72 +2437,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1845,72 +2562,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1932,72 +2687,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2019,72 +2818,128 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:ocelot", + "min_group_size": 1, + "max_group_size": 3, + "weight": 2 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "minecraft:panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2106,72 +2961,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2193,72 +3086,128 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:ocelot", + "min_group_size": 1, + "max_group_size": 1, + "weight": 2 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "minecraft:panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 80 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2280,72 +3229,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2367,72 +3323,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2454,72 +3417,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2541,72 +3511,98 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 6, + "weight": 2 + }, + { + "name": "minecraft:sheep", + "min_group_size": 2, + "max_group_size": 4, + "weight": 2 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2628,72 +3624,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2715,72 +3761,92 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2802,72 +3868,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2889,72 +3969,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2976,72 +4070,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3063,72 +4164,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 100 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } }, { @@ -3150,72 +4278,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } }, { @@ -3237,72 +4392,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:turtle", + "min_group_size": 2, + "max_group_size": 5, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3324,72 +4493,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3411,72 +4587,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3498,72 +4681,111 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 15 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3585,72 +4807,117 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 2, + "weight": 10 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3672,72 +4939,117 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 8 + }, + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3759,72 +5071,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } }, { @@ -3846,72 +5191,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } }, { @@ -3933,72 +5311,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4020,72 +5431,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4107,72 +5551,106 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4194,72 +5672,106 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4281,72 +5793,37 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [ + { + "name": "minecraft:mooshroom", + "min_group_size": 4, + "max_group_size": 8, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4368,72 +5845,85 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4455,72 +5945,93 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [ + { + "name": "minecraft:axolotl", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -4542,72 +6053,16 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4629,72 +6084,54 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "minecraft:zombified_piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:magma_cube", + "min_group_size": 4, + "max_group_size": 4, + "weight": 2 + }, + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 15 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4716,72 +6153,30 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4803,72 +6198,42 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:zombified_piglin", + "min_group_size": 2, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:hoglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 9 + }, + { + "name": "minecraft:piglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4890,72 +6255,42 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:skeleton", + "min_group_size": 5, + "max_group_size": 5, + "weight": 20 + }, + { + "name": "minecraft:ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4977,72 +6312,36 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:ghast", + "min_group_size": 1, + "max_group_size": 1, + "weight": 40 + }, + { + "name": "minecraft:magma_cube", + "min_group_size": 2, + "max_group_size": 5, + "weight": 100 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5064,72 +6363,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5151,72 +6401,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5238,72 +6439,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5325,72 +6477,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5412,72 +6515,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } ] \ No newline at end of file diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index 2a452f0f8..cb27981ad 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -2,6 +2,7 @@ import com.google.gson.*; import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; import rs.valence.extractor.Main; @@ -68,17 +69,20 @@ public JsonElement extract() { var spawnSettings = biome.getSpawnSettings(); spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); - var spawn_groups = new JsonArray(); + var spawn_groups = new JsonObject(); for (var spawn_group : SpawnGroup.values()){ - var group = new JsonObject(); - group.addProperty("name", spawn_group.getName()); - group.addProperty("capacity", spawn_group.getCapacity()); - group.addProperty("despawn_range_start", spawn_group.getDespawnStartRange()); - group.addProperty("despawn_range_immediate", spawn_group.getImmediateDespawnRange()); - group.addProperty("is_peaceful", spawn_group.isPeaceful()); - group.addProperty("is_rare", spawn_group.isRare()); - - spawn_groups.add(group); + var spawns_within_group = new JsonArray(); + for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()){ + var within_group = new JsonObject(); + // Depreciated method to get the entity namespace and path. + //noinspection deprecation + within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); + within_group.addProperty("min_group_size", entry.minGroupSize); + within_group.addProperty("max_group_size", entry.maxGroupSize); + within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawns_within_group.add(within_group); + } + spawn_groups.add(spawn_group.asString(), spawns_within_group); } spawnSettingsJson.add("groups", spawn_groups); From 73cecfeeede1d26f6510ea619c40b5d581a2ff7e Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 24 Oct 2022 00:15:47 +0200 Subject: [PATCH 05/75] Rust part: Biome parsing --- build/biome.rs | 158 +++++++++++++++++-------------------------------- src/biomes.rs | 5 +- src/lib.rs | 2 +- 3 files changed, 59 insertions(+), 106 deletions(-) diff --git a/build/biome.rs b/build/biome.rs index e8e5157d5..efaf8c7bf 100644 --- a/build/biome.rs +++ b/build/biome.rs @@ -1,40 +1,40 @@ -use std::collections::{BTreeMap}; +use std::collections::{BTreeMap, HashMap}; use heck::{ToPascalCase, ToSnakeCase}; use proc_macro2::{Ident, TokenStream}; -use quote::{quote}; +use quote::quote; use serde::Deserialize; use crate::ident; #[derive(Deserialize, Debug)] -pub struct ParsedBiome { +struct ParsedBiome { id: u16, name: String, weather: ParsedBiomeWeather, color: ParsedBiomeColor, - spawn_settings: ParsedBiomeSpawnSettings, + spawn_settings: ParsedBiomeSpawnRates, } #[derive(Debug)] -pub struct RenamedBiome { +struct RenamedBiome { id: u16, name: String, rustified_name: Ident, weather: ParsedBiomeWeather, color: ParsedBiomeColor, - spawn_settings: ParsedBiomeSpawnSettings, + spawn_rates: ParsedBiomeSpawnRates, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeWeather { +struct ParsedBiomeWeather { precipitation: String, temperature: f32, downfall: f32, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeColor { +struct ParsedBiomeColor { grass_modifier: String, grass: Option, foliage: Option, @@ -45,19 +45,17 @@ pub struct ParsedBiomeColor { } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeSpawnSettings { +struct ParsedBiomeSpawnRates { probability: f32, - groups: Vec, + groups: HashMap>, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeGroupSpawnSettings { +struct ParsedSpawnRate { name: String, - capacity: i32, - despawn_range_start: i32, - despawn_range_immediate: i32, - is_peaceful: bool, - is_rare: bool, + min_group_size: u32, + max_group_size: u32, + weight: i32, } pub fn build() -> anyhow::Result { @@ -71,13 +69,13 @@ pub fn build() -> anyhow::Result { name: biome.name, weather: biome.weather, color: biome.color, - spawn_settings: biome.spawn_settings, + spawn_rates: biome.spawn_settings, }) .collect::>(); let mut precipitation_types = BTreeMap::<&str, Ident>::new(); let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); - let mut biome_group_spawn_types = BTreeMap::<&str, (Ident, Ident)>::new(); + let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); for biome in biomes.iter() { precipitation_types .entry(biome.weather.precipitation.as_str()) @@ -85,23 +83,10 @@ pub fn build() -> anyhow::Result { grass_modifier_types .entry(biome.color.grass_modifier.as_str()) .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); - for group in biome.spawn_settings.groups.iter() { - biome_group_spawn_types - .entry(group.name.as_str()) - .or_insert_with(|| { - ( - ident({ - let mut identity = group.name.to_snake_case(); - identity.insert_str(0, "group_"); - identity - }), - ident({ - let mut identity = group.name.to_pascal_case(); - identity.push_str("SpawnSettings"); - identity - }), - ) - }); + for class in biome.spawn_rates.groups.keys() { + class_spawn_fields + .entry(class) + .or_insert_with(|| ident(class.to_snake_case())); } } @@ -138,7 +123,7 @@ pub fn build() -> anyhow::Result { .iter() .map(|(_, rust_id)| { quote! { - pub #rust_id, + #rust_id, } }) .collect::(); @@ -147,7 +132,7 @@ pub fn build() -> anyhow::Result { .iter() .map(|(_, rust_id)| { quote! { - pub #rust_id, + #rust_id, } }) .collect::(); @@ -163,17 +148,6 @@ pub fn build() -> anyhow::Result { }) .collect::(); - let biome_spawn_settings_fields = biome_group_spawn_types - .iter() - .map(|(_, (field, ident))| { - quote! { - pub #field: #ident, - } - }) - .collect::(); - - let biome_spawn_settings_structs = biome_group_spawn_types.iter().map(|(_, (_, ident))| ident); - let biomekind_weather = biomes .iter() .map(|biome| { @@ -224,27 +198,30 @@ pub fn build() -> anyhow::Result { .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let probability = biome.spawn_settings.probability; - - let fields = biome.spawn_settings.groups.iter().map(|parsed_biome|{ - let (_, (field, declaration)) = biome_group_spawn_types.iter().find(|(name,_)| parsed_biome.name.as_str() == **name).expect("Could not find previously generated spawn type"); - let capacity = &parsed_biome.capacity; - let despawn_range_start = &parsed_biome.despawn_range_start; - let despawn_range_immediate = &parsed_biome.despawn_range_immediate; - let is_peaceful = &parsed_biome.is_peaceful; - let is_rare = &parsed_biome.is_rare; - quote! { - #field: #declaration{ - capacity: #capacity, - despawn_range_start: #despawn_range_start, - despawn_range_immediate: #despawn_range_immediate, - is_peaceful: #is_peaceful, - is_rare: #is_rare + let probability = biome.spawn_rates.probability; + + let fields = biome.spawn_rates.groups.iter().map(|(class, rates)| { + let rates = rates.iter().map(|spawn_rate| { + let name = &spawn_rate.name; + let min_group_size = &spawn_rate.min_group_size; + let max_group_size = &spawn_rate.max_group_size; + let weight = &spawn_rate.weight; + quote! { + SpawnEntry { + name: #name, + min_group_size: #min_group_size, + max_group_size: #max_group_size, + weight: #weight + } } + }); + let class = ident(class); + quote! { + #class: &[#( #rates ),*] } }); quote! { - Self::#rustified_name => VanillaBiomeSpawnSettings { + Self::#rustified_name => VanillaBiomeSpawnRates { probability: #probability, #( #fields ),* }, @@ -252,13 +229,15 @@ pub fn build() -> anyhow::Result { }) .collect::(); + let spawn_classes = class_spawn_fields.values(); + Ok(quote! { - pub trait BiomeSpawnSettings { - fn capacity(&self) -> i32; - fn despawn_range_start(&self) -> i32; - fn despawn_range_immediate(&self) -> i32; - fn is_peaceful(&self) -> bool; - fn is_rare(&self) -> bool; + #[derive(Debug, Clone, PartialEq, PartialOrd)] + pub struct SpawnEntry { + pub name: &'static str, + pub min_group_size: u32, + pub max_group_size: u32, + pub weight: i32 } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] @@ -289,39 +268,12 @@ pub fn build() -> anyhow::Result { #grass_modifier_names } - #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] - pub struct VanillaBiomeSpawnSettings { + #[derive(Debug, Clone, PartialEq, PartialOrd)] + pub struct VanillaBiomeSpawnRates { pub probability: f32, - #biome_spawn_settings_fields + #( pub #spawn_classes: &'static [SpawnEntry] ),* } - #( #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct #biome_spawn_settings_structs { - pub capacity: i32, - pub despawn_range_start: i32, - pub despawn_range_immediate: i32, - pub is_peaceful: bool, - pub is_rare: bool, - } - - impl BiomeSpawnSettings for #biome_spawn_settings_structs{ - fn capacity(&self) -> i32 { - self.capacity - } - fn despawn_range_start(&self) -> i32 { - self.despawn_range_start - } - fn despawn_range_immediate(&self) -> i32 { - self.despawn_range_immediate - } - fn is_peaceful(&self) -> bool { - self.is_peaceful - } - fn is_rare(&self) -> bool { - self.is_rare - } - } )* - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BiomeKind { #biome_kind_definitions @@ -364,8 +316,8 @@ pub fn build() -> anyhow::Result { } } - /// Gets the biome spawn settings - pub const fn spawn_settings(self) -> VanillaBiomeSpawnSettings { + /// Gets the biome spawn rates + pub const fn spawn_rates(self) -> VanillaBiomeSpawnRates { match self{ #biomekind_spawn_settings_arms } diff --git a/src/biomes.rs b/src/biomes.rs index dd8f04eb5..96c84504b 100644 --- a/src/biomes.rs +++ b/src/biomes.rs @@ -1,4 +1,5 @@ // biome.rs exposes constant values provided by the build script. // All biome variants are located in `BiomeKind`. You can use the -// associated const fn functions of `BiomeKind` to access details about a biome type. -include!(concat!(env!("OUT_DIR"), "/biome.rs")); \ No newline at end of file +// associated const fn functions of `BiomeKind` to access details about a biome +// type. +include!(concat!(env!("OUT_DIR"), "/biome.rs")); diff --git a/src/lib.rs b/src/lib.rs index 66c2cad90..f07e81b52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,6 +100,7 @@ pub use server::start_server; pub use {uuid, valence_nbt as nbt, vek}; pub mod biome; +pub mod biomes; pub mod block; mod block_pos; mod bvh; @@ -126,7 +127,6 @@ pub mod text; pub mod username; pub mod util; pub mod world; -pub mod biomes; /// Use `valence::prelude::*` to import the most commonly used items from the /// library. From 7cbce008cb1e298bb2c0475fd716a59597467e78 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 23 Oct 2022 15:48:49 -0700 Subject: [PATCH 06/75] Run formatter --- .../valence/extractor/extractors/Biomes.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index cb27981ad..c829dcf0f 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -14,22 +14,22 @@ public Biomes() { } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private JsonElement optional_to_json(Optional var){ - if(var.isEmpty()){ + private JsonElement optional_to_json(Optional var) { + if (var.isEmpty()) { return JsonNull.INSTANCE; - }else{ + } else { var value = var.get(); - if(value instanceof Boolean){ + if (value instanceof Boolean) { return new JsonPrimitive((Boolean) value); - }else if(value instanceof Integer){ + } else if (value instanceof Integer) { return new JsonPrimitive((Integer) value); - }else if(value instanceof Float){ + } else if (value instanceof Float) { return new JsonPrimitive((Float) value); - }else if(value instanceof Long){ + } else if (value instanceof Long) { return new JsonPrimitive((Long) value); - }else if(value instanceof Number){ + } else if (value instanceof Number) { return new JsonPrimitive((Number) value); - }else{ + } else { throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); } } @@ -43,7 +43,7 @@ public String fileName() { @Override public JsonElement extract() { var results = new LinkedList(); - for (var biome_key : BuiltinRegistries.BIOME.getKeys()){ + for (var biome_key : BuiltinRegistries.BIOME.getKeys()) { var identifier = biome_key.getValue(); var biome = BuiltinRegistries.BIOME.get(identifier); assert biome != null; @@ -70,24 +70,24 @@ public JsonElement extract() { spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); var spawn_groups = new JsonObject(); - for (var spawn_group : SpawnGroup.values()){ + for (var spawn_group : SpawnGroup.values()) { var spawns_within_group = new JsonArray(); - for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()){ - var within_group = new JsonObject(); - // Depreciated method to get the entity namespace and path. - //noinspection deprecation - within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); - within_group.addProperty("min_group_size", entry.minGroupSize); - within_group.addProperty("max_group_size", entry.maxGroupSize); - within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); - spawns_within_group.add(within_group); - } + for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()) { + var within_group = new JsonObject(); + // Depreciated method to get the entity namespace and path. + //noinspection deprecation + within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); + within_group.addProperty("min_group_size", entry.minGroupSize); + within_group.addProperty("max_group_size", entry.maxGroupSize); + within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawns_within_group.add(within_group); + } spawn_groups.add(spawn_group.asString(), spawns_within_group); } spawnSettingsJson.add("groups", spawn_groups); - biomeJson.addProperty("name",identifier.toString()); - biomeJson.addProperty("id",BuiltinRegistries.BIOME.getRawId(biome)); + biomeJson.addProperty("name", identifier.toString()); + biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); biomeJson.add("weather", weatherJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); @@ -96,9 +96,9 @@ public JsonElement extract() { } results.sort((one, two) -> { - try{ + try { return one.get("id").getAsInt() - two.get("id").getAsInt(); - }catch (Exception e){ + } catch (Exception e) { throw new RuntimeException(e); } }); From a26668c986078cb0c3414cb6f054a5b11496d0ed Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 23 Oct 2022 18:32:47 -0700 Subject: [PATCH 07/75] Adjustments --- extracted/biomes.json | 1578 ++++++++--------- .../valence/extractor/extractors/Biomes.java | 90 +- src/biome.rs | 10 + src/biomes.rs | 5 - src/lib.rs | 1 - 5 files changed, 837 insertions(+), 847 deletions(-) delete mode 100644 src/biomes.rs diff --git a/extracted/biomes.json b/extracted/biomes.json index c979de145..ae5d543b4 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -1,6 +1,6 @@ [ { - "name": "minecraft:the_void", + "name": "the_void", "id": 0, "weather": { "precipitation": "none", @@ -31,7 +31,7 @@ } }, { - "name": "minecraft:plains", + "name": "plains", "id": 1, "weather": { "precipitation": "rain", @@ -52,49 +52,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -102,37 +102,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 5 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 3, "weight": 1 @@ -140,7 +140,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -149,7 +149,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -162,7 +162,7 @@ } }, { - "name": "minecraft:sunflower_plains", + "name": "sunflower_plains", "id": 2, "weather": { "precipitation": "rain", @@ -183,49 +183,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -233,37 +233,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 5 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 3, "weight": 1 @@ -271,7 +271,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -280,7 +280,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -293,7 +293,7 @@ } }, { - "name": "minecraft:snowy_plains", + "name": "snowy_plains", "id": 3, "weather": { "precipitation": "snow", @@ -314,55 +314,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 20 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:stray", + "name": "stray", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -370,13 +370,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 10 }, { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -384,7 +384,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -393,7 +393,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -406,7 +406,7 @@ } }, { - "name": "minecraft:ice_spikes", + "name": "ice_spikes", "id": 4, "weather": { "precipitation": "snow", @@ -427,55 +427,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 20 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:stray", + "name": "stray", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -483,13 +483,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 10 }, { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -497,7 +497,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -506,7 +506,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -519,7 +519,7 @@ } }, { - "name": "minecraft:desert", + "name": "desert", "id": 5, "weather": { "precipitation": "none", @@ -540,55 +540,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 19 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 1 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:husk", + "name": "husk", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -596,7 +596,7 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 @@ -604,7 +604,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -613,7 +613,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -626,7 +626,7 @@ } }, { - "name": "minecraft:swamp", + "name": "swamp", "id": 6, "weather": { "precipitation": "rain", @@ -647,55 +647,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -703,31 +703,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:frog", + "name": "frog", "min_group_size": 2, "max_group_size": 5, "weight": 10 @@ -735,7 +735,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -744,7 +744,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -757,7 +757,7 @@ } }, { - "name": "minecraft:mangrove_swamp", + "name": "mangrove_swamp", "id": 7, "weather": { "precipitation": "rain", @@ -778,55 +778,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -834,7 +834,7 @@ ], "creature": [ { - "name": "minecraft:frog", + "name": "frog", "min_group_size": 2, "max_group_size": 5, "weight": 10 @@ -842,7 +842,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -851,7 +851,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -860,7 +860,7 @@ "water_creature": [], "water_ambient": [ { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -871,7 +871,7 @@ } }, { - "name": "minecraft:forest", + "name": "forest", "id": 8, "weather": { "precipitation": "rain", @@ -892,49 +892,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -942,31 +942,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 5 @@ -974,7 +974,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -983,7 +983,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -996,7 +996,7 @@ } }, { - "name": "minecraft:flower_forest", + "name": "flower_forest", "id": 9, "weather": { "precipitation": "rain", @@ -1017,49 +1017,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1067,31 +1067,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 @@ -1099,7 +1099,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1108,7 +1108,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1121,7 +1121,7 @@ } }, { - "name": "minecraft:birch_forest", + "name": "birch_forest", "id": 10, "weather": { "precipitation": "rain", @@ -1142,49 +1142,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1192,25 +1192,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1218,7 +1218,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1227,7 +1227,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1240,7 +1240,7 @@ } }, { - "name": "minecraft:dark_forest", + "name": "dark_forest", "id": 11, "weather": { "precipitation": "rain", @@ -1261,49 +1261,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1311,25 +1311,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1337,7 +1337,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1346,7 +1346,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1359,7 +1359,7 @@ } }, { - "name": "minecraft:old_growth_birch_forest", + "name": "old_growth_birch_forest", "id": 12, "weather": { "precipitation": "rain", @@ -1380,49 +1380,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1430,25 +1430,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1456,7 +1456,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1465,7 +1465,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1478,7 +1478,7 @@ } }, { - "name": "minecraft:old_growth_pine_taiga", + "name": "old_growth_pine_taiga", "id": 13, "weather": { "precipitation": "rain", @@ -1499,49 +1499,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 25 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1549,43 +1549,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1593,7 +1593,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1602,7 +1602,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1615,7 +1615,7 @@ } }, { - "name": "minecraft:old_growth_spruce_taiga", + "name": "old_growth_spruce_taiga", "id": 14, "weather": { "precipitation": "rain", @@ -1636,49 +1636,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1686,43 +1686,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1730,7 +1730,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1739,7 +1739,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1752,7 +1752,7 @@ } }, { - "name": "minecraft:taiga", + "name": "taiga", "id": 15, "weather": { "precipitation": "rain", @@ -1773,49 +1773,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1823,43 +1823,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1867,7 +1867,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1876,7 +1876,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1889,7 +1889,7 @@ } }, { - "name": "minecraft:snowy_taiga", + "name": "snowy_taiga", "id": 16, "weather": { "precipitation": "snow", @@ -1910,49 +1910,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1960,43 +1960,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -2004,7 +2004,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2013,7 +2013,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2026,7 +2026,7 @@ } }, { - "name": "minecraft:savanna", + "name": "savanna", "id": 17, "weather": { "precipitation": "none", @@ -2047,49 +2047,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2097,37 +2097,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -2135,7 +2135,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2144,7 +2144,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2157,7 +2157,7 @@ } }, { - "name": "minecraft:savanna_plateau", + "name": "savanna_plateau", "id": 18, "weather": { "precipitation": "none", @@ -2178,49 +2178,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2228,43 +2228,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -2272,7 +2272,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2281,7 +2281,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2294,7 +2294,7 @@ } }, { - "name": "minecraft:windswept_hills", + "name": "windswept_hills", "id": 19, "weather": { "precipitation": "rain", @@ -2315,49 +2315,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2365,31 +2365,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2397,7 +2397,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2406,7 +2406,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2419,7 +2419,7 @@ } }, { - "name": "minecraft:windswept_gravelly_hills", + "name": "windswept_gravelly_hills", "id": 20, "weather": { "precipitation": "rain", @@ -2440,49 +2440,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2490,31 +2490,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2522,7 +2522,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2531,7 +2531,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2544,7 +2544,7 @@ } }, { - "name": "minecraft:windswept_forest", + "name": "windswept_forest", "id": 21, "weather": { "precipitation": "rain", @@ -2565,49 +2565,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2615,31 +2615,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2647,7 +2647,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2656,7 +2656,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2669,7 +2669,7 @@ } }, { - "name": "minecraft:windswept_savanna", + "name": "windswept_savanna", "id": 22, "weather": { "precipitation": "none", @@ -2690,49 +2690,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2740,37 +2740,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -2778,7 +2778,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2787,7 +2787,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2800,7 +2800,7 @@ } }, { - "name": "minecraft:jungle", + "name": "jungle", "id": 23, "weather": { "precipitation": "rain", @@ -2821,55 +2821,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:ocelot", + "name": "ocelot", "min_group_size": 1, "max_group_size": 3, "weight": 2 @@ -2877,43 +2877,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:parrot", + "name": "parrot", "min_group_size": 1, "max_group_size": 2, "weight": 40 }, { - "name": "minecraft:panda", + "name": "panda", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -2921,7 +2921,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2930,7 +2930,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2943,7 +2943,7 @@ } }, { - "name": "minecraft:sparse_jungle", + "name": "sparse_jungle", "id": 24, "weather": { "precipitation": "rain", @@ -2964,49 +2964,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3014,31 +3014,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -3046,7 +3046,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3055,7 +3055,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3068,7 +3068,7 @@ } }, { - "name": "minecraft:bamboo_jungle", + "name": "bamboo_jungle", "id": 25, "weather": { "precipitation": "rain", @@ -3089,55 +3089,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:ocelot", + "name": "ocelot", "min_group_size": 1, "max_group_size": 1, "weight": 2 @@ -3145,43 +3145,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:parrot", + "name": "parrot", "min_group_size": 1, "max_group_size": 2, "weight": 40 }, { - "name": "minecraft:panda", + "name": "panda", "min_group_size": 1, "max_group_size": 2, "weight": 80 @@ -3189,7 +3189,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3198,7 +3198,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3211,7 +3211,7 @@ } }, { - "name": "minecraft:badlands", + "name": "badlands", "id": 26, "weather": { "precipitation": "none", @@ -3232,49 +3232,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3283,7 +3283,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3292,7 +3292,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3305,7 +3305,7 @@ } }, { - "name": "minecraft:eroded_badlands", + "name": "eroded_badlands", "id": 27, "weather": { "precipitation": "none", @@ -3326,49 +3326,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3377,7 +3377,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3386,7 +3386,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3399,7 +3399,7 @@ } }, { - "name": "minecraft:wooded_badlands", + "name": "wooded_badlands", "id": 28, "weather": { "precipitation": "none", @@ -3420,49 +3420,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3471,7 +3471,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3480,7 +3480,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3493,7 +3493,7 @@ } }, { - "name": "minecraft:meadow", + "name": "meadow", "id": 29, "weather": { "precipitation": "rain", @@ -3514,49 +3514,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3564,19 +3564,19 @@ ], "creature": [ { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 2, "weight": 1 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 6, "weight": 2 }, { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 2, "max_group_size": 4, "weight": 2 @@ -3584,7 +3584,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3593,7 +3593,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3606,7 +3606,7 @@ } }, { - "name": "minecraft:grove", + "name": "grove", "id": 30, "weather": { "precipitation": "snow", @@ -3627,49 +3627,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3677,43 +3677,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -3721,7 +3721,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3730,7 +3730,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3743,7 +3743,7 @@ } }, { - "name": "minecraft:snowy_slopes", + "name": "snowy_slopes", "id": 31, "weather": { "precipitation": "snow", @@ -3764,49 +3764,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3814,13 +3814,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -3828,7 +3828,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3837,7 +3837,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3850,7 +3850,7 @@ } }, { - "name": "minecraft:frozen_peaks", + "name": "frozen_peaks", "id": 32, "weather": { "precipitation": "snow", @@ -3871,49 +3871,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3921,7 +3921,7 @@ ], "creature": [ { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -3929,7 +3929,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3938,7 +3938,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3951,7 +3951,7 @@ } }, { - "name": "minecraft:jagged_peaks", + "name": "jagged_peaks", "id": 33, "weather": { "precipitation": "snow", @@ -3972,49 +3972,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4022,7 +4022,7 @@ ], "creature": [ { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -4030,7 +4030,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4039,7 +4039,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4052,7 +4052,7 @@ } }, { - "name": "minecraft:stony_peaks", + "name": "stony_peaks", "id": 34, "weather": { "precipitation": "rain", @@ -4073,49 +4073,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4124,7 +4124,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4133,7 +4133,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4146,7 +4146,7 @@ } }, { - "name": "minecraft:river", + "name": "river", "id": 35, "weather": { "precipitation": "rain", @@ -4167,55 +4167,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 100 @@ -4224,7 +4224,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4233,7 +4233,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4241,7 +4241,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 2 @@ -4249,7 +4249,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 5 @@ -4260,7 +4260,7 @@ } }, { - "name": "minecraft:frozen_river", + "name": "frozen_river", "id": 36, "weather": { "precipitation": "snow", @@ -4281,55 +4281,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -4338,7 +4338,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4347,7 +4347,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4355,7 +4355,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 2 @@ -4363,7 +4363,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 5 @@ -4374,7 +4374,7 @@ } }, { - "name": "minecraft:beach", + "name": "beach", "id": 37, "weather": { "precipitation": "rain", @@ -4395,49 +4395,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4445,7 +4445,7 @@ ], "creature": [ { - "name": "minecraft:turtle", + "name": "turtle", "min_group_size": 2, "max_group_size": 5, "weight": 5 @@ -4453,7 +4453,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4462,7 +4462,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4475,7 +4475,7 @@ } }, { - "name": "minecraft:snowy_beach", + "name": "snowy_beach", "id": 38, "weather": { "precipitation": "snow", @@ -4496,49 +4496,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4547,7 +4547,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4556,7 +4556,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4569,7 +4569,7 @@ } }, { - "name": "minecraft:stony_shore", + "name": "stony_shore", "id": 39, "weather": { "precipitation": "rain", @@ -4590,49 +4590,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4641,7 +4641,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4650,7 +4650,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4663,7 +4663,7 @@ } }, { - "name": "minecraft:warm_ocean", + "name": "warm_ocean", "id": 40, "weather": { "precipitation": "rain", @@ -4684,55 +4684,55 @@ "groups": { "monster": [ { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4741,7 +4741,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4750,7 +4750,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4758,13 +4758,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -4772,13 +4772,13 @@ ], "water_ambient": [ { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 15 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -4789,7 +4789,7 @@ } }, { - "name": "minecraft:lukewarm_ocean", + "name": "lukewarm_ocean", "id": 41, "weather": { "precipitation": "rain", @@ -4810,55 +4810,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4867,7 +4867,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4876,7 +4876,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4884,13 +4884,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 2, "weight": 10 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -4898,19 +4898,19 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 5 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -4921,7 +4921,7 @@ } }, { - "name": "minecraft:deep_lukewarm_ocean", + "name": "deep_lukewarm_ocean", "id": 42, "weather": { "precipitation": "rain", @@ -4942,55 +4942,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4999,7 +4999,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5008,7 +5008,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5016,13 +5016,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -5030,19 +5030,19 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 8 }, { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 5 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -5053,7 +5053,7 @@ } }, { - "name": "minecraft:ocean", + "name": "ocean", "id": 43, "weather": { "precipitation": "rain", @@ -5074,55 +5074,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5131,7 +5131,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5140,7 +5140,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5148,13 +5148,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5162,7 +5162,7 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 10 @@ -5173,7 +5173,7 @@ } }, { - "name": "minecraft:deep_ocean", + "name": "deep_ocean", "id": 44, "weather": { "precipitation": "rain", @@ -5194,55 +5194,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5251,7 +5251,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5260,7 +5260,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5268,13 +5268,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5282,7 +5282,7 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 10 @@ -5293,7 +5293,7 @@ } }, { - "name": "minecraft:cold_ocean", + "name": "cold_ocean", "id": 45, "weather": { "precipitation": "rain", @@ -5314,55 +5314,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5371,7 +5371,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5380,7 +5380,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5388,7 +5388,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 3 @@ -5396,13 +5396,13 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5413,7 +5413,7 @@ } }, { - "name": "minecraft:deep_cold_ocean", + "name": "deep_cold_ocean", "id": 46, "weather": { "precipitation": "rain", @@ -5434,55 +5434,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5491,7 +5491,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5500,7 +5500,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5508,7 +5508,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 3 @@ -5516,13 +5516,13 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5533,7 +5533,7 @@ } }, { - "name": "minecraft:frozen_ocean", + "name": "frozen_ocean", "id": 47, "weather": { "precipitation": "snow", @@ -5554,55 +5554,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5610,7 +5610,7 @@ ], "creature": [ { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5618,7 +5618,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5627,7 +5627,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5635,7 +5635,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 @@ -5643,7 +5643,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5654,7 +5654,7 @@ } }, { - "name": "minecraft:deep_frozen_ocean", + "name": "deep_frozen_ocean", "id": 48, "weather": { "precipitation": "rain", @@ -5675,55 +5675,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5731,7 +5731,7 @@ ], "creature": [ { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5739,7 +5739,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5748,7 +5748,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5756,7 +5756,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 @@ -5764,7 +5764,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5775,7 +5775,7 @@ } }, { - "name": "minecraft:mushroom_fields", + "name": "mushroom_fields", "id": 49, "weather": { "precipitation": "rain", @@ -5797,7 +5797,7 @@ "monster": [], "creature": [ { - "name": "minecraft:mooshroom", + "name": "mooshroom", "min_group_size": 4, "max_group_size": 8, "weight": 8 @@ -5805,7 +5805,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5814,7 +5814,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5827,7 +5827,7 @@ } }, { - "name": "minecraft:dripstone_caves", + "name": "dripstone_caves", "id": 50, "weather": { "precipitation": "rain", @@ -5848,55 +5848,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 4, "max_group_size": 4, "weight": 95 @@ -5905,7 +5905,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5914,7 +5914,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5927,7 +5927,7 @@ } }, { - "name": "minecraft:lush_caves", + "name": "lush_caves", "id": 51, "weather": { "precipitation": "rain", @@ -5948,49 +5948,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5999,7 +5999,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -6007,7 +6007,7 @@ ], "axolotls": [ { - "name": "minecraft:axolotl", + "name": "axolotl", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -6015,7 +6015,7 @@ ], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -6024,7 +6024,7 @@ "water_creature": [], "water_ambient": [ { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -6035,7 +6035,7 @@ } }, { - "name": "minecraft:deep_dark", + "name": "deep_dark", "id": 52, "weather": { "precipitation": "rain", @@ -6066,7 +6066,7 @@ } }, { - "name": "minecraft:nether_wastes", + "name": "nether_wastes", "id": 53, "weather": { "precipitation": "none", @@ -6087,31 +6087,31 @@ "groups": { "monster": [ { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 4, "max_group_size": 4, "weight": 50 }, { - "name": "minecraft:zombified_piglin", + "name": "zombified_piglin", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:magma_cube", + "name": "magma_cube", "min_group_size": 4, "max_group_size": 4, "weight": 2 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:piglin", + "name": "piglin", "min_group_size": 4, "max_group_size": 4, "weight": 15 @@ -6119,7 +6119,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6135,7 +6135,7 @@ } }, { - "name": "minecraft:warped_forest", + "name": "warped_forest", "id": 54, "weather": { "precipitation": "none", @@ -6156,7 +6156,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 @@ -6164,7 +6164,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6180,7 +6180,7 @@ } }, { - "name": "minecraft:crimson_forest", + "name": "crimson_forest", "id": 55, "weather": { "precipitation": "none", @@ -6201,19 +6201,19 @@ "groups": { "monster": [ { - "name": "minecraft:zombified_piglin", + "name": "zombified_piglin", "min_group_size": 2, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:hoglin", + "name": "hoglin", "min_group_size": 3, "max_group_size": 4, "weight": 9 }, { - "name": "minecraft:piglin", + "name": "piglin", "min_group_size": 3, "max_group_size": 4, "weight": 5 @@ -6221,7 +6221,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6237,7 +6237,7 @@ } }, { - "name": "minecraft:soul_sand_valley", + "name": "soul_sand_valley", "id": 56, "weather": { "precipitation": "none", @@ -6258,19 +6258,19 @@ "groups": { "monster": [ { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 5, "max_group_size": 5, "weight": 20 }, { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 4, "max_group_size": 4, "weight": 50 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 @@ -6278,7 +6278,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6294,7 +6294,7 @@ } }, { - "name": "minecraft:basalt_deltas", + "name": "basalt_deltas", "id": 57, "weather": { "precipitation": "none", @@ -6315,13 +6315,13 @@ "groups": { "monster": [ { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 1, "max_group_size": 1, "weight": 40 }, { - "name": "minecraft:magma_cube", + "name": "magma_cube", "min_group_size": 2, "max_group_size": 5, "weight": 100 @@ -6329,7 +6329,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6345,7 +6345,7 @@ } }, { - "name": "minecraft:the_end", + "name": "the_end", "id": 58, "weather": { "precipitation": "none", @@ -6366,7 +6366,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6383,7 +6383,7 @@ } }, { - "name": "minecraft:end_highlands", + "name": "end_highlands", "id": 59, "weather": { "precipitation": "none", @@ -6404,7 +6404,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6421,7 +6421,7 @@ } }, { - "name": "minecraft:end_midlands", + "name": "end_midlands", "id": 60, "weather": { "precipitation": "none", @@ -6442,7 +6442,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6459,7 +6459,7 @@ } }, { - "name": "minecraft:small_end_islands", + "name": "small_end_islands", "id": 61, "weather": { "precipitation": "none", @@ -6480,7 +6480,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6497,7 +6497,7 @@ } }, { - "name": "minecraft:end_barrens", + "name": "end_barrens", "id": 62, "weather": { "precipitation": "none", @@ -6518,7 +6518,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index c829dcf0f..0c88b1e98 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -4,9 +4,9 @@ import net.minecraft.entity.SpawnGroup; import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; import rs.valence.extractor.Main; -import java.util.LinkedList; import java.util.Optional; public class Biomes implements Main.Extractor { @@ -14,21 +14,21 @@ public Biomes() { } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private JsonElement optional_to_json(Optional var) { + private static JsonElement optional_to_json(Optional var) { if (var.isEmpty()) { return JsonNull.INSTANCE; } else { var value = var.get(); - if (value instanceof Boolean) { - return new JsonPrimitive((Boolean) value); - } else if (value instanceof Integer) { - return new JsonPrimitive((Integer) value); - } else if (value instanceof Float) { - return new JsonPrimitive((Float) value); - } else if (value instanceof Long) { - return new JsonPrimitive((Long) value); - } else if (value instanceof Number) { - return new JsonPrimitive((Number) value); + if (value instanceof Boolean b) { + return new JsonPrimitive(b); + } else if (value instanceof Integer i) { + return new JsonPrimitive(i); + } else if (value instanceof Float f) { + return new JsonPrimitive(f); + } else if (value instanceof Long l) { + return new JsonPrimitive(l); + } else if (value instanceof Number n) { + return new JsonPrimitive(n); } else { throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); } @@ -42,13 +42,10 @@ public String fileName() { @Override public JsonElement extract() { - var results = new LinkedList(); - for (var biome_key : BuiltinRegistries.BIOME.getKeys()) { - var identifier = biome_key.getValue(); - var biome = BuiltinRegistries.BIOME.get(identifier); - assert biome != null; + var biomesJson = new JsonArray(); - var biomeJson = new JsonObject(); + for (var biome : BuiltinRegistries.BIOME) { + var biomeIdent = BuiltinRegistries.BIOME.getId(biome); var weatherJson = new JsonObject(); weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); @@ -56,55 +53,44 @@ public JsonElement extract() { weatherJson.addProperty("downfall", biome.getDownfall()); var colorJson = new JsonObject(); - var biome_effects = biome.getEffects(); - colorJson.add("grass", optional_to_json(biome_effects.getGrassColor())); - colorJson.addProperty("grass_modifier", biome_effects.getGrassColorModifier().getName()); - colorJson.add("foliage", optional_to_json(biome_effects.getFoliageColor())); - colorJson.addProperty("fog", biome_effects.getFogColor()); - colorJson.addProperty("sky", biome_effects.getSkyColor()); - colorJson.addProperty("water_fog", biome_effects.getWaterFogColor()); - colorJson.addProperty("water", biome_effects.getWaterColor()); + var biomeEffects = biome.getEffects(); + colorJson.add("grass", optional_to_json(biomeEffects.getGrassColor())); + colorJson.addProperty("grass_modifier", biomeEffects.getGrassColorModifier().getName()); + colorJson.add("foliage", optional_to_json(biomeEffects.getFoliageColor())); + colorJson.addProperty("fog", biomeEffects.getFogColor()); + colorJson.addProperty("sky", biomeEffects.getSkyColor()); + colorJson.addProperty("water_fog", biomeEffects.getWaterFogColor()); + colorJson.addProperty("water", biomeEffects.getWaterColor()); var spawnSettingsJson = new JsonObject(); var spawnSettings = biome.getSpawnSettings(); spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); - var spawn_groups = new JsonObject(); - for (var spawn_group : SpawnGroup.values()) { - var spawns_within_group = new JsonArray(); - for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()) { - var within_group = new JsonObject(); - // Depreciated method to get the entity namespace and path. - //noinspection deprecation - within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); - within_group.addProperty("min_group_size", entry.minGroupSize); - within_group.addProperty("max_group_size", entry.maxGroupSize); - within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); - spawns_within_group.add(within_group); + var spawnGroupsJson = new JsonObject(); + for (var spawnGroup : SpawnGroup.values()) { + var spawnGroupJson = new JsonArray(); + for (var entry : spawnSettings.getSpawnEntries(spawnGroup).getEntries()) { + var groupEntryJson = new JsonObject(); + groupEntryJson.addProperty("name", Registry.ENTITY_TYPE.getId(entry.type).getPath()); + groupEntryJson.addProperty("min_group_size", entry.minGroupSize); + groupEntryJson.addProperty("max_group_size", entry.maxGroupSize); + groupEntryJson.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawnGroupJson.add(groupEntryJson); } - spawn_groups.add(spawn_group.asString(), spawns_within_group); + spawnGroupsJson.add(spawnGroup.getName(), spawnGroupJson); } - spawnSettingsJson.add("groups", spawn_groups); + spawnSettingsJson.add("groups", spawnGroupsJson); - biomeJson.addProperty("name", identifier.toString()); + var biomeJson = new JsonObject(); + biomeJson.addProperty("name", biomeIdent.getPath()); biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); biomeJson.add("weather", weatherJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); - results.add(biomeJson); + biomesJson.add(biomeJson); } - results.sort((one, two) -> { - try { - return one.get("id").getAsInt() - two.get("id").getAsInt(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - - var biomesJson = new JsonArray(results.size()); - results.forEach(biomesJson::add); return biomesJson; } } diff --git a/src/biome.rs b/src/biome.rs index 8be59a5be..3923f4051 100644 --- a/src/biome.rs +++ b/src/biome.rs @@ -8,6 +8,16 @@ use valence_nbt::{compound, Compound}; use crate::ident; use crate::ident::Ident; +pub mod default { + //! Contains data for the default Minecraft biomes. + //! + //! All biome variants are located in [`BiomeKind`]. You can use the + //! associated const functions of [`BiomeKind`] to access details about a + //! biome type. + + include!(concat!(env!("OUT_DIR"), "/biome.rs")); +} + /// Identifies a particular [`Biome`] on the server. /// /// The default biome ID refers to the first biome added in the server's diff --git a/src/biomes.rs b/src/biomes.rs deleted file mode 100644 index 96c84504b..000000000 --- a/src/biomes.rs +++ /dev/null @@ -1,5 +0,0 @@ -// biome.rs exposes constant values provided by the build script. -// All biome variants are located in `BiomeKind`. You can use the -// associated const fn functions of `BiomeKind` to access details about a biome -// type. -include!(concat!(env!("OUT_DIR"), "/biome.rs")); diff --git a/src/lib.rs b/src/lib.rs index f07e81b52..c6a142911 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,6 @@ pub use server::start_server; pub use {uuid, valence_nbt as nbt, vek}; pub mod biome; -pub mod biomes; pub mod block; mod block_pos; mod bvh; From f3c12e1908b5cd4ad0cb40c43dd4efa91eaa7a7b Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 24 Oct 2022 21:54:47 +0200 Subject: [PATCH 08/75] Unify extracted biomes with valence --- build/biome.rs | 177 ++++++++---------- extracted/biomes.json | 126 ++++++------- .../valence/extractor/extractors/Biomes.java | 10 +- 3 files changed, 144 insertions(+), 169 deletions(-) diff --git a/build/biome.rs b/build/biome.rs index efaf8c7bf..1845cddb7 100644 --- a/build/biome.rs +++ b/build/biome.rs @@ -11,7 +11,7 @@ use crate::ident; struct ParsedBiome { id: u16, name: String, - weather: ParsedBiomeWeather, + climate: ParsedBiomeClimate, color: ParsedBiomeColor, spawn_settings: ParsedBiomeSpawnRates, } @@ -21,13 +21,13 @@ struct RenamedBiome { id: u16, name: String, rustified_name: Ident, - weather: ParsedBiomeWeather, + climate: ParsedBiomeClimate, color: ParsedBiomeColor, spawn_rates: ParsedBiomeSpawnRates, } #[derive(Deserialize, Debug)] -struct ParsedBiomeWeather { +struct ParsedBiomeClimate { precipitation: String, temperature: f32, downfall: f32, @@ -36,12 +36,12 @@ struct ParsedBiomeWeather { #[derive(Deserialize, Debug)] struct ParsedBiomeColor { grass_modifier: String, - grass: Option, - foliage: Option, - fog: i32, - sky: i32, - water_fog: i32, - water: i32, + grass: Option, + foliage: Option, + fog: u32, + sky: u32, + water_fog: u32, + water: u32, } #[derive(Deserialize, Debug)] @@ -67,7 +67,7 @@ pub fn build() -> anyhow::Result { id: biome.id, rustified_name: ident(&biome.name.replace("minecraft:", "").to_pascal_case()), name: biome.name, - weather: biome.weather, + climate: biome.climate, color: biome.color, spawn_rates: biome.spawn_settings, }) @@ -78,8 +78,8 @@ pub fn build() -> anyhow::Result { let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); for biome in biomes.iter() { precipitation_types - .entry(biome.weather.precipitation.as_str()) - .or_insert_with(|| ident(biome.weather.precipitation.to_pascal_case())); + .entry(biome.climate.precipitation.as_str()) + .or_insert_with(|| ident(biome.climate.precipitation.to_pascal_case())); grass_modifier_types .entry(biome.color.grass_modifier.as_str()) .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); @@ -119,77 +119,69 @@ pub fn build() -> anyhow::Result { }) .collect::(); - let precipitation_names = precipitation_types + let biomekind_name_lookup = biomes .iter() - .map(|(_, rust_id)| { - quote! { - #rust_id, - } - }) - .collect::(); - - let grass_modifier_names = grass_modifier_types - .iter() - .map(|(_, rust_id)| { + .map(|biome| { + let rustified_name = &biome.rustified_name; + let name = &biome.name; quote! { - #rust_id, + #name => Some(Self::#rustified_name), } }) .collect::(); - let biomekind_names = biomes + let biomekind_temperatures_arms = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let name = &biome.name; + let temp = &biome.climate.temperature; quote! { - Self::#rustified_name => #name, + Self::#rustified_name => #temp, } }) .collect::(); - let biomekind_weather = biomes + let biomekind_downfall_arms = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let precipitation = precipitation_types - .get(biome.weather.precipitation.as_str()) - .expect("Could not find previously generated precipitation"); - let downfall = &biome.weather.downfall; - let temperature = &biome.weather.temperature; + let downfall = &biome.climate.downfall; quote! { - Self::#rustified_name => BiomeWeather { - precipitation: Precipitation::#precipitation, - downfall: #downfall, - temperature: #temperature, - }, + Self::#rustified_name => #downfall, } }) .collect::(); - let biomekind_color = biomes + let biomekind_to_biome = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let grass_modifier = grass_modifier_types - .get(biome.color.grass_modifier.as_str()) - .expect("Could not find previously generated grass modifier"); - let grass = option_to_quote(&biome.color.grass); - let foliage = option_to_quote(&biome.color.foliage); - let fog = &biome.color.fog; - let sky = &biome.color.sky; + let name = &biome.name; + let precipitation = ident(&biome.climate.precipitation.to_pascal_case()); + let sky_color = &biome.color.sky; let water_fog = &biome.color.water_fog; - let water = &biome.color.water; + let fog = &biome.color.fog; + let water_color = &biome.color.water; + let foliage_color = option_to_quote(&biome.color.foliage); + let grass_color = option_to_quote(&biome.color.grass); + let grass_modifier = ident(&biome.color.grass_modifier.to_pascal_case()); quote! { - Self::#rustified_name => BiomeColor { - grass_modifier: GrassModifier::#grass_modifier, - grass: #grass, - foliage: #foliage, - fog: #fog, - sky: #sky, - water_fog: #water_fog, - water: #water, - }, + Self::#rustified_name => Ok(Biome{ + name: Ident::from_str(#name)?, + precipitation: BiomePrecipitation::#precipitation, + sky_color: #sky_color, + water_fog_color: #water_fog, + fog_color: #fog, + water_color: #water_color, + foliage_color: #foliage_color, + grass_color: #grass_color, + grass_color_modifier: BiomeGrassColorModifier::#grass_modifier, + music: None, + ambient_sound: None, + additions_sound: None, + mood_sound: None, + particle: None, + }), } }) .collect::(); @@ -207,7 +199,7 @@ pub fn build() -> anyhow::Result { let max_group_size = &spawn_rate.max_group_size; let weight = &spawn_rate.weight; quote! { - SpawnEntry { + SpawnProperty { name: #name, min_group_size: #min_group_size, max_group_size: #max_group_size, @@ -221,7 +213,7 @@ pub fn build() -> anyhow::Result { } }); quote! { - Self::#rustified_name => VanillaBiomeSpawnRates { + Self::#rustified_name => SpawnSettings { probability: #probability, #( #fields ),* }, @@ -232,46 +224,22 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { + use super::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; + use crate::ident::{Ident,IdentError}; + use std::str::FromStr; + #[derive(Debug, Clone, PartialEq, PartialOrd)] - pub struct SpawnEntry { + pub struct SpawnProperty { pub name: &'static str, pub min_group_size: u32, pub max_group_size: u32, pub weight: i32 } - #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] - pub struct BiomeWeather { - pub precipitation: Precipitation, - pub temperature: f32, - pub downfall: f32, - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum Precipitation { - #precipitation_names - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct BiomeColor { - pub grass_modifier: GrassModifier, - pub grass: Option, - pub foliage: Option, - pub fog: i32, - pub sky: i32, - pub water_fog: i32, - pub water: i32, - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum GrassModifier { - #grass_modifier_names - } - #[derive(Debug, Clone, PartialEq, PartialOrd)] - pub struct VanillaBiomeSpawnRates { + pub struct SpawnSettings { pub probability: f32, - #( pub #spawn_classes: &'static [SpawnEntry] ),* + #( pub #spawn_classes: &'static [SpawnProperty] ),* } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -295,31 +263,38 @@ pub fn build() -> anyhow::Result { self as u16 } - /// Returns the biome name with both the namespace and path (eg: minecraft:plains) - pub const fn name(self) -> &'static str { + pub fn from_ident>(ident: &Ident) -> Option { + if ident.namespace() != "minecraft"{ + return None; + } + match ident.path() { + #biomekind_name_lookup + _ => None + } + } + + pub fn biome(self) -> Result> { match self{ - #biomekind_names + #biomekind_to_biome } } - /// Gets the biome weather settings - pub const fn weather(self) -> BiomeWeather { + /// Gets the biome spawn rates + pub const fn spawn_rates(self) -> SpawnSettings { match self{ - #biomekind_weather + #biomekind_spawn_settings_arms } } - /// Gets the biome color settings - pub const fn color(self) -> BiomeColor { + pub const fn temperature(self) -> f32 { match self{ - #biomekind_color + #biomekind_temperatures_arms } } - /// Gets the biome spawn rates - pub const fn spawn_rates(self) -> VanillaBiomeSpawnRates { + pub const fn downfall(self) -> f32 { match self{ - #biomekind_spawn_settings_arms + #biomekind_downfall_arms } } } diff --git a/extracted/biomes.json b/extracted/biomes.json index ae5d543b4..e0571e5d8 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -2,7 +2,7 @@ { "name": "the_void", "id": 0, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -33,7 +33,7 @@ { "name": "plains", "id": 1, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -164,7 +164,7 @@ { "name": "sunflower_plains", "id": 2, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -295,7 +295,7 @@ { "name": "snowy_plains", "id": 3, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -408,7 +408,7 @@ { "name": "ice_spikes", "id": 4, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -521,7 +521,7 @@ { "name": "desert", "id": 5, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -628,7 +628,7 @@ { "name": "swamp", "id": 6, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.9 @@ -759,7 +759,7 @@ { "name": "mangrove_swamp", "id": 7, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.9 @@ -873,7 +873,7 @@ { "name": "forest", "id": 8, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -998,7 +998,7 @@ { "name": "flower_forest", "id": 9, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -1123,7 +1123,7 @@ { "name": "birch_forest", "id": 10, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.6, "downfall": 0.6 @@ -1242,7 +1242,7 @@ { "name": "dark_forest", "id": 11, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -1361,7 +1361,7 @@ { "name": "old_growth_birch_forest", "id": 12, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.6, "downfall": 0.6 @@ -1480,7 +1480,7 @@ { "name": "old_growth_pine_taiga", "id": 13, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.3, "downfall": 0.8 @@ -1617,7 +1617,7 @@ { "name": "old_growth_spruce_taiga", "id": 14, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.25, "downfall": 0.8 @@ -1754,7 +1754,7 @@ { "name": "taiga", "id": 15, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.25, "downfall": 0.8 @@ -1891,7 +1891,7 @@ { "name": "snowy_taiga", "id": 16, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.5, "downfall": 0.4 @@ -2028,7 +2028,7 @@ { "name": "savanna", "id": 17, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2159,7 +2159,7 @@ { "name": "savanna_plateau", "id": 18, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2296,7 +2296,7 @@ { "name": "windswept_hills", "id": 19, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2421,7 +2421,7 @@ { "name": "windswept_gravelly_hills", "id": 20, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2546,7 +2546,7 @@ { "name": "windswept_forest", "id": 21, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2671,7 +2671,7 @@ { "name": "windswept_savanna", "id": 22, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2802,7 +2802,7 @@ { "name": "jungle", "id": 23, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.9 @@ -2945,7 +2945,7 @@ { "name": "sparse_jungle", "id": 24, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.8 @@ -3070,7 +3070,7 @@ { "name": "bamboo_jungle", "id": 25, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.9 @@ -3213,7 +3213,7 @@ { "name": "badlands", "id": 26, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3307,7 +3307,7 @@ { "name": "eroded_badlands", "id": 27, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3401,7 +3401,7 @@ { "name": "wooded_badlands", "id": 28, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3495,7 +3495,7 @@ { "name": "meadow", "id": 29, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.8 @@ -3608,7 +3608,7 @@ { "name": "grove", "id": 30, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.2, "downfall": 0.8 @@ -3745,7 +3745,7 @@ { "name": "snowy_slopes", "id": 31, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.3, "downfall": 0.9 @@ -3852,7 +3852,7 @@ { "name": "frozen_peaks", "id": 32, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.7, "downfall": 0.9 @@ -3953,7 +3953,7 @@ { "name": "jagged_peaks", "id": 33, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.7, "downfall": 0.9 @@ -4054,7 +4054,7 @@ { "name": "stony_peaks", "id": 34, - "weather": { + "climate": { "precipitation": "rain", "temperature": 1.0, "downfall": 0.3 @@ -4148,7 +4148,7 @@ { "name": "river", "id": 35, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4262,7 +4262,7 @@ { "name": "frozen_river", "id": 36, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -4376,7 +4376,7 @@ { "name": "beach", "id": 37, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -4477,7 +4477,7 @@ { "name": "snowy_beach", "id": 38, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.05, "downfall": 0.3 @@ -4571,7 +4571,7 @@ { "name": "stony_shore", "id": 39, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -4665,7 +4665,7 @@ { "name": "warm_ocean", "id": 40, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4791,7 +4791,7 @@ { "name": "lukewarm_ocean", "id": 41, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4923,7 +4923,7 @@ { "name": "deep_lukewarm_ocean", "id": 42, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5055,7 +5055,7 @@ { "name": "ocean", "id": 43, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5175,7 +5175,7 @@ { "name": "deep_ocean", "id": 44, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5295,7 +5295,7 @@ { "name": "cold_ocean", "id": 45, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5415,7 +5415,7 @@ { "name": "deep_cold_ocean", "id": 46, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5535,7 +5535,7 @@ { "name": "frozen_ocean", "id": 47, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -5656,7 +5656,7 @@ { "name": "deep_frozen_ocean", "id": 48, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5777,7 +5777,7 @@ { "name": "mushroom_fields", "id": 49, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.9, "downfall": 1.0 @@ -5829,7 +5829,7 @@ { "name": "dripstone_caves", "id": 50, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -5929,7 +5929,7 @@ { "name": "lush_caves", "id": 51, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -6037,7 +6037,7 @@ { "name": "deep_dark", "id": 52, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -6068,7 +6068,7 @@ { "name": "nether_wastes", "id": 53, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6137,7 +6137,7 @@ { "name": "warped_forest", "id": 54, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6182,7 +6182,7 @@ { "name": "crimson_forest", "id": 55, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6239,7 +6239,7 @@ { "name": "soul_sand_valley", "id": 56, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6296,7 +6296,7 @@ { "name": "basalt_deltas", "id": 57, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6347,7 +6347,7 @@ { "name": "the_end", "id": 58, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6385,7 +6385,7 @@ { "name": "end_highlands", "id": 59, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6423,7 +6423,7 @@ { "name": "end_midlands", "id": 60, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6461,7 +6461,7 @@ { "name": "small_end_islands", "id": 61, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6499,7 +6499,7 @@ { "name": "end_barrens", "id": 62, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index 0c88b1e98..c078e08e2 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -47,10 +47,10 @@ public JsonElement extract() { for (var biome : BuiltinRegistries.BIOME) { var biomeIdent = BuiltinRegistries.BIOME.getId(biome); - var weatherJson = new JsonObject(); - weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); - weatherJson.addProperty("temperature", biome.getTemperature()); - weatherJson.addProperty("downfall", biome.getDownfall()); + var climateJson = new JsonObject(); + climateJson.addProperty("precipitation", biome.getPrecipitation().getName()); + climateJson.addProperty("temperature", biome.getTemperature()); + climateJson.addProperty("downfall", biome.getDownfall()); var colorJson = new JsonObject(); var biomeEffects = biome.getEffects(); @@ -84,7 +84,7 @@ public JsonElement extract() { var biomeJson = new JsonObject(); biomeJson.addProperty("name", biomeIdent.getPath()); biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); - biomeJson.add("weather", weatherJson); + biomeJson.add("climate", climateJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); From 893d51a67cdce345eb7627eeb4f9597c2efe651c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Fri, 28 Oct 2022 21:26:47 +0200 Subject: [PATCH 09/75] Move biomes into valence_anvil crate --- build/main.rs | 2 - src/biome.rs | 10 ---- valence_anvil/Cargo.toml | 14 ++++- {build => valence_anvil/build}/biome.rs | 29 +++++++-- valence_anvil/build/main.rs | 38 ++++++++++++ valence_anvil/examples/java_region.rs | 24 ++++---- valence_anvil/src/biome.rs | 7 +++ valence_anvil/src/lib.rs | 78 +++++++++++++++---------- 8 files changed, 140 insertions(+), 62 deletions(-) rename {build => valence_anvil/build}/biome.rs (91%) create mode 100644 valence_anvil/build/main.rs create mode 100644 valence_anvil/src/biome.rs diff --git a/build/main.rs b/build/main.rs index 89e1d1f80..d098a37ec 100644 --- a/build/main.rs +++ b/build/main.rs @@ -5,7 +5,6 @@ use std::{env, fs}; use anyhow::Context; use proc_macro2::{Ident, Span}; -mod biome; mod block; mod enchant; mod entity; @@ -21,7 +20,6 @@ pub fn main() -> anyhow::Result<()> { (block::build, "block.rs"), (item::build, "item.rs"), (enchant::build, "enchant.rs"), - (biome::build, "biome.rs"), ]; let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?; diff --git a/src/biome.rs b/src/biome.rs index 3923f4051..8be59a5be 100644 --- a/src/biome.rs +++ b/src/biome.rs @@ -8,16 +8,6 @@ use valence_nbt::{compound, Compound}; use crate::ident; use crate::ident::Ident; -pub mod default { - //! Contains data for the default Minecraft biomes. - //! - //! All biome variants are located in [`BiomeKind`]. You can use the - //! associated const functions of [`BiomeKind`] to access details about a - //! biome type. - - include!(concat!(env!("OUT_DIR"), "/biome.rs")); -} - /// Identifies a particular [`Biome`] on the server. /// /// The default biome ID refers to the first biome added in the server's diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 588af4f6e..bcaf9dd97 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -8,13 +8,23 @@ license = "MIT" keywords = ["anvil", "minecraft", "serialization"] version = "0.1.0" authors = ["Ryan Johnson ", "TerminatorNL "] +build = "build/main.rs" edition = "2021" [dependencies] valence = {path = ".."} -valence_nbt = {path = "../valence_nbt"} rayon = "1.5.3" async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} byteorder = "1" tokio = {version = "1", features = ["fs", "io-util", "full"]} -futures = "0.3.24" \ No newline at end of file +futures = "0.3.24" + +[build-dependencies] +anyhow = "1.0.65" +heck = "0.4.0" +proc-macro2 = "1.0.43" +quote = "1.0.21" +serde = { version = "1.0.145", features = ["derive"] } +serde_json = "1.0.85" +rayon = "1.5.3" +num = "0.4.0" \ No newline at end of file diff --git a/build/biome.rs b/valence_anvil/build/biome.rs similarity index 91% rename from build/biome.rs rename to valence_anvil/build/biome.rs index 1845cddb7..4b4443303 100644 --- a/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -59,9 +59,10 @@ struct ParsedSpawnRate { } pub fn build() -> anyhow::Result { - let biomes: Vec = serde_json::from_str(include_str!("../extracted/biomes.json"))?; + let biomes: Vec = + serde_json::from_str(include_str!("../../extracted/biomes.json"))?; - let biomes = biomes + let mut biomes = biomes .into_iter() .map(|biome| RenamedBiome { id: biome.id, @@ -73,6 +74,9 @@ pub fn build() -> anyhow::Result { }) .collect::>(); + //Ensure biomes are sorted, even if the JSON changes later. + biomes.sort_by(|one, two| one.id.cmp(&two.id)); + let mut precipitation_types = BTreeMap::<&str, Ident>::new(); let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); @@ -97,7 +101,7 @@ pub fn build() -> anyhow::Result { } } - let biome_kind_definitions = biomes + let biome_kind_enum_declare = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; @@ -108,6 +112,16 @@ pub fn build() -> anyhow::Result { }) .collect::(); + let biome_kind_enum_names = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + quote! { + #rustified_name + } + }) + .collect::>(); + let biomekind_id_to_variant_lookup = biomes .iter() .map(|biome| { @@ -224,8 +238,8 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { - use super::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; - use crate::ident::{Ident,IdentError}; + use valence::biome::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; + use valence::ident::{Ident,IdentError}; use std::str::FromStr; #[derive(Debug, Clone, PartialEq, PartialOrd)] @@ -244,10 +258,13 @@ pub fn build() -> anyhow::Result { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BiomeKind { - #biome_kind_definitions + #biome_kind_enum_declare } impl BiomeKind { + /// All imported vanilla biomes (All variants of `BiomeKind`) + pub const ALL: &'static [Self] = &[#(Self::#biome_kind_enum_names),*]; + /// Constructs an `BiomeKind` from a raw biome ID. /// /// If the given ID is invalid, `None` is returned. diff --git a/valence_anvil/build/main.rs b/valence_anvil/build/main.rs new file mode 100644 index 000000000..d7200f067 --- /dev/null +++ b/valence_anvil/build/main.rs @@ -0,0 +1,38 @@ +use std::path::Path; +use std::process::Command; +use std::{env, fs}; + +use anyhow::Context; +use proc_macro2::{Ident, Span}; + +mod biome; + +pub fn main() -> anyhow::Result<()> { + println!("cargo:rerun-if-changed=extracted/"); + + let generators = [(biome::build, "biome.rs")]; + + let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?; + + for (g, file_name) in generators { + let path = Path::new(&out_dir).join(file_name); + let code = g()?.to_string(); + fs::write(&path, &code)?; + + // Format the output for debugging purposes. + // Doesn't matter if rustfmt is unavailable. + let _ = Command::new("rustfmt").arg(path).output(); + } + + Ok(()) +} + +fn ident(s: impl AsRef) -> Ident { + let s = s.as_ref().trim(); + + match s.as_bytes() { + // TODO: check for the other rust keywords. + [b'0'..=b'9', ..] | b"type" => Ident::new(&format!("_{s}"), Span::call_site()), + _ => Ident::new(s, Span::call_site()), + } +} diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 25c5edc96..8b759099e 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -6,6 +6,7 @@ use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::async_trait; +use valence::biome::Biome; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::client::{handle_event_default, GameMode}; use valence::config::{Config, ServerListPing}; @@ -15,17 +16,13 @@ use valence::player_list::PlayerListId; use valence::server::{Server, SharedServer, ShutdownResult}; use valence::text::{Color, TextFormat}; use valence::util::chunks_in_view_distance; +use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; pub fn main() -> ShutdownResult { - let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); - - println!("World folder: {:?}", world_folder.canonicalize()); - valence::start_server( Game { player_count: AtomicUsize::new(0), - anvil_world: AnvilWorld::new(world_folder), }, None, ) @@ -33,7 +30,6 @@ pub fn main() -> ShutdownResult { struct Game { player_count: AtomicUsize, - anvil_world: AnvilWorld, } const MAX_PLAYERS: usize = 10; @@ -44,7 +40,7 @@ impl Config for Game { type ServerState = Option; type ClientState = EntityId; type EntityState = (); - type WorldState = (); + type WorldState = AnvilWorld; /// If the chunk should stay loaded at the end of the tick. type ChunkState = bool; type PlayerListState = (); @@ -54,6 +50,10 @@ impl Config for Game { MAX_PLAYERS + 64 } + fn biomes(&self) -> Vec { + BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() + } + async fn server_list_ping( &self, _server: &SharedServer, @@ -74,7 +74,11 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - server.worlds.insert(DimensionId::default(), ()); + let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + server.worlds.insert( + DimensionId::default(), + AnvilWorld::new(world_folder, &server.shared), + ); server.state = Some(server.player_lists.insert(()).0); } @@ -151,7 +155,7 @@ impl Config for Game { } }); - let future = self.anvil_world.load_chunks(new_chunks); + let future = world.state.load_chunks(new_chunks); let parsed_chunks = futures::executor::block_on(future).unwrap(); for (pos, chunk) in parsed_chunks { if let Some(chunk) = chunk { @@ -180,4 +184,4 @@ impl Config for Game { } }); } -} \ No newline at end of file +} diff --git a/valence_anvil/src/biome.rs b/valence_anvil/src/biome.rs new file mode 100644 index 000000000..5d3d19536 --- /dev/null +++ b/valence_anvil/src/biome.rs @@ -0,0 +1,7 @@ +//! This module contains data for the default Minecraft biomes. +//! +//! All biome variants are located in [`BiomeKind`]. You can use the +//! associated const functions of [`BiomeKind`] to access details about a +//! biome type. + +include!(concat!(env!("OUT_DIR"), "/biome.rs")); diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index be47f9469..12ab88859 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -3,7 +3,7 @@ mod palette; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::{SeekFrom}; +use std::io::SeekFrom; use std::path::{Path, PathBuf}; use async_compression::tokio::bufread::ZlibDecoder; @@ -18,19 +18,35 @@ use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; +pub mod biome; + +use valence::config::Config; +use valence::server::SharedServer; + use crate::error::Error; use crate::palette::DataFormat; +pub enum Test { + One, + Two, +} + #[derive(Debug)] pub struct AnvilWorld { world_root: PathBuf, + biomes: BTreeMap, BiomeId>, region_files: Mutex>>>, } impl AnvilWorld { - pub fn new(directory: PathBuf) -> Self { + pub fn new(directory: PathBuf, server: &SharedServer) -> Self { + let mut biomes = BTreeMap::new(); + for (id, biome) in server.biomes() { + biomes.insert(biome.name.clone(), id); + } Self { world_root: directory, + biomes, region_files: Mutex::new(BTreeMap::new()), } } @@ -59,7 +75,7 @@ impl AnvilWorld { } }) { // A region file exists, and it is loaded. - result_vec.extend(region.parse_chunks(chunk_pos_vec).await?); + result_vec.extend(region.parse_chunks(self, chunk_pos_vec).await?); } else { // No region file exists, there is no data to load here. result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); @@ -157,6 +173,7 @@ impl Region { pub async fn parse_chunks>( &self, + world: &AnvilWorld, positions: I, ) -> Result)>, Error> { let mut results = Vec::<(ChunkPos, Option)>::new(); @@ -165,7 +182,7 @@ impl Region { let chunk_data = self.read_chunk_data(pos).await?; if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - let parsed_chunk = Self::parse_chunk_nbt(&mut nbt)?; + let parsed_chunk = Self::parse_chunk_nbt(&mut nbt, world)?; results.push((pos, Some(parsed_chunk))); } else { results.push((pos, None)); @@ -175,10 +192,10 @@ impl Region { Ok(results) } - fn parse_chunk_nbt(nbt: &mut Compound) -> Result { + fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { fn take_assume(compound: &mut Compound, key: &'static str) -> Result - where - Option: From, + where + Option: From, { match compound.remove(key) { None => Err(Error::missing_nbt_value(key)), @@ -193,8 +210,8 @@ impl Region { } fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option - where - Option: From, + where + Option: From, { match compound.remove(key) { None => None, @@ -205,7 +222,7 @@ impl Region { // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; -// + // // let _status: String = take_assume(nbt, "Status")?; // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; @@ -222,7 +239,8 @@ impl Region { } } - // Max should always be equal or higher than 'lower'. Therefore, this is positive. + // Max should always be equal or higher than 'lower'. Therefore, this is + // positive. let section_height = ((y_max - y_min) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; @@ -236,7 +254,7 @@ impl Region { let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; let parsed_block_state_palette: Vec = if let Some(Value::List(List::Compound(nbt_palette_vec))) = - nbt_block_states.remove("palette") + nbt_block_states.remove("palette") { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); @@ -253,14 +271,14 @@ impl Region { }; let mut block_state = BlockState::from_kind(block_kind); if let Some(Value::Compound(nbt_palette_properties)) = - nbt_palette.remove("Properties") + nbt_palette.remove("Properties") { for (property_name, property_value) in nbt_palette_properties { if let Value::String(property_value) = property_value { let property_name = PropName::from_str(&property_name); let property_value = PropValue::from_str(&property_value); if let (Some(property_name), Some(property_value)) = - (property_name, property_value) + (property_name, property_value) { block_state = block_state.set(property_name, property_value); @@ -286,7 +304,7 @@ impl Region { }; // Block state palette - palette::parse_palette::( + palette::parse_palette::( &parsed_block_state_palette, take_assume_optional(&mut nbt_block_states, "data"), 4, @@ -329,22 +347,25 @@ impl Region { let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; let parsed_biome_palette: Vec = if let Some(Value::List(List::String(biome_names))) = - nbt_biomes.remove("palette") + nbt_biomes.remove("palette") { let mut biomes: Vec = Vec::with_capacity(biome_names.len()); for biome in biome_names { - let _identity_IMPLEMENT_ME = Ident::new(biome)?; - - //TODO: EXTRACT BIOME IDs - //TODO: BiomeId::from_str(identity.path()); - biomes.push(BiomeId::default()); + let biome_identity = Ident::new(biome)?; + if let Some(biome) = world.biomes.get(&biome_identity) { + biomes.push(*biome); + } else { + return Err(Error::invalid_nbt( + "sections/*/palette/ Unknown biome", + )); + } } biomes } else { return Err(Error::invalid_nbt("sections/*/palette.")); }; - palette::parse_palette::( + palette::parse_palette::( &parsed_biome_palette, take_assume_optional(&mut nbt_biomes, "data"), 0, @@ -370,12 +391,7 @@ impl Region { let x = index & 0b11; let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); - chunk.set_biome( - x, - final_y as usize, - z, - biome, - ); + chunk.set_biome(x, final_y as usize, z, biome); } } Ok(()) @@ -516,9 +532,7 @@ impl CompressionScheme { decoder.read_to_end(&mut vec).await?; Ok(vec) } - CompressionScheme::Raw => { - Ok(raw_data) - } + CompressionScheme::Raw => Ok(raw_data), } } -} \ No newline at end of file +} From f30e48275b1968923a4f25f36bf61ab5afb0eaea Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 29 Oct 2022 13:56:29 +0200 Subject: [PATCH 10/75] Require position to be within region --- valence_anvil/src/error.rs | 2 +- valence_anvil/src/lib.rs | 43 ++++++++++++++++++++++++++++++------ valence_anvil/src/palette.rs | 10 ++++----- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 1da656e8f..74c7a6645 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -125,4 +125,4 @@ impl Display for SerializeError { fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { write!(f, "Serialization failed") } -} \ No newline at end of file +} diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 12ab88859..2ef68f02f 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -69,7 +69,7 @@ impl AnvilWorld { if let Some(region) = lock.entry(region_pos).or_insert({ let path = region_pos.path(&self.world_root); if path.exists() { - Some(Region::from_file(File::open(&path).await?).await?) + Some(Region::from_file(File::open(&path).await?, region_pos).await?) } else { None } @@ -108,26 +108,36 @@ impl RegionPos { .join("region") .join(format!("r.{}.{}.mca", self.x, self.z)) } + + pub fn contains(self, chunk_pos: ChunkPos) -> bool { + Self::from(chunk_pos) == self + } } #[derive(Debug)] pub struct Region { source: Mutex, offset: u64, + position: RegionPos, header: AnvilHeader, } impl Region { - /// Convenience method, creates a Region object from the given file. - pub async fn from_file(source: File) -> Result { - Self::from_seek(Mutex::new(source), 0).await + /// Convenience method, creates a Region object from the given file and + /// position. + pub async fn from_file(source: File, position: RegionPos) -> Result { + Self::from_seek(Mutex::new(source), 0, position).await } } impl Region { /// Creates a Region object using the incoming stream. The offset defines /// the position of the header start. - pub async fn from_seek(source: Mutex, offset: u64) -> Result { + pub async fn from_seek( + source: Mutex, + offset: u64, + position: RegionPos, + ) -> Result { let mut lock = source.lock().await; lock.seek(SeekFrom::Start(offset)).await?; let header = AnvilHeader::parse(&mut *lock).await?; @@ -136,10 +146,17 @@ impl Region { Ok(Self { source, offset, + position, header, }) } + /// Get the last time the chunk was modified in seconds since epoch. + pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> &ChunkTimestamp { + self.header + .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) + } + async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { let seek_pos = self .header @@ -179,6 +196,13 @@ impl Region { let mut results = Vec::<(ChunkPos, Option)>::new(); for pos in positions.into_iter() { + assert!( + self.position.contains(pos), + "Chunk position {:?} was not found in region {:?}", + pos, + self.position + ); + let chunk_data = self.read_chunk_data(pos).await?; if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; @@ -241,7 +265,7 @@ impl Region { // Max should always be equal or higher than 'lower'. Therefore, this is // positive. - let section_height = ((y_max - y_min) as usize * 16) + 16; + let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; //Parsing sections @@ -477,7 +501,7 @@ impl ChunkLocation { /// The timestamp when the chunk was last modified in seconds since epoch. #[derive(Copy, Clone)] -struct ChunkTimestamp(u32); +pub struct ChunkTimestamp(u32); impl Debug for ChunkTimestamp { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { @@ -493,6 +517,11 @@ impl ChunkTimestamp { fn load(&mut self, chunk: [u8; 4]) { self.0 = BigEndian::read_u32(&chunk) } + + #[inline(always)] + pub fn seconds_since_epoch(&self) -> u32 { + self.0 + } } #[derive(Debug, Copy, Clone)] diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 3113e5fc9..6fe5b051a 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -1,15 +1,13 @@ -use crate::error::Error; use std::ops::BitXor; +use crate::error::Error; + pub enum DataFormat { All(T), Palette(usize, T), } -pub fn parse_palette< - T: Copy, - F: (FnMut(DataFormat) -> Result<(), Error>) ->( +pub fn parse_palette) -> Result<(), Error>)>( source: &Vec, data: Option>, min_bits: usize, @@ -64,4 +62,4 @@ pub fn parse_palette< fun(DataFormat::All(source[0]))?; Ok(()) } -} \ No newline at end of file +} From da673f34b0197b5e8d46cc2dde0dfe2a15766378 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 20:50:57 +0100 Subject: [PATCH 11/75] Refactor everything --- valence_anvil/build/biome.rs | 2 +- valence_anvil/examples/java_region.rs | 21 +- valence_anvil/src/compression.rs | 49 +++ valence_anvil/src/error.rs | 135 +++--- valence_anvil/src/lib.rs | 575 +++++++------------------- valence_anvil/src/palette.rs | 12 +- valence_anvil/src/region.rs | 394 ++++++++++++++++++ 7 files changed, 657 insertions(+), 531 deletions(-) create mode 100644 valence_anvil/src/compression.rs create mode 100644 valence_anvil/src/region.rs diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 4b4443303..3f20c5652 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -242,7 +242,7 @@ pub fn build() -> anyhow::Result { use valence::ident::{Ident,IdentError}; use std::str::FromStr; - #[derive(Debug, Clone, PartialEq, PartialOrd)] + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] pub struct SpawnProperty { pub name: &'static str, pub min_group_size: u32, diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 8b759099e..9b34b7942 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -33,7 +33,12 @@ struct Game { } const MAX_PLAYERS: usize = 10; -const WORLD_FOLDER: &'static str = "./test_data/"; + +/// # IMPORTANT +/// Change the following to the world file you wish to load. +/// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most +/// importantly `region` directories. Only the `region` directory is accessed. +const WORLD_FOLDER: &str = "./test_data/"; #[async_trait] impl Config for Game { @@ -146,16 +151,18 @@ impl Config for Game { let dist = client.view_distance(); let p = client.position(); - let new_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist).filter(|pos| { - if let Some(existing) = world.chunks.get_mut(*pos) { + let required_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); + let mut new_chunks = Vec::new(); + for pos in required_chunks { + if let Some(existing) = world.chunks.get_mut(pos) { existing.state = true; - false } else { - true + new_chunks.push(pos); } - }); + } + + let future = world.state.load_chunks(new_chunks.into_iter()); - let future = world.state.load_chunks(new_chunks); let parsed_chunks = futures::executor::block_on(future).unwrap(); for (pos, chunk) in parsed_chunks { if let Some(chunk) = chunk { diff --git a/valence_anvil/src/compression.rs b/valence_anvil/src/compression.rs new file mode 100644 index 000000000..5393d4abe --- /dev/null +++ b/valence_anvil/src/compression.rs @@ -0,0 +1,49 @@ +use async_compression::tokio::bufread::ZlibDecoder; +use async_compression::tokio::write::GzipDecoder; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; + +use crate::error::{DataFormatError, Error}; + +#[derive(Debug, Copy, Clone)] +pub enum CompressionScheme { + GZip = 1, + Zlib = 2, + Raw = 3, +} + +impl CompressionScheme { + pub(crate) fn from_raw(mode: u8) -> Result { + match mode { + 1 => Ok(Self::GZip), + 2 => Ok(Self::Zlib), + 3 => Ok(Self::Raw), + scheme => Err(Error::DataFormatError( + DataFormatError::UnknownCompressionScheme(scheme), + )), + } + } + + pub(crate) async fn read_to_vec( + self, + source: &mut R, + length: usize, + ) -> Result, std::io::Error> { + let mut raw_data = vec![0u8; length]; + source.read_exact(&mut raw_data).await?; + match self { + CompressionScheme::GZip => { + let mut decoder = GzipDecoder::new(Vec::::new()); + decoder.write_all(&raw_data).await?; + decoder.shutdown().await?; + Ok(decoder.into_inner()) + } + CompressionScheme::Zlib => { + let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); + let mut vec = Vec::::new(); + decoder.read_to_end(&mut vec).await?; + Ok(vec) + } + CompressionScheme::Raw => Ok(raw_data), + } + } +} diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 74c7a6645..a11960bec 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -2,57 +2,36 @@ use std::error::Error as StdError; use std::fmt::{Display, Formatter}; use std::io; -use valence::ident::Ident; +use valence::ident::{Ident, IdentError}; -/// Errors that can occur when encoding or decoding. #[derive(Debug)] -pub struct Error { - /// Box this to keep the size of `Result` small. - cause: Box, +pub enum Error { + Io(io::Error), + DataFormatError(DataFormatError), + NbtParseError(valence::nbt::Error), + NbtFormatError(NbtFormatError), } -impl Error { - pub(crate) fn unknown_compression_scheme(mode: u8) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::UnknownCompressionScheme(mode))), - } - } - - pub(crate) fn invalid_chunk_size(size: usize) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidChunkSize(size))), - } - } - - pub(crate) fn missing_nbt_value(key: &'static str) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::MissingNBT(key))), - } - } - - pub(crate) fn invalid_nbt(message: &'static str) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidNBT(message))), - } - } - - pub(crate) fn invalid_palette() -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidPalette)), - } - } +#[derive(Debug)] +pub enum NbtFormatError { + MissingKey(String), + InvalidType(String), +} - pub(crate) fn unknown_type(ident: Ident) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::UnknownType(ident))), - } - } +#[derive(Debug)] +pub enum DataFormatError { + UnknownCompressionScheme(u8), + InvalidChunkSize(usize), + IdentityError(IdentError), + UnknownType(Ident), + InvalidChunkState(String), + InvalidPalette, } impl StdError for Error { fn source(&self) -> Option<&(dyn StdError + 'static)> { - match &*self.cause { - Cause::Io(e) => Some(e), + match self { + Self::Io(e) => Some(e), _ => None, } } @@ -60,69 +39,55 @@ impl StdError for Error { impl From for Error { fn from(e: io::Error) -> Self { - Self { - cause: Box::new(Cause::Io(e)), - } + Self::Io(e) } } + impl From for Error { fn from(e: valence::nbt::Error) -> Self { - Self { - cause: Box::new(Cause::NBT(e)), - } + Self::NbtParseError(e) } } impl From> for Error { fn from(e: valence::ident::IdentError) -> Self { - Self { - cause: Box::new(Cause::IdentityError(e)), - } + Self::DataFormatError(DataFormatError::IdentityError(e)) } } -#[derive(Debug)] -pub enum Cause { - Io(io::Error), - Parse(ParseError), - NBT(valence::nbt::Error), - IdentityError(valence::ident::IdentError), -} - -#[derive(Debug)] -pub enum ParseError { - UnknownCompressionScheme(u8), - InvalidChunkSize(usize), - MissingNBT(&'static str), - InvalidNBT(&'static str), - InvalidPalette, - UnknownType(Ident), -} - -#[derive(Debug)] -pub enum SerializeError { - // ChunkTooLarge -} - impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match &*self.cause { - Cause::Io(e) => e.fmt(f), - Cause::Parse(err) => err.fmt(f), - Cause::NBT(e) => e.fmt(f), - Cause::IdentityError(e) => e.fmt(f), + match self { + Error::Io(e) => e.fmt(f), + Error::DataFormatError(e) => e.fmt(f), + Error::NbtParseError(e) => e.fmt(f), + Error::NbtFormatError(e) => e.fmt(f), } } } -impl Display for ParseError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { - write!(f, "Parse failed") +impl Display for DataFormatError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + match self { + DataFormatError::UnknownCompressionScheme(scheme) => { + write!(f, "Unknown compression scheme: {scheme}") + } + DataFormatError::InvalidChunkSize(size) => write!(f, "Invalid chunk size: {size}"), + DataFormatError::IdentityError(e) => e.fmt(f), + DataFormatError::UnknownType(identity) => write!(f, "Unknown identity: {identity}"), + DataFormatError::InvalidChunkState(state) => write!(f, "Unknown chunk state: {state}"), + DataFormatError::InvalidPalette => write!(f, "Invalid chunk palette"), + } } } -impl Display for SerializeError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { - write!(f, "Serialization failed") +impl Display for NbtFormatError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + match self { + NbtFormatError::MissingKey(key) => { + write!(f, "Could not find key: \"{key}\" in nbt data.") + } + NbtFormatError::InvalidType(key) => write!(f, "Unexpected type for key: \"{key}\""), + } } } diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 2ef68f02f..234b0738e 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,35 +1,25 @@ -mod error; -mod palette; - use std::collections::BTreeMap; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::SeekFrom; use std::path::{Path, PathBuf}; -use async_compression::tokio::bufread::ZlibDecoder; -use async_compression::tokio::write::GzipDecoder; use byteorder::{BigEndian, ByteOrder}; +use region::Region; use tokio::fs::File; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWriteExt}; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, MutexGuard}; use valence::biome::BiomeId; -use valence::block::{BlockKind, BlockState, PropName, PropValue}; -use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::ident::Ident; -use valence::nbt::{Compound, List, Value}; - -pub mod biome; - +use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; +use valence::ident::Ident; use valence::server::SharedServer; use crate::error::Error; -use crate::palette::DataFormat; -pub enum Test { - One, - Two, -} +pub mod error; +pub mod biome; +pub mod compression; + +mod palette; +mod region; #[derive(Debug)] pub struct AnvilWorld { @@ -39,6 +29,31 @@ pub struct AnvilWorld { } impl AnvilWorld { + //noinspection ALL + /// Creates an `AnvilWorld` instance. + /// + /// # Arguments + /// + /// * `directory`: A path to the world folder. Inside this folder you should + /// see the `region` directory. + /// * `server`: The shared server. This is used to initialize which biomes + /// to use. + /// + /// returns: AnvilWorld + /// + /// # Examples + /// + /// ``` + /// impl Config for Game { + /// fn init(&self, server: &mut Server) { + /// let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + /// server.worlds.insert( + /// DimensionId::default(), + /// AnvilWorld::new(world_folder, &server.shared), + /// ); + /// } + /// } + /// ``` pub fn new(directory: PathBuf, server: &SharedServer) -> Self { let mut biomes = BTreeMap::new(); for (id, biome) in server.biomes() { @@ -51,29 +66,57 @@ impl AnvilWorld { } } - pub async fn load_chunks>( + //noinspection ALL + /// Load chunks from the available region files within the world directory. + /// This operation will temporarily block operations on all region files + /// within `AnvilWorld`. + /// + /// # Arguments + /// + /// * `positions`: Any iterator of `valence::chunk_pos::ChunkPos` + /// + /// returns: An iterator of the requested chunk positions and their + /// associated chunks + /// + /// # Examples + /// + /// ``` + /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); + /// let future = world.state.load_chunks(to_load); + /// let parsed_chunks = futures::executor::block_on(future).unwrap(); + /// for (pos, chunk) in parsed_chunks { + /// if let Some(chunk) = chunk { + /// // A chunk has successfully loaded from the region file. + /// world.chunks.insert(pos, chunk, true); + /// } else { + /// // There is no information on this chunk in the region file. + /// let mut blank_chunk = UnloadedChunk::new(16); + /// blank_chunk.set_block_state( + /// 0, + /// 0, + /// 0, + /// valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + /// ); + /// world.chunks.insert(pos, blank_chunk, true); + /// } + /// } + /// ``` + pub async fn load_chunks>( &self, positions: I, - ) -> Result)>, Error> { + ) -> Result)>, Error> { let mut map = BTreeMap::>::new(); - for pos in positions.into_iter() { + for pos in positions { let region_pos = RegionPos::from(pos); map.entry(region_pos) .and_modify(|v| v.push(pos)) - .or_insert(vec![pos]); + .or_insert_with(|| vec![pos]); } let mut result_vec = Vec::<(ChunkPos, Option)>::new(); let mut lock = self.region_files.lock().await; for (region_pos, chunk_pos_vec) in map.into_iter() { - if let Some(region) = lock.entry(region_pos).or_insert({ - let path = region_pos.path(&self.world_root); - if path.exists() { - Some(Region::from_file(File::open(&path).await?, region_pos).await?) - } else { - None - } - }) { + if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { // A region file exists, and it is loaded. result_vec.extend(region.parse_chunks(self, chunk_pos_vec).await?); } else { @@ -82,7 +125,63 @@ impl AnvilWorld { } } - Ok(result_vec) + Ok(result_vec.into_iter()) + } + + /// Get the last time the chunk was modified in seconds since epoch. + /// This operation will temporarily block operations on all region files + /// within `AnvilWorld`. + /// + /// # Arguments + /// + /// * `positions`: An iterator of chunk positions + /// + /// returns: An iterator with `ChunkPos` and the respective + /// `Option` as tuple. + pub async fn chunk_timestamps>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut map = BTreeMap::>::new(); + for pos in positions { + let region_pos = RegionPos::from(pos); + map.entry(region_pos) + .and_modify(|v| v.push(pos)) + .or_insert_with(|| vec![pos]); + } + + let mut result_vec = Vec::<(ChunkPos, Option)>::new(); + let mut lock = self.region_files.lock().await; + for (region_pos, chunk_pos_vec) in map.into_iter() { + if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { + for chunk_pos in chunk_pos_vec { + result_vec.push((chunk_pos, region.chunk_timestamp(chunk_pos))); + } + } else { + for chunk_pos in chunk_pos_vec { + result_vec.push((chunk_pos, None)); + } + } + } + Ok(result_vec.into_iter()) + } + + async fn access_region_mut<'a>( + &self, + lock: &'a mut MutexGuard<'_, BTreeMap>>>, + region_pos: RegionPos, + ) -> Result>, Error> { + Ok(lock + .entry(region_pos) + .or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path).await?, region_pos).await?) + } else { + None + } + }) + .as_mut()) } } @@ -114,370 +213,14 @@ impl RegionPos { } } -#[derive(Debug)] -pub struct Region { - source: Mutex, - offset: u64, - position: RegionPos, - header: AnvilHeader, -} - -impl Region { - /// Convenience method, creates a Region object from the given file and - /// position. - pub async fn from_file(source: File, position: RegionPos) -> Result { - Self::from_seek(Mutex::new(source), 0, position).await - } -} - -impl Region { - /// Creates a Region object using the incoming stream. The offset defines - /// the position of the header start. - pub async fn from_seek( - source: Mutex, - offset: u64, - position: RegionPos, - ) -> Result { - let mut lock = source.lock().await; - lock.seek(SeekFrom::Start(offset)).await?; - let header = AnvilHeader::parse(&mut *lock).await?; - drop(lock); - - Ok(Self { - source, - offset, - position, - header, - }) - } - - /// Get the last time the chunk was modified in seconds since epoch. - pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> &ChunkTimestamp { - self.header - .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) - } - - async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { - let seek_pos = self - .header - .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); - - let mut lock = self.source.lock().await; - - lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) - .await?; - - if seek_pos.len() == 0 { - return Ok(None); - } - - let compressed_chunk_size = { - let mut buf = [0u8; 4]; - lock.read_exact(&mut buf).await?; - BigEndian::read_u32(&buf) as usize - }; - - if compressed_chunk_size == 0 { - return Err(Error::invalid_chunk_size(compressed_chunk_size)); - } - - let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; - let uncompressed_buffer = compression - .read_to_vec(&mut *lock, compressed_chunk_size - 1) - .await?; - Ok(Some(uncompressed_buffer)) - } - - pub async fn parse_chunks>( - &self, - world: &AnvilWorld, - positions: I, - ) -> Result)>, Error> { - let mut results = Vec::<(ChunkPos, Option)>::new(); - - for pos in positions.into_iter() { - assert!( - self.position.contains(pos), - "Chunk position {:?} was not found in region {:?}", - pos, - self.position - ); - - let chunk_data = self.read_chunk_data(pos).await?; - if let Some(chunk_data) = chunk_data { - let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - let parsed_chunk = Self::parse_chunk_nbt(&mut nbt, world)?; - results.push((pos, Some(parsed_chunk))); - } else { - results.push((pos, None)); - } - } - - Ok(results) - } - - fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { - fn take_assume(compound: &mut Compound, key: &'static str) -> Result - where - Option: From, - { - match compound.remove(key) { - None => Err(Error::missing_nbt_value(key)), - Some(value) => { - if let Some(value) = Option::::from(value) { - Ok(value) - } else { - Err(Error::invalid_nbt(key)) - } - } - } - } - - fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option - where - Option: From, - { - match compound.remove(key) { - None => None, - Some(value) => Option::::from(value), - } - } - - // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; - // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; - // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; - // - // let _status: String = take_assume(nbt, "Status")?; - // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; - - if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { - let mut y_max = 0i8; - let mut y_min = 0i8; - - for chunk_nbt in nbt_sections.iter() { - if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { - y_max = y_max.max(*section_y); - y_min = y_min.min(*section_y); - } else { - return Err(Error::missing_nbt_value("sections/*/Y")); - } - } - - // Max should always be equal or higher than 'lower'. Therefore, this is - // positive. - let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; - let y_raise = isize::from(-y_min) * 16; - - //Parsing sections - let mut chunk = UnloadedChunk::new(section_height); - for mut nbt_section in nbt_sections.into_iter() { - let chunk_y_offset: isize = - isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; - - // Block states - let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; - let parsed_block_state_palette: Vec = - if let Some(Value::List(List::Compound(nbt_palette_vec))) = - nbt_block_states.remove("palette") - { - let mut palette_vec: Vec = - Vec::with_capacity(nbt_palette_vec.len()); - for mut nbt_palette in nbt_palette_vec { - let block_id = valence::ident::Ident::new(take_assume::( - &mut nbt_palette, - "Name", - )?)?; - let block_kind = - if let Some(block_kind) = BlockKind::from_str(block_id.path()) { - block_kind - } else { - return Err(Error::unknown_type(block_id)); - }; - let mut block_state = BlockState::from_kind(block_kind); - if let Some(Value::Compound(nbt_palette_properties)) = - nbt_palette.remove("Properties") - { - for (property_name, property_value) in nbt_palette_properties { - if let Value::String(property_value) = property_value { - let property_name = PropName::from_str(&property_name); - let property_value = PropValue::from_str(&property_value); - if let (Some(property_name), Some(property_value)) = - (property_name, property_value) - { - block_state = - block_state.set(property_name, property_value); - } else { - return Err(Error::invalid_nbt( - "sections/*/block_states/Properties/*/property \ - value is not recognized.", - )); - } - } else { - return Err(Error::invalid_nbt( - "sections/*/block_states/Properties/*/property value \ - is invalid.", - )); - } - } - } - palette_vec.push(block_state); - } - palette_vec - } else { - return Err(Error::invalid_nbt("sections/*/palette")); - }; - - // Block state palette - palette::parse_palette::( - &parsed_block_state_palette, - take_assume_optional(&mut nbt_block_states, "data"), - 4, - &mut |data| { - match data { - DataFormat::All(state) => { - if !state.is_air() { - for x in 0..16 { - for y in 0..16isize { - for z in 0..16 { - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - } - } - } - DataFormat::Palette(index, state) => { - let y = (index >> 8 & 0b1111) as isize; - let z = index >> 4 & 0b1111; - let x = index & 0b1111; - - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - Ok(()) - }, - )?; - - // Biome palette - let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; - let parsed_biome_palette: Vec = - if let Some(Value::List(List::String(biome_names))) = - nbt_biomes.remove("palette") - { - let mut biomes: Vec = Vec::with_capacity(biome_names.len()); - for biome in biome_names { - let biome_identity = Ident::new(biome)?; - if let Some(biome) = world.biomes.get(&biome_identity) { - biomes.push(*biome); - } else { - return Err(Error::invalid_nbt( - "sections/*/palette/ Unknown biome", - )); - } - } - biomes - } else { - return Err(Error::invalid_nbt("sections/*/palette.")); - }; - - palette::parse_palette::( - &parsed_biome_palette, - take_assume_optional(&mut nbt_biomes, "data"), - 0, - &mut |data| { - match data { - DataFormat::All(biome) => { - for x in 0..4 { - for y in 0..4isize { - for z in 0..4 { - chunk.set_biome( - x, - (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, - z, - biome, - ); - } - } - } - } - DataFormat::Palette(index, biome) => { - let y = (index >> 4 & 0b11) as isize; - let z = index >> 2 & 0b11; - let x = index & 0b11; - - let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); - chunk.set_biome(x, final_y as usize, z, biome); - } - } - Ok(()) - }, - )?; - } - - //sections - - Ok(chunk) - } else { - return Err(Error::invalid_nbt("sections tag invalid.")); - } - } -} - -#[derive(Copy, Clone, Debug)] -struct AnvilHeader { - offsets: [ChunkLocation; 1024], - timestamps: [ChunkTimestamp; 1024], -} - -impl AnvilHeader { - /// Parses the header bytes from the current position - async fn parse(source: &mut R) -> Result { - let mut offsets = [ChunkLocation::zero(); 1024]; - for offset in &mut offsets { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; - offset.load(buf); - } - let mut timestamps = [ChunkTimestamp::zero(); 1024]; - for timestamp in &mut timestamps { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; - timestamp.load(buf); - } - Ok(Self { - offsets, - timestamps, - }) - } - - #[inline(always)] - fn offset(&self, x: usize, z: usize) -> &ChunkLocation { - &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] - } - - #[inline(always)] - fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { - &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] - } -} - /// The location of the chunk inside the region file. #[derive(Copy, Clone, Debug)] -struct ChunkLocation { +struct ChunkSeekLocation { offset_sectors: u32, len_sectors: u8, } -impl ChunkLocation { +impl ChunkSeekLocation { const fn zero() -> Self { Self { offset_sectors: 0, @@ -518,50 +261,16 @@ impl ChunkTimestamp { self.0 = BigEndian::read_u32(&chunk) } - #[inline(always)] - pub fn seconds_since_epoch(&self) -> u32 { - self.0 - } -} - -#[derive(Debug, Copy, Clone)] -enum CompressionScheme { - GZip = 1, - Zlib = 2, - Raw = 3, -} - -impl CompressionScheme { - fn from_raw(mode: u8) -> Result { - match mode { - 1 => Ok(Self::GZip), - 2 => Ok(Self::Zlib), - 3 => Ok(Self::Raw), - mode => Err(Error::unknown_compression_scheme(mode)), + fn into_option(self) -> Option { + if self.0 == 0 { + None + } else { + Some(self) } } - async fn read_to_vec( - self, - source: &mut R, - length: usize, - ) -> Result, std::io::Error> { - let mut raw_data = vec![0u8; length]; - source.read_exact(&mut raw_data).await?; - match self { - CompressionScheme::GZip => { - let mut decoder = GzipDecoder::new(Vec::::new()); - decoder.write_all(&mut raw_data).await?; - decoder.shutdown().await?; - Ok(decoder.into_inner()) - } - CompressionScheme::Zlib => { - let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); - let mut vec = Vec::::new(); - decoder.read_to_end(&mut vec).await?; - Ok(vec) - } - CompressionScheme::Raw => Ok(raw_data), - } + #[inline(always)] + pub fn seconds_since_epoch(self) -> u32 { + self.0 } } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 6fe5b051a..65d8ffcc7 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -1,6 +1,6 @@ use std::ops::BitXor; -use crate::error::Error; +use crate::error::{DataFormatError, Error}; pub enum DataFormat { All(T), @@ -28,9 +28,9 @@ pub fn parse_palette) -> Result<(), Error>)>( let mut entry_mask = (u64::MAX << bits_per_index).bitxor(u64::MAX); let mut mask_fields: Vec<(u64, usize)> = vec![(0u64, 0usize); entries_per_integer]; - for i in 0..mask_fields.len() { - mask_fields[i] = (entry_mask, (i * bits_per_index)); - entry_mask = entry_mask << bits_per_index; + for (i, mask_field) in mask_fields.iter_mut().enumerate() { + *mask_field = (entry_mask, (i * bits_per_index)); + entry_mask <<= bits_per_index; } let mut index: usize = 0; @@ -49,7 +49,9 @@ pub fn parse_palette) -> Result<(), Error>)>( //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", // palette_index_shifted, choice_len, // bits_per_index, source, source.len()); - return Err(crate::error::Error::invalid_palette()); + return Err(crate::error::Error::DataFormatError( + DataFormatError::InvalidPalette, + )); } else { fun(DataFormat::Palette(index, source[palette_index_shifted]))?; index += 1; diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs new file mode 100644 index 000000000..6d9e48576 --- /dev/null +++ b/valence_anvil/src/region.rs @@ -0,0 +1,394 @@ +use std::io::SeekFrom; + +use byteorder::{BigEndian, ByteOrder}; +use tokio::fs::File; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; +use tokio::sync::Mutex; +use valence::biome::BiomeId; +use valence::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::ident::Ident; +use valence::nbt::{Compound, List, Value}; + +use crate::compression::CompressionScheme; +use crate::error::{DataFormatError, Error, NbtFormatError}; +use crate::palette::DataFormat; +use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; + +#[derive(Debug)] +pub struct Region { + source: Mutex, + offset: u64, + position: RegionPos, + header: AnvilHeader, +} + +impl Region { + /// Convenience method, creates a Region object from the given file and + /// position. + pub async fn from_file(source: File, position: RegionPos) -> Result { + Self::from_seek(Mutex::new(source), 0, position).await + } +} + +impl Region { + /// Creates a Region object using the incoming stream. The offset defines + /// the position of the header start. + pub async fn from_seek( + source: Mutex, + offset: u64, + position: RegionPos, + ) -> Result { + let mut lock = source.lock().await; + lock.seek(SeekFrom::Start(offset)).await?; + let header = AnvilHeader::parse(&mut *lock).await?; + drop(lock); + + Ok(Self { + source, + offset, + position, + header, + }) + } + + /// Get the last time the chunk was modified in seconds since epoch. + pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> Option { + self.header + .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) + .into_option() + } + + async fn read_chunk_bytes(&self, chunk_pos: ChunkPos) -> Result>, Error> { + let seek_pos = self + .header + .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); + + let mut lock = self.source.lock().await; + + lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) + .await?; + + if seek_pos.len() == 0 { + return Ok(None); + } + + let compressed_chunk_size = { + let mut buf = [0u8; 4]; + lock.read_exact(&mut buf).await?; + BigEndian::read_u32(&buf) as usize + }; + + if compressed_chunk_size == 0 { + return Err(Error::DataFormatError(DataFormatError::InvalidChunkSize( + compressed_chunk_size, + ))); + } + + let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; + let uncompressed_buffer = compression + .read_to_vec(&mut *lock, compressed_chunk_size - 1) + .await?; + Ok(Some(uncompressed_buffer)) + } + + pub(crate) async fn parse_chunks>( + &self, + world: &AnvilWorld, + positions: I, + ) -> Result)>, Error> { + let mut results = Vec::<(ChunkPos, Option)>::new(); + + for pos in positions.into_iter() { + assert!( + self.position.contains(pos), + "Chunk position {:?} was not found in region {:?}", + pos, + self.position + ); + + let chunk_data = self.read_chunk_bytes(pos).await?; + if let Some(chunk_data) = chunk_data { + let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; + match Self::parse_chunk_nbt(&mut nbt, world) { + Err(Error::NbtParseError(_)) => { + results.push((pos, None)); + } + Err(e) => return Err(e), + Ok(parsed_chunk) => { + results.push((pos, Some(parsed_chunk))); + } + } + } else { + results.push((pos, None)); + } + } + + Ok(results.into_iter()) + } + + //TODO: This function is very large and should be separated into dedicated + // functions at some point. + fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { + fn take_assume(compound: &mut Compound, key: &'static str) -> Result + where + Option: From, + { + match compound.remove(key) { + None => Err(Error::NbtFormatError(NbtFormatError::MissingKey( + key.to_string(), + ))), + Some(value) => { + if let Some(value) = Option::::from(value) { + Ok(value) + } else { + Err(Error::NbtFormatError(NbtFormatError::InvalidType( + key.to_string(), + ))) + } + } + } + } + + fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option + where + Option: From, + { + match compound.remove(key) { + None => None, + Some(value) => Option::::from(value), + } + } + + let status: String = take_assume(nbt, "Status")?; + if status.as_str() != "full" { + return Err(Error::DataFormatError(DataFormatError::InvalidChunkState( + status, + ))); + } + + if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { + let mut y_max = 0i8; + let mut y_min = 0i8; + + for chunk_nbt in nbt_sections.iter() { + if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { + y_max = y_max.max(*section_y); + y_min = y_min.min(*section_y); + } else { + return Err(Error::NbtFormatError(NbtFormatError::MissingKey( + "Y".to_string(), + ))); + } + } + + // `y_max` should always be equal or higher than `y_min`. Therefore, + // section_height is positive. + let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; + let y_raise = isize::from(-y_min) * 16; + + //Parsing sections + let mut chunk = UnloadedChunk::new(section_height); + for mut nbt_section in nbt_sections.into_iter() { + let chunk_y_offset: isize = + isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; + + // Block states + let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; + let parsed_block_state_palette: Vec = + if let Some(Value::List(List::Compound(nbt_palette_vec))) = + nbt_block_states.remove("palette") + { + let mut palette_vec: Vec = + Vec::with_capacity(nbt_palette_vec.len()); + for mut nbt_palette in nbt_palette_vec { + let block_id = valence::ident::Ident::new(take_assume::( + &mut nbt_palette, + "Name", + )?)?; + let block_kind = + if let Some(block_kind) = BlockKind::from_str(block_id.path()) { + block_kind + } else { + return Err(Error::DataFormatError( + DataFormatError::UnknownType(block_id), + )); + }; + let mut block_state = BlockState::from_kind(block_kind); + if let Some(Value::Compound(nbt_palette_properties)) = + nbt_palette.remove("Properties") + { + for (property_name_raw, property_value) in nbt_palette_properties { + if let Value::String(property_value) = property_value { + let property_name = PropName::from_str(&property_name_raw); + let property_value = PropValue::from_str(&property_value); + if let (Some(property_name), Some(property_value)) = + (property_name, property_value) + { + block_state = + block_state.set(property_name, property_value); + } else { + return Err(Error::NbtFormatError( + NbtFormatError::MissingKey(property_name_raw), + )); + } + } else { + return Err(Error::NbtFormatError( + NbtFormatError::InvalidType(property_name_raw), + )); + } + } + } + palette_vec.push(block_state); + } + palette_vec + } else { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "palette".to_string(), + ))); + }; + + // Block state palette + palette::parse_palette::( + &parsed_block_state_palette, + take_assume_optional(&mut nbt_block_states, "data"), + 4, + &mut |data| { + match data { + DataFormat::All(state) => { + if !state.is_air() { + for x in 0..16 { + for y in 0..16isize { + for z in 0..16 { + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + } + } + } + DataFormat::Palette(index, state) => { + let y = (index >> 8 & 0b1111) as isize; + let z = index >> 4 & 0b1111; + let x = index & 0b1111; + + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + Ok(()) + }, + )?; + + // Biome palette + let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; + let parsed_biome_palette: Vec = + if let Some(Value::List(List::String(biome_names))) = + nbt_biomes.remove("palette") + { + let mut biomes: Vec = Vec::with_capacity(biome_names.len()); + for biome in biome_names { + let biome_identity = Ident::new(biome)?; + if let Some(biome) = world.biomes.get(&biome_identity) { + biomes.push(*biome); + } else { + return Err(Error::DataFormatError(DataFormatError::UnknownType( + biome_identity, + ))); + } + } + biomes + } else { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "palette".to_string(), + ))); + }; + + palette::parse_palette::( + &parsed_biome_palette, + take_assume_optional(&mut nbt_biomes, "data"), + 0, + &mut |data| { + match data { + DataFormat::All(biome) => { + for x in 0..4 { + for y in 0..4isize { + for z in 0..4 { + chunk.set_biome( + x, + (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, + z, + biome, + ); + } + } + } + } + DataFormat::Palette(index, biome) => { + let y = (index >> 4 & 0b11) as isize; + let z = index >> 2 & 0b11; + let x = index & 0b11; + + let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); + chunk.set_biome(x, final_y as usize, z, biome); + } + } + Ok(()) + }, + )?; + } + + Ok(chunk) + } else { + Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "sections".to_string(), + ))) + } + } +} + +#[derive(Copy, Clone, Debug)] +struct AnvilHeader { + offsets: [ChunkSeekLocation; 1024], + timestamps: [ChunkTimestamp; 1024], +} + +impl AnvilHeader { + /// Parses the header bytes from the current position + async fn parse(source: &mut R) -> Result { + let mut offsets = [ChunkSeekLocation::zero(); 1024]; + for offset in &mut offsets { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + offset.load(buf); + } + let mut timestamps = [ChunkTimestamp::zero(); 1024]; + for timestamp in &mut timestamps { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + timestamp.load(buf); + } + Ok(Self { + offsets, + timestamps, + }) + } + + #[inline(always)] + fn offset(&self, x: usize, z: usize) -> &ChunkSeekLocation { + &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] + } + + #[inline(always)] + fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { + &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] + } +} From d1ab1b90715f32bea8a45460d89d9cd7c23ceecc Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 21:06:33 +0100 Subject: [PATCH 12/75] Fix remnant of Result refactor --- valence_anvil/src/region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 6d9e48576..d1d28d656 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -111,7 +111,7 @@ impl Region { if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; match Self::parse_chunk_nbt(&mut nbt, world) { - Err(Error::NbtParseError(_)) => { + Err(Error::DataFormatError(DataFormatError::InvalidChunkState(..))) => { results.push((pos, None)); } Err(e) => return Err(e), From 6334a43bf6d3491a9e2b18f9a9d10913b7690b26 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 21:07:50 +0100 Subject: [PATCH 13/75] Update message at log-in --- valence_anvil/examples/java_region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 9b34b7942..229fef801 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -131,7 +131,7 @@ impl Config for Game { ); } - client.send_message("Welcome to the terrain example!".italic()); + client.send_message("Welcome to the java chunk parsing example!".italic()); } if client.is_disconnected() { From 6a2bec7245eb304be2fe2ed5f9962e0d26a52eef Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 23:20:14 +0100 Subject: [PATCH 14/75] Cargo fmt --- valence_anvil/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 234b0738e..9c3f1eb2d 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -14,9 +14,9 @@ use valence::server::SharedServer; use crate::error::Error; -pub mod error; pub mod biome; pub mod compression; +pub mod error; mod palette; mod region; From 146e319e4adc04a7bade68b63826e8646e78ce3c Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 30 Oct 2022 23:26:47 +0100 Subject: [PATCH 15/75] Bump valence_nbt version --- Cargo.toml | 2 +- valence_nbt/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed7b617d6..5ed34274b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ sha2 = "0.10.6" thiserror = "1.0.35" url = { version = "2.2.2", features = ["serde"] } uuid = { version = "1.1.2", features = ["serde"] } -valence_nbt = {path = "valence_nbt"} +valence_nbt = "0.4.0" vek = "0.15.8" [dependencies.tokio] diff --git a/valence_nbt/Cargo.toml b/valence_nbt/Cargo.toml index 9db85c775..2c9455724 100644 --- a/valence_nbt/Cargo.toml +++ b/valence_nbt/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/valence-rs/valence/tree/main/valence_nbt" readme = "README.md" license = "MIT" keywords = ["nbt", "minecraft", "serialization"] -version = "0.3.0" +version = "0.4.0" authors = ["Ryan Johnson "] edition = "2021" From 84c79085b8cdeea0edb5fac31c652aff50317496 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 23:46:41 +0100 Subject: [PATCH 16/75] Define valence version --- valence_anvil/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index bcaf9dd97..d69bc80fb 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -12,7 +12,7 @@ build = "build/main.rs" edition = "2021" [dependencies] -valence = {path = ".."} +valence = {version = "0.1.0+mc1.19.2", path = ".."} rayon = "1.5.3" async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} byteorder = "1" From b1382e2fdf3e587e0805c57337be8fc9048cbac2 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 3 Nov 2022 01:30:15 -0700 Subject: [PATCH 17/75] Syntax tweaks --- Cargo.toml | 2 +- valence_anvil/Cargo.toml | 10 +++++----- valence_anvil/build/biome.rs | 10 +++++----- valence_anvil/examples/java_region.rs | 20 +++----------------- valence_anvil/src/error.rs | 12 ++++++------ valence_anvil/src/lib.rs | 11 ++++------- valence_anvil/src/region.rs | 6 +++--- 7 files changed, 27 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a22aee99b..35931f667 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ valence_nbt = "0.4.0" vek = "0.15.8" [dependencies.tokio] -version = "1.21.1" +version = "1.21.2" features = ["macros", "rt-multi-thread", "net", "io-util", "sync", "time"] [dependencies.reqwest] diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index d69bc80fb..ebb735fc7 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -12,11 +12,11 @@ build = "build/main.rs" edition = "2021" [dependencies] -valence = {version = "0.1.0+mc1.19.2", path = ".."} +valence = { version = "0.1.0", path = ".." } rayon = "1.5.3" -async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} -byteorder = "1" -tokio = {version = "1", features = ["fs", "io-util", "full"]} +async-compression = { version = "0.3.15", features = ["tokio", "gzip", "zlib"] } +byteorder = "1.4.3" +tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" [build-dependencies] @@ -27,4 +27,4 @@ quote = "1.0.21" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.85" rayon = "1.5.3" -num = "0.4.0" \ No newline at end of file +num = "0.4.0" diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 3f20c5652..268d5a77b 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -281,7 +281,7 @@ pub fn build() -> anyhow::Result { } pub fn from_ident>(ident: &Ident) -> Option { - if ident.namespace() != "minecraft"{ + if ident.namespace() != "minecraft" { return None; } match ident.path() { @@ -291,26 +291,26 @@ pub fn build() -> anyhow::Result { } pub fn biome(self) -> Result> { - match self{ + match self { #biomekind_to_biome } } /// Gets the biome spawn rates pub const fn spawn_rates(self) -> SpawnSettings { - match self{ + match self { #biomekind_spawn_settings_arms } } pub const fn temperature(self) -> f32 { - match self{ + match self { #biomekind_temperatures_arms } } pub const fn downfall(self) -> f32 { - match self{ + match self { #biomekind_downfall_arms } } diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 229fef801..ec629c841 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -5,17 +5,7 @@ use std::path::PathBuf; use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; -use valence::async_trait; -use valence::biome::Biome; -use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::client::{handle_event_default, GameMode}; -use valence::config::{Config, ServerListPing}; -use valence::dimension::DimensionId; -use valence::entity::{EntityId, EntityKind}; -use valence::player_list::PlayerListId; -use valence::server::{Server, SharedServer, ShutdownResult}; -use valence::text::{Color, TextFormat}; -use valence::util::chunks_in_view_distance; +use valence::prelude::*; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; @@ -35,6 +25,7 @@ struct Game { const MAX_PLAYERS: usize = 10; /// # IMPORTANT +/// /// Change the following to the world file you wish to load. /// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most /// importantly `region` directories. Only the `region` directory is accessed. @@ -50,11 +41,6 @@ impl Config for Game { type ChunkState = bool; type PlayerListState = (); - fn max_connections(&self) -> usize { - // We want status pings to be successful even if the server is full. - MAX_PLAYERS + 64 - } - fn biomes(&self) -> Vec { BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() } @@ -173,7 +159,7 @@ impl Config for Game { 0, 0, 0, - valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + BlockState::from_kind(BlockKind::Lava), ); world.chunks.insert(pos, blank_chunk, true); } diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index a11960bec..c2c180da2 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,6 +1,6 @@ use std::error::Error as StdError; use std::fmt::{Display, Formatter}; -use std::io; +use std::{fmt, io}; use valence::ident::{Ident, IdentError}; @@ -49,14 +49,14 @@ impl From for Error { } } -impl From> for Error { - fn from(e: valence::ident::IdentError) -> Self { +impl From> for Error { + fn from(e: IdentError) -> Self { Self::DataFormatError(DataFormatError::IdentityError(e)) } } impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Error::Io(e) => e.fmt(f), Error::DataFormatError(e) => e.fmt(f), @@ -67,7 +67,7 @@ impl Display for Error { } impl Display for DataFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { DataFormatError::UnknownCompressionScheme(scheme) => { write!(f, "Unknown compression scheme: {scheme}") @@ -82,7 +82,7 @@ impl Display for DataFormatError { } impl Display for NbtFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { NbtFormatError::MissingKey(key) => { write!(f, "Could not find key: \"{key}\" in nbt data.") diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 9c3f1eb2d..880365583 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -81,6 +81,8 @@ impl AnvilWorld { /// # Examples /// /// ``` + /// use valence::prelude::*; + /// /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); /// let future = world.state.load_chunks(to_load); /// let parsed_chunks = futures::executor::block_on(future).unwrap(); @@ -91,12 +93,7 @@ impl AnvilWorld { /// } else { /// // There is no information on this chunk in the region file. /// let mut blank_chunk = UnloadedChunk::new(16); - /// blank_chunk.set_block_state( - /// 0, - /// 0, - /// 0, - /// valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), - /// ); + /// blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); /// world.chunks.insert(pos, blank_chunk, true); /// } /// } @@ -104,7 +101,7 @@ impl AnvilWorld { pub async fn load_chunks>( &self, positions: I, - ) -> Result)>, Error> { + ) -> Result)>, Error> { let mut map = BTreeMap::>::new(); for pos in positions { let region_pos = RegionPos::from(pos); diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index d1d28d656..bce082d06 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -16,7 +16,7 @@ use crate::palette::DataFormat; use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; #[derive(Debug)] -pub struct Region { +pub struct Region { source: Mutex, offset: u64, position: RegionPos, @@ -187,7 +187,7 @@ impl Region { let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; - //Parsing sections + // Parsing sections let mut chunk = UnloadedChunk::new(section_height); for mut nbt_section in nbt_sections.into_iter() { let chunk_y_offset: isize = @@ -202,7 +202,7 @@ impl Region { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); for mut nbt_palette in nbt_palette_vec { - let block_id = valence::ident::Ident::new(take_assume::( + let block_id = Ident::new(take_assume::( &mut nbt_palette, "Name", )?)?; From 3379bdd4c0ac25a66bed4a50f80925b0acad5a7f Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 3 Nov 2022 01:41:06 -0700 Subject: [PATCH 18/75] Fix formatting --- valence_anvil/examples/java_region.rs | 7 +------ valence_anvil/src/region.rs | 6 ++---- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index ec629c841..5e27d59de 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -155,12 +155,7 @@ impl Config for Game { world.chunks.insert(pos, chunk, true); } else { let mut blank_chunk = UnloadedChunk::new(16); - blank_chunk.set_block_state( - 0, - 0, - 0, - BlockState::from_kind(BlockKind::Lava), - ); + blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); world.chunks.insert(pos, blank_chunk, true); } } diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index bce082d06..4e595c0d0 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -202,10 +202,8 @@ impl Region { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); for mut nbt_palette in nbt_palette_vec { - let block_id = Ident::new(take_assume::( - &mut nbt_palette, - "Name", - )?)?; + let block_id = + Ident::new(take_assume::(&mut nbt_palette, "Name")?)?; let block_kind = if let Some(block_kind) = BlockKind::from_str(block_id.path()) { block_kind From 8db39c72235f7bbd59134c9b022c829921745c23 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Fri, 4 Nov 2022 23:30:01 +0100 Subject: [PATCH 19/75] Fix bug: Palette data wrapping around when palette array and bitmask do not align. This fixes blocks randomly repeating at the start of chunk subsections --- valence_anvil/Cargo.toml | 1 + valence_anvil/examples/java_region.rs | 71 +++++++++++++++++++-------- valence_anvil/src/error.rs | 13 +---- valence_anvil/src/lib.rs | 15 +++--- valence_anvil/src/palette.rs | 18 ++++--- valence_anvil/src/region.rs | 2 + 6 files changed, 73 insertions(+), 47 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index ebb735fc7..e9b941da0 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -18,6 +18,7 @@ async-compression = { version = "0.3.15", features = ["tokio", "gzip", "zlib"] } byteorder = "1.4.3" tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" +thiserror = "1.0.37" [build-dependencies] anyhow = "1.0.65" diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 5e27d59de..8060a13ca 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -2,39 +2,64 @@ extern crate valence; use std::net::SocketAddr; use std::path::PathBuf; -use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::prelude::*; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; +/// # IMPORTANT +/// +/// Run this example with one argument containing the path of the the following +/// to the world directory you wish to load. Inside this directory you can +/// commonly see `advancements`, `DIM1`, `DIM-1` and most importantly `region` +/// subdirectories. Only the `region` directory is accessed. pub fn main() -> ShutdownResult { - valence::start_server( - Game { - player_count: AtomicUsize::new(0), - }, - None, - ) + let args: Vec = std::env::args().collect(); + if let Some(world_folder) = args.get(1) { + let world_folder = PathBuf::from(world_folder); + if world_folder.exists() && world_folder.is_dir() { + if !world_folder.join("region").exists() { + ShutdownResult::Err( + "Could not find the `region` folder inside the world directory.".into(), + ) + } else { + // This actually starts and runs the server. + valence::start_server( + Game { + world_dir: world_folder, + player_count: AtomicUsize::new(0), + }, + None, + ) + } + } else { + ShutdownResult::Err( + "World directory argument is not valid: Must be a folder that exists.".into(), + ) + } + } else { + ShutdownResult::Err("Please add the world directory as program argument.".into()) + } +} + +#[derive(Debug, Default)] +struct ClientData { + id: EntityId, + //block: valence::block::BlockKind } struct Game { + world_dir: PathBuf, player_count: AtomicUsize, } const MAX_PLAYERS: usize = 10; -/// # IMPORTANT -/// -/// Change the following to the world file you wish to load. -/// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most -/// importantly `region` directories. Only the `region` directory is accessed. -const WORLD_FOLDER: &str = "./test_data/"; - #[async_trait] impl Config for Game { type ServerState = Option; - type ClientState = EntityId; + type ClientState = ClientData; type EntityState = (); type WorldState = AnvilWorld; /// If the chunk should stay loaded at the end of the tick. @@ -65,10 +90,9 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); server.worlds.insert( DimensionId::default(), - AnvilWorld::new(world_folder, &server.shared), + AnvilWorld::new::(&self.world_dir, server.shared.biomes()), ); server.state = Some(server.player_lists.insert(()).0); } @@ -93,7 +117,7 @@ impl Config for Game { .entities .insert_with_uuid(EntityKind::Player, client.uuid(), ()) { - Some((id, _)) => client.state = id, + Some((id, _)) => client.state.id = id, None => { client.disconnect("Conflicting UUID"); return false; @@ -117,7 +141,12 @@ impl Config for Game { ); } - client.send_message("Welcome to the java chunk parsing example!".italic()); + client.send_message("Welcome to the java chunk parsing example!"); + client.send_message( + "Chunks with a single lava source block indicates that the chunk is not \ + (fully) generated." + .italic(), + ); } if client.is_disconnected() { @@ -125,12 +154,12 @@ impl Config for Game { if let Some(id) = &server.state { server.player_lists.get_mut(id).remove(client.uuid()); } - server.entities.remove(client.state); + server.entities.remove(client.state.id); return false; } - if let Some(entity) = server.entities.get_mut(client.state) { + if let Some(entity) = server.entities.get_mut(client.state.id) { while handle_event_default(client, entity).is_some() {} } diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index c2c180da2..417c341a5 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,10 +1,10 @@ -use std::error::Error as StdError; use std::fmt::{Display, Formatter}; use std::{fmt, io}; +use thiserror::Error; use valence::ident::{Ident, IdentError}; -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Error { Io(io::Error), DataFormatError(DataFormatError), @@ -28,15 +28,6 @@ pub enum DataFormatError { InvalidPalette, } -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - Self::Io(e) => Some(e), - _ => None, - } - } -} - impl From for Error { fn from(e: io::Error) -> Self { Self::Io(e) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 880365583..857e8b06c 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -6,11 +6,10 @@ use byteorder::{BigEndian, ByteOrder}; use region::Region; use tokio::fs::File; use tokio::sync::{Mutex, MutexGuard}; -use valence::biome::BiomeId; +use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; use valence::ident::Ident; -use valence::server::SharedServer; use crate::error::Error; @@ -46,21 +45,23 @@ impl AnvilWorld { /// ``` /// impl Config for Game { /// fn init(&self, server: &mut Server) { - /// let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); /// server.worlds.insert( /// DimensionId::default(), - /// AnvilWorld::new(world_folder, &server.shared), + /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), /// ); /// } /// } /// ``` - pub fn new(directory: PathBuf, server: &SharedServer) -> Self { + pub fn new<'a, C: Config>( + directory: impl Into, + server_biomes: impl Iterator, + ) -> Self { let mut biomes = BTreeMap::new(); - for (id, biome) in server.biomes() { + for (id, biome) in server_biomes { biomes.insert(biome.name.clone(), id); } Self { - world_root: directory, + world_root: directory.into(), biomes, region_files: Mutex::new(BTreeMap::new()), } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 65d8ffcc7..490eb552d 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -11,9 +11,15 @@ pub fn parse_palette) -> Result<(), Error>)>( source: &Vec, data: Option>, min_bits: usize, + expected_len: usize, fun: &mut F, ) -> Result<(), Error> { let palette_len = source.len(); + if palette_len == 0 { + return Err(crate::error::Error::DataFormatError( + DataFormatError::InvalidPalette, + )); + } if let Some(data) = data { if palette_len < 2 || data.is_empty() { fun(DataFormat::All(source[0]))?; @@ -40,21 +46,17 @@ pub fn parse_palette) -> Result<(), Error>)>( let palette_index_unshifted = (integer & mask) as usize; let palette_index_shifted = palette_index_unshifted >> rev_shift; - // Uncomment the following to aid in debugging. - // println!("IN - // \t{integer:064b}\nMSK\t{mask:064b}({bits_per_index})\nRES\ - // t{palette_index_unshifted:064b}\nSFT\t{palette_index_shifted:064b} - // ({rev_shift} - {trailing_bits})\n"); if palette_index_shifted > choice_len { - //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", - // palette_index_shifted, choice_len, - // bits_per_index, source, source.len()); return Err(crate::error::Error::DataFormatError( DataFormatError::InvalidPalette, )); } else { fun(DataFormat::Palette(index, source[palette_index_shifted]))?; index += 1; + // Prevents interpreting the rest of the long as data. + if index == expected_len { + return Ok(()); + } } } } diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 4e595c0d0..7468362bd 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -251,6 +251,7 @@ impl Region { &parsed_block_state_palette, take_assume_optional(&mut nbt_block_states, "data"), 4, + 16 * 16 * 16, &mut |data| { match data { DataFormat::All(state) => { @@ -314,6 +315,7 @@ impl Region { &parsed_biome_palette, take_assume_optional(&mut nbt_biomes, "data"), 0, + 4 * 4 * 4, &mut |data| { match data { DataFormat::All(biome) => { From e88a44d5c3aaa26d9e7fa8d30b0b3614eed5a9d1 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 5 Nov 2022 12:09:24 +0100 Subject: [PATCH 20/75] Change error implementations to `thiserror` macro derive where possible --- valence_anvil/src/error.rs | 88 +++++++++++--------------------------- 1 file changed, 25 insertions(+), 63 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 417c341a5..d87de06f1 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,84 +1,46 @@ -use std::fmt::{Display, Formatter}; -use std::{fmt, io}; +use std::io; use thiserror::Error; use valence::ident::{Ident, IdentError}; -#[derive(Debug, Error)] +#[derive(Error, Debug)] pub enum Error { - Io(io::Error), - DataFormatError(DataFormatError), - NbtParseError(valence::nbt::Error), - NbtFormatError(NbtFormatError), + #[error(transparent)] + Io(#[from] io::Error), + #[error(transparent)] + DataFormatError(#[from] DataFormatError), + #[error(transparent)] + NbtParseError(#[from] valence::nbt::Error), + #[error(transparent)] + NbtFormatError(#[from] NbtFormatError), } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum NbtFormatError { + #[error("Missing key: {0}")] MissingKey(String), + #[error("Invalid type: {0}")] InvalidType(String), } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum DataFormatError { + #[error("Unknown compression scheme: {0}")] UnknownCompressionScheme(u8), + #[error("Invalid chunk size: {0}")] InvalidChunkSize(usize), - IdentityError(IdentError), + #[error(transparent)] + IdentityError(#[from] IdentError), + #[error("Unknown identity: {0}")] UnknownType(Ident), + #[error("Invalid chunk state: {0}")] InvalidChunkState(String), + #[error("Invalid chunk palette")] InvalidPalette, } -impl From for Error { - fn from(e: io::Error) -> Self { - Self::Io(e) +impl From> for Error{ + fn from(err: IdentError) -> Self { + Self::DataFormatError(DataFormatError::IdentityError(err)) } -} - -impl From for Error { - fn from(e: valence::nbt::Error) -> Self { - Self::NbtParseError(e) - } -} - -impl From> for Error { - fn from(e: IdentError) -> Self { - Self::DataFormatError(DataFormatError::IdentityError(e)) - } -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Error::Io(e) => e.fmt(f), - Error::DataFormatError(e) => e.fmt(f), - Error::NbtParseError(e) => e.fmt(f), - Error::NbtFormatError(e) => e.fmt(f), - } - } -} - -impl Display for DataFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - DataFormatError::UnknownCompressionScheme(scheme) => { - write!(f, "Unknown compression scheme: {scheme}") - } - DataFormatError::InvalidChunkSize(size) => write!(f, "Invalid chunk size: {size}"), - DataFormatError::IdentityError(e) => e.fmt(f), - DataFormatError::UnknownType(identity) => write!(f, "Unknown identity: {identity}"), - DataFormatError::InvalidChunkState(state) => write!(f, "Unknown chunk state: {state}"), - DataFormatError::InvalidPalette => write!(f, "Invalid chunk palette"), - } - } -} - -impl Display for NbtFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - NbtFormatError::MissingKey(key) => { - write!(f, "Could not find key: \"{key}\" in nbt data.") - } - NbtFormatError::InvalidType(key) => write!(f, "Unexpected type for key: \"{key}\""), - } - } -} +} \ No newline at end of file From d13a4073352ecea2ddc52f9208f93f785586650b Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 5 Nov 2022 12:13:59 +0100 Subject: [PATCH 21/75] cargo fmt --- valence_anvil/src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index d87de06f1..ba594a6ce 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -39,8 +39,8 @@ pub enum DataFormatError { InvalidPalette, } -impl From> for Error{ +impl From> for Error { fn from(err: IdentError) -> Self { Self::DataFormatError(DataFormatError::IdentityError(err)) } -} \ No newline at end of file +} From e6a07273019400f9b1720d6dc85ee19436895c18 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 6 Nov 2022 12:42:22 +0100 Subject: [PATCH 22/75] Refactor components. Move from lib.rs to region.rs --- valence_anvil/src/lib.rs | 97 ++----------------------------------- valence_anvil/src/region.rs | 95 +++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 857e8b06c..e2db7b1bd 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,9 +1,8 @@ use std::collections::BTreeMap; -use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::path::{Path, PathBuf}; +use std::fmt::Debug; +use std::path::PathBuf; -use byteorder::{BigEndian, ByteOrder}; -use region::Region; +use region::{ChunkTimestamp, Region, RegionPos}; use tokio::fs::File; use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; @@ -182,93 +181,3 @@ impl AnvilWorld { .as_mut()) } } - -#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] -pub struct RegionPos { - x: i32, - z: i32, -} - -impl From for RegionPos { - fn from(pos: ChunkPos) -> Self { - Self { - x: pos.x >> 5, - z: pos.z >> 5, - } - } -} - -impl RegionPos { - pub fn path(self, world_root: impl AsRef) -> PathBuf { - world_root - .as_ref() - .join("region") - .join(format!("r.{}.{}.mca", self.x, self.z)) - } - - pub fn contains(self, chunk_pos: ChunkPos) -> bool { - Self::from(chunk_pos) == self - } -} - -/// The location of the chunk inside the region file. -#[derive(Copy, Clone, Debug)] -struct ChunkSeekLocation { - offset_sectors: u32, - len_sectors: u8, -} - -impl ChunkSeekLocation { - const fn zero() -> Self { - Self { - offset_sectors: 0, - len_sectors: 0, - } - } - - const fn offset(&self) -> u64 { - self.offset_sectors as u64 * 1024 * 4 - } - - const fn len(&self) -> usize { - self.len_sectors as usize * 1024 * 4 - } - - fn load(&mut self, chunk: [u8; 4]) { - self.offset_sectors = BigEndian::read_u24(&chunk[..3]); - self.len_sectors = chunk[3]; - } -} - -/// The timestamp when the chunk was last modified in seconds since epoch. -#[derive(Copy, Clone)] -pub struct ChunkTimestamp(u32); - -impl Debug for ChunkTimestamp { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}s", self.0) - } -} - -impl ChunkTimestamp { - const fn zero() -> Self { - Self(0) - } - - fn load(&mut self, chunk: [u8; 4]) { - self.0 = BigEndian::read_u32(&chunk) - } - - fn into_option(self) -> Option { - if self.0 == 0 { - None - } else { - Some(self) - } - } - - #[inline(always)] - pub fn seconds_since_epoch(self) -> u32 { - self.0 - } -} diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 7468362bd..83e7e3ab4 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -1,4 +1,5 @@ use std::io::SeekFrom; +use std::path::{Path, PathBuf}; use byteorder::{BigEndian, ByteOrder}; use tokio::fs::File; @@ -9,11 +10,13 @@ use valence::block::{BlockKind, BlockState, PropName, PropValue}; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; +use valence::prelude::vek::serde::__private::fmt::{Debug, Result as FmtResult}; +use valence::prelude::vek::serde::__private::Formatter; use crate::compression::CompressionScheme; use crate::error::{DataFormatError, Error, NbtFormatError}; use crate::palette::DataFormat; -use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; +use crate::{palette, AnvilWorld}; #[derive(Debug)] pub struct Region { @@ -392,3 +395,93 @@ impl AnvilHeader { &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] } } + +/// The location of the chunk inside the region file. +#[derive(Copy, Clone, Debug)] +struct ChunkSeekLocation { + offset_sectors: u32, + len_sectors: u8, +} + +impl ChunkSeekLocation { + const fn zero() -> Self { + Self { + offset_sectors: 0, + len_sectors: 0, + } + } + + const fn offset(&self) -> u64 { + self.offset_sectors as u64 * 1024 * 4 + } + + const fn len(&self) -> usize { + self.len_sectors as usize * 1024 * 4 + } + + fn load(&mut self, chunk: [u8; 4]) { + self.offset_sectors = BigEndian::read_u24(&chunk[..3]); + self.len_sectors = chunk[3]; + } +} + +/// The timestamp when the chunk was last modified in seconds since epoch. +#[derive(Copy, Clone)] +pub struct ChunkTimestamp(u32); + +impl Debug for ChunkTimestamp { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}s", self.0) + } +} + +impl ChunkTimestamp { + const fn zero() -> Self { + Self(0) + } + + fn load(&mut self, chunk: [u8; 4]) { + self.0 = BigEndian::read_u32(&chunk) + } + + fn into_option(self) -> Option { + if self.0 == 0 { + None + } else { + Some(self) + } + } + + #[inline(always)] + pub fn seconds_since_epoch(self) -> u32 { + self.0 + } +} + +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] +pub struct RegionPos { + x: i32, + z: i32, +} + +impl From for RegionPos { + fn from(pos: ChunkPos) -> Self { + Self { + x: pos.x >> 5, + z: pos.z >> 5, + } + } +} + +impl RegionPos { + pub fn path(self, world_root: impl AsRef) -> PathBuf { + world_root + .as_ref() + .join("region") + .join(format!("r.{}.{}.mca", self.x, self.z)) + } + + pub fn contains(self, chunk_pos: ChunkPos) -> bool { + Self::from(chunk_pos) == self + } +} From d0795fdfb899f27fb32c6e244caca80065ce7ac0 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 7 Nov 2022 20:50:09 +0100 Subject: [PATCH 23/75] Allow taking an owned or borrowed value for Biome. Prevents boilerplate. --- valence_anvil/examples/java_region.rs | 2 +- valence_anvil/src/lib.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 8060a13ca..569a4187a 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -92,7 +92,7 @@ impl Config for Game { fn init(&self, server: &mut Server) { server.worlds.insert( DimensionId::default(), - AnvilWorld::new::(&self.world_dir, server.shared.biomes()), + AnvilWorld::new::(&self.world_dir, server.shared.biomes()), ); server.state = Some(server.player_lists.insert(()).0); } diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index e2db7b1bd..9c938f057 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,3 +1,4 @@ +use std::borrow::Borrow; use std::collections::BTreeMap; use std::fmt::Debug; use std::path::PathBuf; @@ -46,18 +47,18 @@ impl AnvilWorld { /// fn init(&self, server: &mut Server) { /// server.worlds.insert( /// DimensionId::default(), - /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), + /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), /// ); /// } /// } /// ``` - pub fn new<'a, C: Config>( + pub fn new>( directory: impl Into, - server_biomes: impl Iterator, + server_biomes: impl Iterator, ) -> Self { let mut biomes = BTreeMap::new(); for (id, biome) in server_biomes { - biomes.insert(biome.name.clone(), id); + biomes.insert(biome.borrow().name.clone(), id); } Self { world_root: directory.into(), From c1c828351a8518ad4058fed98e0cd0ed34215d1f Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 13 Nov 2022 13:53:54 +0100 Subject: [PATCH 24/75] NONFUNCTIONAL: Benchmark set-up. Still needs a way to download one git directory only --- .gitignore | 1 + valence_anvil/Cargo.toml | 7 ++ valence_anvil/benches/world_parsing.rs | 106 +++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 valence_anvil/benches/world_parsing.rs diff --git a/.gitignore b/.gitignore index 2564d7257..bbe891c60 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ Cargo.lock flamegraph.svg perf.data perf.data.old +/valence_anvil/.asset_cache/ diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index e9b941da0..4b788f560 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -20,6 +20,13 @@ tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" thiserror = "1.0.37" +[dev-dependencies] +criterion = { version = "0.4.0", features = ["async", "async_tokio"] } + +[[bench]] +name = "world_parsing" +harness = false + [build-dependencies] anyhow = "1.0.65" heck = "0.4.0" diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs new file mode 100644 index 000000000..709ef7686 --- /dev/null +++ b/valence_anvil/benches/world_parsing.rs @@ -0,0 +1,106 @@ +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use tokio::runtime::Builder; +use valence::biome::BiomeId; +use valence::chunk::ChunkPos; +use valence::config::Config; +use valence_anvil::biome::BiomeKind; +use valence_anvil::AnvilWorld; +use std::process::{Command, Stdio}; +use std::io::Write; +use std::fs::create_dir_all; + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); + +const BENCHMARK_WORLD_ASSET: GitAsset = GitAsset::new( + "https://github.com/TerminatorNL/valence-test-data.git", + "Worlds/1.19.2/Benchmark world SP" +); + +struct GitAsset<'a> { + repository: &'a str, + repo_path: &'a str, +} + +impl<'a> GitAsset<'a> { + pub const fn new(repository: &'a str, repo_path: &'a str) -> Self { + GitAsset { + repository, + repo_path + } + } + + /// Downloads the asset from git if they aren't already downloaded. + /// This download uses the 'git' command. + /// Returns the location of the downloaded asset. + pub fn load(&self) -> PathBuf { + let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); + + + create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache`"); + let asset_cache_dir = asset_cache_dir.canonicalize().expect("Unable to resolve `.asset_cache` directory"); + +// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["clone", ""]).spawn().expect("Failed to execute `git clone` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git clone` command output").stdout); +// +// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["sparse-checkout", "set", self.repo_path]).spawn().expect("Failed to execute `git sparse-checkout` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git sparse-checkout` command output").stdout); +// +// let cmd = Command::new("pwd").current_dir(&asset_cache_dir).spawn().expect("Failed to execute `pwd` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `pwd` command output").stdout).expect("Unable to write output to console"); + + unimplemented!("Asset downloading is not yet implemented") + } +} + +struct BenchmarkConfig; +impl Config for BenchmarkConfig { + type ServerState = (); + type ClientState = (); + type EntityState = (); + type WorldState = (); + type ChunkState = (); + type PlayerListState = (); +} + +fn criterion_benchmark(c: &mut Criterion) { + let world_directory = BENCHMARK_WORLD_ASSET.load(); + + let world = AnvilWorld::new::( + world_directory, + BiomeKind::ALL + .iter() + .map(|b| (BiomeId::default(), b.biome().unwrap())), + ); + + let mut load_targets = Vec::new(); + for x in -5..5 { + for z in -5..5 { + load_targets.push(ChunkPos::new(x, z)); + } + } + + let runtime = Builder::new_multi_thread() + .enable_all() + .build() + .expect("Creating runtime failed"); + + c.bench_function("Load square 10x10", |b| { + b.to_async(&runtime).iter_with_setup( + || load_targets.clone().into_iter(), + |targets| async { + for (chunk_pos, chunk) in world.load_chunks(black_box(targets)).await.unwrap() { + assert!( + chunk.is_some(), + "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ + generated?" + ); + black_box(chunk); + } + }, + ); + }); +} From fdcb56b649659b16995d4df05ae0d55659d18a05 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 13 Nov 2022 20:10:30 +0100 Subject: [PATCH 25/75] Add benchmarks to valence_anvil --- valence_anvil/Cargo.toml | 6 + valence_anvil/benches/benchtools.rs | 178 +++++++++++++++++++++++++ valence_anvil/benches/world_parsing.rs | 53 +------- 3 files changed, 191 insertions(+), 46 deletions(-) create mode 100644 valence_anvil/benches/benchtools.rs diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 4b788f560..96858bf6c 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -21,6 +21,12 @@ futures = "0.3.24" thiserror = "1.0.37" [dev-dependencies] +reqwest = { version = "0.11.12", features = ["blocking", "stream"] } +tempfile = "3.3.0" +zip = "0.5" +fs_extra = "1.2.0" +zip-extensions = "0.6.1" + criterion = { version = "0.4.0", features = ["async", "async_tokio"] } [[bench]] diff --git a/valence_anvil/benches/benchtools.rs b/valence_anvil/benches/benchtools.rs new file mode 100644 index 000000000..c4fb1d6c1 --- /dev/null +++ b/valence_anvil/benches/benchtools.rs @@ -0,0 +1,178 @@ +use std::fs::{create_dir_all, DirEntry}; +use std::io; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use fs_extra::dir::CopyOptions; +use reqwest::IntoUrl; + +/// Describes where to find the asset if it already has been downloaded and from +/// which URL the asset can be downloaded. More asset types can be added on +/// demand by modifying this enum. +pub enum WebAsset, URL: IntoUrl> { + ZippedDirectory { + destination_path: DestinationPath, + remove_top_level_dir: bool, + url: URL, + }, +} + +impl, URL: IntoUrl + Clone> WebAsset { + /// Creates a ZippedDirectory asset type. + /// + /// # Arguments + /// + /// * `destination_path`: A unique path for this asset. If the path is + /// relative, it will be placed under the `.asset_cache` directory. + /// Relative paths are recommended. + /// * `remove_top_level_dir`: Some zip files wrap all their contents in an + /// additional folder. Setting this value to `true` will remove that + /// redundant directory. If the Zip file contains multiple + /// files/directories in the root, this will cause a panic. + /// * `url`: The URL from which to download the Zip file. + /// + /// returns: `WebAsset` The created asset. + /// + /// # Examples + /// + /// ``` + /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + /// "BenchmarkWorld", + /// true, + /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", + /// ); + /// ``` + pub const fn zipped_directory( + destination_path: DestinationPath, + remove_top_level_dir: bool, + url: URL, + ) -> Self { + Self::ZippedDirectory { + destination_path, + remove_top_level_dir, + url, + } + } + + fn url(&self) -> URL { + match self { + WebAsset::ZippedDirectory { url, .. } => url.clone(), + } + } + + fn destination_path(&self) -> &DestinationPath { + match self { + WebAsset::ZippedDirectory { + destination_path: directory_name, + .. + } => directory_name, + } + } + + /// Loads the asset. If the asset is already present on the system due to a + /// prior run, the cached asset is used instead. If the asset is not + /// cached yet, this function downloads the asset using the current thread. + /// This will block until the download is complete. + /// + /// returns: `PathBuf` The reference to the asset on the file system + /// + /// # Examples + /// + /// ``` + /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + /// "BenchmarkWorld", + /// true, + /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", + /// ); + /// let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); + /// ``` + pub fn load_blocking_panic(&self) -> PathBuf { + let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); + create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache` directory"); + let final_path = asset_cache_dir.join(self.destination_path()); + if final_path.exists() { + return final_path; + } + + let mut request = reqwest::blocking::get(self.url()) + .expect("File download request failed") + .error_for_status() + .unwrap(); + + let cache_download_directory = asset_cache_dir.join("downloads"); + create_dir_all(&cache_download_directory) + .expect("Unable to create `.asset_cache/downloads` directory"); + + let mut downloaded_zip_file = tempfile::tempfile_in(&cache_download_directory) + .expect("Could not create the temporary file"); + + println!( + "Downloading {:?} from {}", + self.destination_path().as_ref(), + self.url().as_str() + ); + request + .copy_to(&mut downloaded_zip_file) + .expect("Could not write web contents to the temporary file"); + + match self { + WebAsset::ZippedDirectory { + remove_top_level_dir: remove_single_top_level_dir, + .. + } => { + let mut zip_archive = zip::ZipArchive::new(downloaded_zip_file) + .expect("unable to create zip archive from downloaded content"); + if *remove_single_top_level_dir { + let temporary_directory = tempfile::tempdir_in(&cache_download_directory) + .expect("Unable to create temporary directory in `.asset_cache`"); + zip_archive + .extract(&temporary_directory) + .expect("Unable to unzip downloaded contents"); + let mut entries: Vec> = temporary_directory + .path() + .read_dir() + .expect("Could not read the contents of the temporary directory") + .into_iter() + .collect(); + if let Some(top_level_directory) = entries.pop() { + assert_eq!( + entries.len(), + 0, + "Found more than one entry in the top level directory of the Zip file." + ); + let top_level_directory = top_level_directory.unwrap(); + let top_level_directory = top_level_directory.path(); + assert!( + top_level_directory.is_dir(), + "The only content in the Zip is a file!" + ); + create_dir_all(&final_path) + .expect("Could not create a directory inside the asset cache"); + fs_extra::move_items( + top_level_directory + .read_dir() + .unwrap() + .map(|v| v.unwrap().path()) + .collect::>() + .as_slice(), + &final_path, + &CopyOptions::new(), + ) + .unwrap(); + // We keep the temporary directory around until we're done moving files out + // of it. + drop(temporary_directory); + final_path + } else { + panic!("The downloaded zip file was empty"); + } + } else { + zip_archive + .extract(&final_path) + .expect("Unable to unzip downloaded contents"); + final_path + } + } + } + } +} diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 709ef7686..2acf585b5 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -1,6 +1,3 @@ -use std::path::{Path, PathBuf}; -use std::str::FromStr; - use criterion::{black_box, criterion_group, criterion_main, Criterion}; use tokio::runtime::Builder; use valence::biome::BiomeId; @@ -8,53 +5,17 @@ use valence::chunk::ChunkPos; use valence::config::Config; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -use std::process::{Command, Stdio}; -use std::io::Write; -use std::fs::create_dir_all; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -const BENCHMARK_WORLD_ASSET: GitAsset = GitAsset::new( - "https://github.com/TerminatorNL/valence-test-data.git", - "Worlds/1.19.2/Benchmark world SP" -); - -struct GitAsset<'a> { - repository: &'a str, - repo_path: &'a str, -} - -impl<'a> GitAsset<'a> { - pub const fn new(repository: &'a str, repo_path: &'a str) -> Self { - GitAsset { - repository, - repo_path - } - } - - /// Downloads the asset from git if they aren't already downloaded. - /// This download uses the 'git' command. - /// Returns the location of the downloaded asset. - pub fn load(&self) -> PathBuf { - let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); - - - create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache`"); - let asset_cache_dir = asset_cache_dir.canonicalize().expect("Unable to resolve `.asset_cache` directory"); - -// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["clone", ""]).spawn().expect("Failed to execute `git clone` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git clone` command output").stdout); -// -// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["sparse-checkout", "set", self.repo_path]).spawn().expect("Failed to execute `git sparse-checkout` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git sparse-checkout` command output").stdout); -// -// let cmd = Command::new("pwd").current_dir(&asset_cache_dir).spawn().expect("Failed to execute `pwd` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `pwd` command output").stdout).expect("Unable to write output to console"); +mod benchtools; - unimplemented!("Asset downloading is not yet implemented") - } -} +const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + "1.19.2 benchmark world", + true, + "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", +); struct BenchmarkConfig; impl Config for BenchmarkConfig { @@ -67,7 +28,7 @@ impl Config for BenchmarkConfig { } fn criterion_benchmark(c: &mut Criterion) { - let world_directory = BENCHMARK_WORLD_ASSET.load(); + let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); let world = AnvilWorld::new::( world_directory, From 64458fd89c12cf8110d17ad0b2571f422e837820 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 14 Nov 2022 22:51:29 -0800 Subject: [PATCH 26/75] Fix imports --- valence_anvil/build/biome.rs | 4 ++-- valence_anvil/src/error.rs | 2 +- valence_anvil/src/lib.rs | 2 +- valence_anvil/src/region.rs | 9 ++++----- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 268d5a77b..993494f81 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -238,8 +238,8 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { - use valence::biome::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; - use valence::ident::{Ident,IdentError}; + use valence::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation}; + use valence::protocol::ident::{Ident, IdentError}; use std::str::FromStr; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index ba594a6ce..76bb2f9af 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,7 +1,7 @@ use std::io; use thiserror::Error; -use valence::ident::{Ident, IdentError}; +use valence::protocol::ident::{Ident, IdentError}; #[derive(Error, Debug)] pub enum Error { diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 9c938f057..398767b8f 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -9,7 +9,7 @@ use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; -use valence::ident::Ident; +use valence::protocol::Ident; use crate::error::Error; diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 83e7e3ab4..22e9de154 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -1,3 +1,4 @@ +use std::fmt::{self, Debug, Formatter}; use std::io::SeekFrom; use std::path::{Path, PathBuf}; @@ -6,12 +7,10 @@ use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; use tokio::sync::Mutex; use valence::biome::BiomeId; -use valence::block::{BlockKind, BlockState, PropName, PropValue}; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; -use valence::prelude::vek::serde::__private::fmt::{Debug, Result as FmtResult}; -use valence::prelude::vek::serde::__private::Formatter; +use valence::protocol::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::protocol::Ident; use crate::compression::CompressionScheme; use crate::error::{DataFormatError, Error, NbtFormatError}; @@ -430,7 +429,7 @@ impl ChunkSeekLocation { pub struct ChunkTimestamp(u32); impl Debug for ChunkTimestamp { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}s", self.0) } } From 65a18cb5f94ef5984fe245eb822025df602f1b95 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 14 Nov 2022 22:59:14 -0800 Subject: [PATCH 27/75] Avoid OpenSSL dependency on linux --- valence_anvil/Cargo.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 96858bf6c..87a64dd23 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -21,14 +21,18 @@ futures = "0.3.24" thiserror = "1.0.37" [dev-dependencies] -reqwest = { version = "0.11.12", features = ["blocking", "stream"] } tempfile = "3.3.0" zip = "0.5" fs_extra = "1.2.0" zip-extensions = "0.6.1" - criterion = { version = "0.4.0", features = ["async", "async_tokio"] } +[dev-dependencies.reqwest] +version = "0.11.12" +default-features = false +# Avoid OpenSSL dependency on Linux. +features = ["rustls-tls", "blocking", "stream"] + [[bench]] name = "world_parsing" harness = false From 44e404a615d92a83f04eb305fe64128cbd23f2a7 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 11:32:57 +0200 Subject: [PATCH 28/75] Add anvil file support --- valence_anvil/Cargo.toml | 20 + valence_anvil/examples/java_region.rs | 183 +++++++++ valence_anvil/src/error.rs | 128 +++++++ valence_anvil/src/lib.rs | 524 ++++++++++++++++++++++++++ valence_anvil/src/palette.rs | 67 ++++ 5 files changed, 922 insertions(+) create mode 100644 valence_anvil/Cargo.toml create mode 100644 valence_anvil/examples/java_region.rs create mode 100644 valence_anvil/src/error.rs create mode 100644 valence_anvil/src/lib.rs create mode 100644 valence_anvil/src/palette.rs diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml new file mode 100644 index 000000000..588af4f6e --- /dev/null +++ b/valence_anvil/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "valence_anvil" +description = "A library for Minecraft's Anvil world format." +documentation = "https://docs.rs/valence_anvil/" +repository = "https://github.com/valence_anvil/valence/tree/main/valence_anvil" +readme = "README.md" +license = "MIT" +keywords = ["anvil", "minecraft", "serialization"] +version = "0.1.0" +authors = ["Ryan Johnson ", "TerminatorNL "] +edition = "2021" + +[dependencies] +valence = {path = ".."} +valence_nbt = {path = "../valence_nbt"} +rayon = "1.5.3" +async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} +byteorder = "1" +tokio = {version = "1", features = ["fs", "io-util", "full"]} +futures = "0.3.24" \ No newline at end of file diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs new file mode 100644 index 000000000..25c5edc96 --- /dev/null +++ b/valence_anvil/examples/java_region.rs @@ -0,0 +1,183 @@ +extern crate valence; + +use std::net::SocketAddr; +use std::path::PathBuf; +use std::str::FromStr; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use valence::async_trait; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::client::{handle_event_default, GameMode}; +use valence::config::{Config, ServerListPing}; +use valence::dimension::DimensionId; +use valence::entity::{EntityId, EntityKind}; +use valence::player_list::PlayerListId; +use valence::server::{Server, SharedServer, ShutdownResult}; +use valence::text::{Color, TextFormat}; +use valence::util::chunks_in_view_distance; +use valence_anvil::AnvilWorld; + +pub fn main() -> ShutdownResult { + let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + + println!("World folder: {:?}", world_folder.canonicalize()); + + valence::start_server( + Game { + player_count: AtomicUsize::new(0), + anvil_world: AnvilWorld::new(world_folder), + }, + None, + ) +} + +struct Game { + player_count: AtomicUsize, + anvil_world: AnvilWorld, +} + +const MAX_PLAYERS: usize = 10; +const WORLD_FOLDER: &'static str = "./test_data/"; + +#[async_trait] +impl Config for Game { + type ServerState = Option; + type ClientState = EntityId; + type EntityState = (); + type WorldState = (); + /// If the chunk should stay loaded at the end of the tick. + type ChunkState = bool; + type PlayerListState = (); + + fn max_connections(&self) -> usize { + // We want status pings to be successful even if the server is full. + MAX_PLAYERS + 64 + } + + async fn server_list_ping( + &self, + _server: &SharedServer, + _remote_addr: SocketAddr, + _protocol_version: i32, + ) -> ServerListPing { + ServerListPing::Respond { + online_players: self.player_count.load(Ordering::SeqCst) as i32, + max_players: MAX_PLAYERS as i32, + player_sample: Default::default(), + description: "Hello Valence!".color(Color::AQUA), + favicon_png: Some( + include_bytes!("../../assets/logo-64x64.png") + .as_slice() + .into(), + ), + } + } + + fn init(&self, server: &mut Server) { + server.worlds.insert(DimensionId::default(), ()); + server.state = Some(server.player_lists.insert(()).0); + } + + fn update(&self, server: &mut Server) { + let (world_id, world) = server.worlds.iter_mut().next().unwrap(); + + server.clients.retain(|_, client| { + if client.created_this_tick() { + if self + .player_count + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |count| { + (count < MAX_PLAYERS).then_some(count + 1) + }) + .is_err() + { + client.disconnect("The server is full!".color(Color::RED)); + return false; + } + + match server + .entities + .insert_with_uuid(EntityKind::Player, client.uuid(), ()) + { + Some((id, _)) => client.state = id, + None => { + client.disconnect("Conflicting UUID"); + return false; + } + } + + client.spawn(world_id); + client.set_flat(true); + client.set_game_mode(GameMode::Spectator); + client.teleport([0.0, 200.0, 0.0], 0.0, 0.0); + client.set_player_list(server.state.clone()); + + if let Some(id) = &server.state { + server.player_lists.get_mut(id).insert( + client.uuid(), + client.username(), + client.textures().cloned(), + client.game_mode(), + 0, + None, + ); + } + + client.send_message("Welcome to the terrain example!".italic()); + } + + if client.is_disconnected() { + self.player_count.fetch_sub(1, Ordering::SeqCst); + if let Some(id) = &server.state { + server.player_lists.get_mut(id).remove(client.uuid()); + } + server.entities.remove(client.state); + + return false; + } + + if let Some(entity) = server.entities.get_mut(client.state) { + while handle_event_default(client, entity).is_some() {} + } + + let dist = client.view_distance(); + let p = client.position(); + + let new_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist).filter(|pos| { + if let Some(existing) = world.chunks.get_mut(*pos) { + existing.state = true; + false + } else { + true + } + }); + + let future = self.anvil_world.load_chunks(new_chunks); + let parsed_chunks = futures::executor::block_on(future).unwrap(); + for (pos, chunk) in parsed_chunks { + if let Some(chunk) = chunk { + world.chunks.insert(pos, chunk, true); + } else { + let mut blank_chunk = UnloadedChunk::new(16); + blank_chunk.set_block_state( + 0, + 0, + 0, + valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + ); + world.chunks.insert(pos, blank_chunk, true); + } + } + true + }); + + // Remove chunks outside the view distance of players. + world.chunks.retain(|_, chunk| { + if chunk.state { + chunk.state = false; + true + } else { + false + } + }); + } +} \ No newline at end of file diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs new file mode 100644 index 000000000..1da656e8f --- /dev/null +++ b/valence_anvil/src/error.rs @@ -0,0 +1,128 @@ +use std::error::Error as StdError; +use std::fmt::{Display, Formatter}; +use std::io; + +use valence::ident::Ident; + +/// Errors that can occur when encoding or decoding. +#[derive(Debug)] +pub struct Error { + /// Box this to keep the size of `Result` small. + cause: Box, +} + +impl Error { + pub(crate) fn unknown_compression_scheme(mode: u8) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::UnknownCompressionScheme(mode))), + } + } + + pub(crate) fn invalid_chunk_size(size: usize) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidChunkSize(size))), + } + } + + pub(crate) fn missing_nbt_value(key: &'static str) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::MissingNBT(key))), + } + } + + pub(crate) fn invalid_nbt(message: &'static str) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidNBT(message))), + } + } + + pub(crate) fn invalid_palette() -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::InvalidPalette)), + } + } + + pub(crate) fn unknown_type(ident: Ident) -> Self { + Self { + cause: Box::new(Cause::Parse(ParseError::UnknownType(ident))), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match &*self.cause { + Cause::Io(e) => Some(e), + _ => None, + } + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + Self { + cause: Box::new(Cause::Io(e)), + } + } +} +impl From for Error { + fn from(e: valence::nbt::Error) -> Self { + Self { + cause: Box::new(Cause::NBT(e)), + } + } +} + +impl From> for Error { + fn from(e: valence::ident::IdentError) -> Self { + Self { + cause: Box::new(Cause::IdentityError(e)), + } + } +} + +#[derive(Debug)] +pub enum Cause { + Io(io::Error), + Parse(ParseError), + NBT(valence::nbt::Error), + IdentityError(valence::ident::IdentError), +} + +#[derive(Debug)] +pub enum ParseError { + UnknownCompressionScheme(u8), + InvalidChunkSize(usize), + MissingNBT(&'static str), + InvalidNBT(&'static str), + InvalidPalette, + UnknownType(Ident), +} + +#[derive(Debug)] +pub enum SerializeError { + // ChunkTooLarge +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &*self.cause { + Cause::Io(e) => e.fmt(f), + Cause::Parse(err) => err.fmt(f), + Cause::NBT(e) => e.fmt(f), + Cause::IdentityError(e) => e.fmt(f), + } + } +} + +impl Display for ParseError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { + write!(f, "Parse failed") + } +} + +impl Display for SerializeError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { + write!(f, "Serialization failed") + } +} \ No newline at end of file diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs new file mode 100644 index 000000000..be47f9469 --- /dev/null +++ b/valence_anvil/src/lib.rs @@ -0,0 +1,524 @@ +mod error; +mod palette; + +use std::collections::BTreeMap; +use std::fmt::{Debug, Formatter, Result as FmtResult}; +use std::io::{SeekFrom}; +use std::path::{Path, PathBuf}; + +use async_compression::tokio::bufread::ZlibDecoder; +use async_compression::tokio::write::GzipDecoder; +use byteorder::{BigEndian, ByteOrder}; +use tokio::fs::File; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWriteExt}; +use tokio::sync::Mutex; +use valence::biome::BiomeId; +use valence::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::ident::Ident; +use valence::nbt::{Compound, List, Value}; + +use crate::error::Error; +use crate::palette::DataFormat; + +#[derive(Debug)] +pub struct AnvilWorld { + world_root: PathBuf, + region_files: Mutex>>>, +} + +impl AnvilWorld { + pub fn new(directory: PathBuf) -> Self { + Self { + world_root: directory, + region_files: Mutex::new(BTreeMap::new()), + } + } + + pub async fn load_chunks>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut map = BTreeMap::>::new(); + for pos in positions.into_iter() { + let region_pos = RegionPos::from(pos); + map.entry(region_pos) + .and_modify(|v| v.push(pos)) + .or_insert(vec![pos]); + } + + let mut result_vec = Vec::<(ChunkPos, Option)>::new(); + let mut lock = self.region_files.lock().await; + for (region_pos, chunk_pos_vec) in map.into_iter() { + if let Some(region) = lock.entry(region_pos).or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path).await?).await?) + } else { + None + } + }) { + // A region file exists, and it is loaded. + result_vec.extend(region.parse_chunks(chunk_pos_vec).await?); + } else { + // No region file exists, there is no data to load here. + result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); + } + } + + Ok(result_vec) + } +} + +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] +pub struct RegionPos { + x: i32, + z: i32, +} + +impl From for RegionPos { + fn from(pos: ChunkPos) -> Self { + Self { + x: pos.x >> 5, + z: pos.z >> 5, + } + } +} + +impl RegionPos { + pub fn path(self, world_root: impl AsRef) -> PathBuf { + world_root + .as_ref() + .join("region") + .join(format!("r.{}.{}.mca", self.x, self.z)) + } +} + +#[derive(Debug)] +pub struct Region { + source: Mutex, + offset: u64, + header: AnvilHeader, +} + +impl Region { + /// Convenience method, creates a Region object from the given file. + pub async fn from_file(source: File) -> Result { + Self::from_seek(Mutex::new(source), 0).await + } +} + +impl Region { + /// Creates a Region object using the incoming stream. The offset defines + /// the position of the header start. + pub async fn from_seek(source: Mutex, offset: u64) -> Result { + let mut lock = source.lock().await; + lock.seek(SeekFrom::Start(offset)).await?; + let header = AnvilHeader::parse(&mut *lock).await?; + drop(lock); + + Ok(Self { + source, + offset, + header, + }) + } + + async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { + let seek_pos = self + .header + .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); + + let mut lock = self.source.lock().await; + + lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) + .await?; + + if seek_pos.len() == 0 { + return Ok(None); + } + + let compressed_chunk_size = { + let mut buf = [0u8; 4]; + lock.read_exact(&mut buf).await?; + BigEndian::read_u32(&buf) as usize + }; + + if compressed_chunk_size == 0 { + return Err(Error::invalid_chunk_size(compressed_chunk_size)); + } + + let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; + let uncompressed_buffer = compression + .read_to_vec(&mut *lock, compressed_chunk_size - 1) + .await?; + Ok(Some(uncompressed_buffer)) + } + + pub async fn parse_chunks>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut results = Vec::<(ChunkPos, Option)>::new(); + + for pos in positions.into_iter() { + let chunk_data = self.read_chunk_data(pos).await?; + if let Some(chunk_data) = chunk_data { + let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; + let parsed_chunk = Self::parse_chunk_nbt(&mut nbt)?; + results.push((pos, Some(parsed_chunk))); + } else { + results.push((pos, None)); + } + } + + Ok(results) + } + + fn parse_chunk_nbt(nbt: &mut Compound) -> Result { + fn take_assume(compound: &mut Compound, key: &'static str) -> Result + where + Option: From, + { + match compound.remove(key) { + None => Err(Error::missing_nbt_value(key)), + Some(value) => { + if let Some(value) = Option::::from(value) { + Ok(value) + } else { + Err(Error::invalid_nbt(key)) + } + } + } + } + + fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option + where + Option: From, + { + match compound.remove(key) { + None => None, + Some(value) => Option::::from(value), + } + } + + // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; + // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; + // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; +// + // let _status: String = take_assume(nbt, "Status")?; + // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; + + if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { + let mut y_max = 0i8; + let mut y_min = 0i8; + + for chunk_nbt in nbt_sections.iter() { + if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { + y_max = y_max.max(*section_y); + y_min = y_min.min(*section_y); + } else { + return Err(Error::missing_nbt_value("sections/*/Y")); + } + } + + // Max should always be equal or higher than 'lower'. Therefore, this is positive. + let section_height = ((y_max - y_min) as usize * 16) + 16; + let y_raise = isize::from(-y_min) * 16; + + //Parsing sections + let mut chunk = UnloadedChunk::new(section_height); + for mut nbt_section in nbt_sections.into_iter() { + let chunk_y_offset: isize = + isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; + + // Block states + let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; + let parsed_block_state_palette: Vec = + if let Some(Value::List(List::Compound(nbt_palette_vec))) = + nbt_block_states.remove("palette") + { + let mut palette_vec: Vec = + Vec::with_capacity(nbt_palette_vec.len()); + for mut nbt_palette in nbt_palette_vec { + let block_id = valence::ident::Ident::new(take_assume::( + &mut nbt_palette, + "Name", + )?)?; + let block_kind = + if let Some(block_kind) = BlockKind::from_str(block_id.path()) { + block_kind + } else { + return Err(Error::unknown_type(block_id)); + }; + let mut block_state = BlockState::from_kind(block_kind); + if let Some(Value::Compound(nbt_palette_properties)) = + nbt_palette.remove("Properties") + { + for (property_name, property_value) in nbt_palette_properties { + if let Value::String(property_value) = property_value { + let property_name = PropName::from_str(&property_name); + let property_value = PropValue::from_str(&property_value); + if let (Some(property_name), Some(property_value)) = + (property_name, property_value) + { + block_state = + block_state.set(property_name, property_value); + } else { + return Err(Error::invalid_nbt( + "sections/*/block_states/Properties/*/property \ + value is not recognized.", + )); + } + } else { + return Err(Error::invalid_nbt( + "sections/*/block_states/Properties/*/property value \ + is invalid.", + )); + } + } + } + palette_vec.push(block_state); + } + palette_vec + } else { + return Err(Error::invalid_nbt("sections/*/palette")); + }; + + // Block state palette + palette::parse_palette::( + &parsed_block_state_palette, + take_assume_optional(&mut nbt_block_states, "data"), + 4, + &mut |data| { + match data { + DataFormat::All(state) => { + if !state.is_air() { + for x in 0..16 { + for y in 0..16isize { + for z in 0..16 { + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + } + } + } + DataFormat::Palette(index, state) => { + let y = (index >> 8 & 0b1111) as isize; + let z = index >> 4 & 0b1111; + let x = index & 0b1111; + + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + Ok(()) + }, + )?; + + // Biome palette + let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; + let parsed_biome_palette: Vec = + if let Some(Value::List(List::String(biome_names))) = + nbt_biomes.remove("palette") + { + let mut biomes: Vec = Vec::with_capacity(biome_names.len()); + for biome in biome_names { + let _identity_IMPLEMENT_ME = Ident::new(biome)?; + + //TODO: EXTRACT BIOME IDs + //TODO: BiomeId::from_str(identity.path()); + biomes.push(BiomeId::default()); + } + biomes + } else { + return Err(Error::invalid_nbt("sections/*/palette.")); + }; + + palette::parse_palette::( + &parsed_biome_palette, + take_assume_optional(&mut nbt_biomes, "data"), + 0, + &mut |data| { + match data { + DataFormat::All(biome) => { + for x in 0..4 { + for y in 0..4isize { + for z in 0..4 { + chunk.set_biome( + x, + (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, + z, + biome, + ); + } + } + } + } + DataFormat::Palette(index, biome) => { + let y = (index >> 4 & 0b11) as isize; + let z = index >> 2 & 0b11; + let x = index & 0b11; + + let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); + chunk.set_biome( + x, + final_y as usize, + z, + biome, + ); + } + } + Ok(()) + }, + )?; + } + + //sections + + Ok(chunk) + } else { + return Err(Error::invalid_nbt("sections tag invalid.")); + } + } +} + +#[derive(Copy, Clone, Debug)] +struct AnvilHeader { + offsets: [ChunkLocation; 1024], + timestamps: [ChunkTimestamp; 1024], +} + +impl AnvilHeader { + /// Parses the header bytes from the current position + async fn parse(source: &mut R) -> Result { + let mut offsets = [ChunkLocation::zero(); 1024]; + for offset in &mut offsets { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + offset.load(buf); + } + let mut timestamps = [ChunkTimestamp::zero(); 1024]; + for timestamp in &mut timestamps { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + timestamp.load(buf); + } + Ok(Self { + offsets, + timestamps, + }) + } + + #[inline(always)] + fn offset(&self, x: usize, z: usize) -> &ChunkLocation { + &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] + } + + #[inline(always)] + fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { + &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] + } +} + +/// The location of the chunk inside the region file. +#[derive(Copy, Clone, Debug)] +struct ChunkLocation { + offset_sectors: u32, + len_sectors: u8, +} + +impl ChunkLocation { + const fn zero() -> Self { + Self { + offset_sectors: 0, + len_sectors: 0, + } + } + + const fn offset(&self) -> u64 { + self.offset_sectors as u64 * 1024 * 4 + } + + const fn len(&self) -> usize { + self.len_sectors as usize * 1024 * 4 + } + + fn load(&mut self, chunk: [u8; 4]) { + self.offset_sectors = BigEndian::read_u24(&chunk[..3]); + self.len_sectors = chunk[3]; + } +} + +/// The timestamp when the chunk was last modified in seconds since epoch. +#[derive(Copy, Clone)] +struct ChunkTimestamp(u32); + +impl Debug for ChunkTimestamp { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}s", self.0) + } +} + +impl ChunkTimestamp { + const fn zero() -> Self { + Self(0) + } + + fn load(&mut self, chunk: [u8; 4]) { + self.0 = BigEndian::read_u32(&chunk) + } +} + +#[derive(Debug, Copy, Clone)] +enum CompressionScheme { + GZip = 1, + Zlib = 2, + Raw = 3, +} + +impl CompressionScheme { + fn from_raw(mode: u8) -> Result { + match mode { + 1 => Ok(Self::GZip), + 2 => Ok(Self::Zlib), + 3 => Ok(Self::Raw), + mode => Err(Error::unknown_compression_scheme(mode)), + } + } + + async fn read_to_vec( + self, + source: &mut R, + length: usize, + ) -> Result, std::io::Error> { + let mut raw_data = vec![0u8; length]; + source.read_exact(&mut raw_data).await?; + match self { + CompressionScheme::GZip => { + let mut decoder = GzipDecoder::new(Vec::::new()); + decoder.write_all(&mut raw_data).await?; + decoder.shutdown().await?; + Ok(decoder.into_inner()) + } + CompressionScheme::Zlib => { + let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); + let mut vec = Vec::::new(); + decoder.read_to_end(&mut vec).await?; + Ok(vec) + } + CompressionScheme::Raw => { + Ok(raw_data) + } + } + } +} \ No newline at end of file diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs new file mode 100644 index 000000000..3113e5fc9 --- /dev/null +++ b/valence_anvil/src/palette.rs @@ -0,0 +1,67 @@ +use crate::error::Error; +use std::ops::BitXor; + +pub enum DataFormat { + All(T), + Palette(usize, T), +} + +pub fn parse_palette< + T: Copy, + F: (FnMut(DataFormat) -> Result<(), Error>) +>( + source: &Vec, + data: Option>, + min_bits: usize, + fun: &mut F, +) -> Result<(), Error> { + let palette_len = source.len(); + if let Some(data) = data { + if palette_len < 2 || data.is_empty() { + fun(DataFormat::All(source[0]))?; + Ok(()) + } else { + let choice_len = palette_len - 1; //Corrects for the absence of a non-choice: null is not an option. + let bits_per_index = usize::max( + (usize::BITS - choice_len.leading_zeros()) as usize, + min_bits, + ); + let entries_per_integer = i64::BITS as usize / bits_per_index; + + let mut entry_mask = (u64::MAX << bits_per_index).bitxor(u64::MAX); + let mut mask_fields: Vec<(u64, usize)> = vec![(0u64, 0usize); entries_per_integer]; + for i in 0..mask_fields.len() { + mask_fields[i] = (entry_mask, (i * bits_per_index)); + entry_mask = entry_mask << bits_per_index; + } + + let mut index: usize = 0; + for integer in data { + let integer = integer as u64; + for (mask, rev_shift) in &mask_fields { + let palette_index_unshifted = (integer & mask) as usize; + let palette_index_shifted = palette_index_unshifted >> rev_shift; + + // Uncomment the following to aid in debugging. + // println!("IN + // \t{integer:064b}\nMSK\t{mask:064b}({bits_per_index})\nRES\ + // t{palette_index_unshifted:064b}\nSFT\t{palette_index_shifted:064b} + // ({rev_shift} - {trailing_bits})\n"); + if palette_index_shifted > choice_len { + //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", + // palette_index_shifted, choice_len, + // bits_per_index, source, source.len()); + return Err(crate::error::Error::invalid_palette()); + } else { + fun(DataFormat::Palette(index, source[palette_index_shifted]))?; + index += 1; + } + } + } + Ok(()) + } + } else { + fun(DataFormat::All(source[0]))?; + Ok(()) + } +} \ No newline at end of file From eb5f17b3c1c923e4590d6ace856f3fdecd5d1de3 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 15:48:59 +0200 Subject: [PATCH 29/75] Java part: Biome parsing --- extracted/biomes.json | 5483 +++++++++++++++++ .../valence/extractor/extractors/Biomes.java | 106 + 2 files changed, 5589 insertions(+) create mode 100644 extracted/biomes.json create mode 100644 extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java diff --git a/extracted/biomes.json b/extracted/biomes.json new file mode 100644 index 000000000..da9810e47 --- /dev/null +++ b/extracted/biomes.json @@ -0,0 +1,5483 @@ +[ + { + "name": "minecraft:the_void", + "id": 0, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:plains", + "id": 1, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:sunflower_plains", + "id": 2, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_plains", + "id": 3, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.07, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:ice_spikes", + "id": 4, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.07, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:desert", + "id": 5, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:swamp", + "id": 6, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "swamp", + "foliage": 6975545, + "fog": 12638463, + "sky": 7907327, + "water_fog": 2302743, + "water": 6388580 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:mangrove_swamp", + "id": 7, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "swamp", + "foliage": 9285927, + "fog": 12638463, + "sky": 7907327, + "water_fog": 5077600, + "water": 3832426 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:forest", + "id": 8, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:flower_forest", + "id": 9, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:birch_forest", + "id": 10, + "weather": { + "precipitation": "rain", + "temperature": 0.6, + "downfall": 0.6 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8037887, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:dark_forest", + "id": 11, + "weather": { + "precipitation": "rain", + "temperature": 0.7, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "dark_forest", + "foliage": null, + "fog": 12638463, + "sky": 7972607, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_birch_forest", + "id": 12, + "weather": { + "precipitation": "rain", + "temperature": 0.6, + "downfall": 0.6 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8037887, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_pine_taiga", + "id": 13, + "weather": { + "precipitation": "rain", + "temperature": 0.3, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8168447, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:old_growth_spruce_taiga", + "id": 14, + "weather": { + "precipitation": "rain", + "temperature": 0.25, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233983, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:taiga", + "id": 15, + "weather": { + "precipitation": "rain", + "temperature": 0.25, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233983, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_taiga", + "id": 16, + "weather": { + "precipitation": "snow", + "temperature": -0.5, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8625919, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:savanna", + "id": 17, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:savanna_plateau", + "id": 18, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_hills", + "id": 19, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_gravelly_hills", + "id": 20, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_forest", + "id": 21, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:windswept_savanna", + "id": 22, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:jungle", + "id": 23, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:sparse_jungle", + "id": 24, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:bamboo_jungle", + "id": 25, + "weather": { + "precipitation": "rain", + "temperature": 0.95, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:badlands", + "id": 26, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:eroded_badlands", + "id": 27, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:wooded_badlands", + "id": 28, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": 9470285, + "grass_modifier": "none", + "foliage": 10387789, + "fog": 12638463, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:meadow", + "id": 29, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 937679 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:grove", + "id": 30, + "weather": { + "precipitation": "snow", + "temperature": -0.2, + "downfall": 0.8 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8495359, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_slopes", + "id": 31, + "weather": { + "precipitation": "snow", + "temperature": -0.3, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8560639, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_peaks", + "id": 32, + "weather": { + "precipitation": "snow", + "temperature": -0.7, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8756735, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:jagged_peaks", + "id": 33, + "weather": { + "precipitation": "snow", + "temperature": -0.7, + "downfall": 0.9 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8756735, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:stony_peaks", + "id": 34, + "weather": { + "precipitation": "rain", + "temperature": 1.0, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7776511, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:river", + "id": 35, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_river", + "id": 36, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:beach", + "id": 37, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:snowy_beach", + "id": 38, + "weather": { + "precipitation": "snow", + "temperature": 0.05, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:stony_shore", + "id": 39, + "weather": { + "precipitation": "rain", + "temperature": 0.2, + "downfall": 0.3 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8233727, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:warm_ocean", + "id": 40, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 270131, + "water": 4445678 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:lukewarm_ocean", + "id": 41, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 267827, + "water": 4566514 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_lukewarm_ocean", + "id": 42, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 267827, + "water": 4566514 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:ocean", + "id": 43, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_ocean", + "id": 44, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:cold_ocean", + "id": 45, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_cold_ocean", + "id": 46, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4020182 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:frozen_ocean", + "id": 47, + "weather": { + "precipitation": "snow", + "temperature": 0.0, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8364543, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_frozen_ocean", + "id": 48, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 3750089 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:mushroom_fields", + "id": 49, + "weather": { + "precipitation": "rain", + "temperature": 0.9, + "downfall": 1.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7842047, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:dripstone_caves", + "id": 50, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:lush_caves", + "id": 51, + "weather": { + "precipitation": "rain", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 8103167, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:deep_dark", + "id": 52, + "weather": { + "precipitation": "rain", + "temperature": 0.8, + "downfall": 0.4 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 12638463, + "sky": 7907327, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:nether_wastes", + "id": 53, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 3344392, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:warped_forest", + "id": 54, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 1705242, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:crimson_forest", + "id": 55, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 3343107, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:soul_sand_valley", + "id": 56, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 1787717, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:basalt_deltas", + "id": 57, + "weather": { + "precipitation": "none", + "temperature": 2.0, + "downfall": 0.0 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 6840176, + "sky": 7254527, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:the_end", + "id": 58, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_highlands", + "id": 59, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_midlands", + "id": 60, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:small_end_islands", + "id": 61, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + }, + { + "name": "minecraft:end_barrens", + "id": 62, + "weather": { + "precipitation": "none", + "temperature": 0.5, + "downfall": 0.5 + }, + "color": { + "grass": null, + "grass_modifier": "none", + "foliage": null, + "fog": 10518688, + "sky": 0, + "water_fog": 329011, + "water": 4159204 + }, + "spawn_settings": { + "probability": 0.1, + "groups": [ + { + "name": "monster", + "capacity": 70, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": false, + "is_rare": false + }, + { + "name": "creature", + "capacity": 10, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + }, + { + "name": "ambient", + "capacity": 15, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "axolotls", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "underground_water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_creature", + "capacity": 5, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "water_ambient", + "capacity": 20, + "despawn_range_start": 32, + "despawn_range_immediate": 64, + "is_peaceful": true, + "is_rare": false + }, + { + "name": "misc", + "capacity": -1, + "despawn_range_start": 32, + "despawn_range_immediate": 128, + "is_peaceful": true, + "is_rare": true + } + ] + } + } +] \ No newline at end of file diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java new file mode 100644 index 000000000..2a452f0f8 --- /dev/null +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -0,0 +1,106 @@ +package rs.valence.extractor.extractors; + +import com.google.gson.*; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.registry.BuiltinRegistries; +import rs.valence.extractor.Main; + +import java.util.LinkedList; +import java.util.Optional; + +public class Biomes implements Main.Extractor { + public Biomes() { + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private JsonElement optional_to_json(Optional var){ + if(var.isEmpty()){ + return JsonNull.INSTANCE; + }else{ + var value = var.get(); + if(value instanceof Boolean){ + return new JsonPrimitive((Boolean) value); + }else if(value instanceof Integer){ + return new JsonPrimitive((Integer) value); + }else if(value instanceof Float){ + return new JsonPrimitive((Float) value); + }else if(value instanceof Long){ + return new JsonPrimitive((Long) value); + }else if(value instanceof Number){ + return new JsonPrimitive((Number) value); + }else{ + throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); + } + } + } + + @Override + public String fileName() { + return "biomes.json"; + } + + @Override + public JsonElement extract() { + var results = new LinkedList(); + for (var biome_key : BuiltinRegistries.BIOME.getKeys()){ + var identifier = biome_key.getValue(); + var biome = BuiltinRegistries.BIOME.get(identifier); + assert biome != null; + + var biomeJson = new JsonObject(); + + var weatherJson = new JsonObject(); + weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); + weatherJson.addProperty("temperature", biome.getTemperature()); + weatherJson.addProperty("downfall", biome.getDownfall()); + + var colorJson = new JsonObject(); + var biome_effects = biome.getEffects(); + colorJson.add("grass", optional_to_json(biome_effects.getGrassColor())); + colorJson.addProperty("grass_modifier", biome_effects.getGrassColorModifier().getName()); + colorJson.add("foliage", optional_to_json(biome_effects.getFoliageColor())); + colorJson.addProperty("fog", biome_effects.getFogColor()); + colorJson.addProperty("sky", biome_effects.getSkyColor()); + colorJson.addProperty("water_fog", biome_effects.getWaterFogColor()); + colorJson.addProperty("water", biome_effects.getWaterColor()); + + var spawnSettingsJson = new JsonObject(); + var spawnSettings = biome.getSpawnSettings(); + spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); + + var spawn_groups = new JsonArray(); + for (var spawn_group : SpawnGroup.values()){ + var group = new JsonObject(); + group.addProperty("name", spawn_group.getName()); + group.addProperty("capacity", spawn_group.getCapacity()); + group.addProperty("despawn_range_start", spawn_group.getDespawnStartRange()); + group.addProperty("despawn_range_immediate", spawn_group.getImmediateDespawnRange()); + group.addProperty("is_peaceful", spawn_group.isPeaceful()); + group.addProperty("is_rare", spawn_group.isRare()); + + spawn_groups.add(group); + } + spawnSettingsJson.add("groups", spawn_groups); + + biomeJson.addProperty("name",identifier.toString()); + biomeJson.addProperty("id",BuiltinRegistries.BIOME.getRawId(biome)); + biomeJson.add("weather", weatherJson); + biomeJson.add("color", colorJson); + biomeJson.add("spawn_settings", spawnSettingsJson); + + results.add(biomeJson); + } + + results.sort((one, two) -> { + try{ + return one.get("id").getAsInt() - two.get("id").getAsInt(); + }catch (Exception e){ + throw new RuntimeException(e); + } + }); + + var biomesJson = new JsonArray(results.size()); + results.forEach(biomesJson::add); + return biomesJson; + } +} From c98e61f5f5c312cdb27f902fb9f46d01fea2d5bf Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 22:09:32 +0200 Subject: [PATCH 30/75] Rust part: Biome parsing --- build/biome.rs | 375 +++++++++++++++++++++++++++++++++++++++++++++++++ src/biomes.rs | 4 + src/lib.rs | 1 + 3 files changed, 380 insertions(+) create mode 100644 build/biome.rs create mode 100644 src/biomes.rs diff --git a/build/biome.rs b/build/biome.rs new file mode 100644 index 000000000..e8e5157d5 --- /dev/null +++ b/build/biome.rs @@ -0,0 +1,375 @@ +use std::collections::{BTreeMap}; + +use heck::{ToPascalCase, ToSnakeCase}; +use proc_macro2::{Ident, TokenStream}; +use quote::{quote}; +use serde::Deserialize; + +use crate::ident; + +#[derive(Deserialize, Debug)] +pub struct ParsedBiome { + id: u16, + name: String, + weather: ParsedBiomeWeather, + color: ParsedBiomeColor, + spawn_settings: ParsedBiomeSpawnSettings, +} + +#[derive(Debug)] +pub struct RenamedBiome { + id: u16, + name: String, + rustified_name: Ident, + weather: ParsedBiomeWeather, + color: ParsedBiomeColor, + spawn_settings: ParsedBiomeSpawnSettings, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeWeather { + precipitation: String, + temperature: f32, + downfall: f32, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeColor { + grass_modifier: String, + grass: Option, + foliage: Option, + fog: i32, + sky: i32, + water_fog: i32, + water: i32, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeSpawnSettings { + probability: f32, + groups: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct ParsedBiomeGroupSpawnSettings { + name: String, + capacity: i32, + despawn_range_start: i32, + despawn_range_immediate: i32, + is_peaceful: bool, + is_rare: bool, +} + +pub fn build() -> anyhow::Result { + let biomes: Vec = serde_json::from_str(include_str!("../extracted/biomes.json"))?; + + let biomes = biomes + .into_iter() + .map(|biome| RenamedBiome { + id: biome.id, + rustified_name: ident(&biome.name.replace("minecraft:", "").to_pascal_case()), + name: biome.name, + weather: biome.weather, + color: biome.color, + spawn_settings: biome.spawn_settings, + }) + .collect::>(); + + let mut precipitation_types = BTreeMap::<&str, Ident>::new(); + let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); + let mut biome_group_spawn_types = BTreeMap::<&str, (Ident, Ident)>::new(); + for biome in biomes.iter() { + precipitation_types + .entry(biome.weather.precipitation.as_str()) + .or_insert_with(|| ident(biome.weather.precipitation.to_pascal_case())); + grass_modifier_types + .entry(biome.color.grass_modifier.as_str()) + .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); + for group in biome.spawn_settings.groups.iter() { + biome_group_spawn_types + .entry(group.name.as_str()) + .or_insert_with(|| { + ( + ident({ + let mut identity = group.name.to_snake_case(); + identity.insert_str(0, "group_"); + identity + }), + ident({ + let mut identity = group.name.to_pascal_case(); + identity.push_str("SpawnSettings"); + identity + }), + ) + }); + } + } + + fn option_to_quote(input: &Option) -> TokenStream { + match input { + Some(value) => quote!(Some(#value)), + None => quote!(None), + } + } + + let biome_kind_definitions = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let id = biome.id as isize; + quote! { + #rustified_name = #id, + } + }) + .collect::(); + + let biomekind_id_to_variant_lookup = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let id = &biome.id; + quote! { + #id => Some(Self::#rustified_name), + } + }) + .collect::(); + + let precipitation_names = precipitation_types + .iter() + .map(|(_, rust_id)| { + quote! { + pub #rust_id, + } + }) + .collect::(); + + let grass_modifier_names = grass_modifier_types + .iter() + .map(|(_, rust_id)| { + quote! { + pub #rust_id, + } + }) + .collect::(); + + let biomekind_names = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let name = &biome.name; + quote! { + Self::#rustified_name => #name, + } + }) + .collect::(); + + let biome_spawn_settings_fields = biome_group_spawn_types + .iter() + .map(|(_, (field, ident))| { + quote! { + pub #field: #ident, + } + }) + .collect::(); + + let biome_spawn_settings_structs = biome_group_spawn_types.iter().map(|(_, (_, ident))| ident); + + let biomekind_weather = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let precipitation = precipitation_types + .get(biome.weather.precipitation.as_str()) + .expect("Could not find previously generated precipitation"); + let downfall = &biome.weather.downfall; + let temperature = &biome.weather.temperature; + quote! { + Self::#rustified_name => BiomeWeather { + precipitation: Precipitation::#precipitation, + downfall: #downfall, + temperature: #temperature, + }, + } + }) + .collect::(); + + let biomekind_color = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let grass_modifier = grass_modifier_types + .get(biome.color.grass_modifier.as_str()) + .expect("Could not find previously generated grass modifier"); + let grass = option_to_quote(&biome.color.grass); + let foliage = option_to_quote(&biome.color.foliage); + let fog = &biome.color.fog; + let sky = &biome.color.sky; + let water_fog = &biome.color.water_fog; + let water = &biome.color.water; + quote! { + Self::#rustified_name => BiomeColor { + grass_modifier: GrassModifier::#grass_modifier, + grass: #grass, + foliage: #foliage, + fog: #fog, + sky: #sky, + water_fog: #water_fog, + water: #water, + }, + } + }) + .collect::(); + + let biomekind_spawn_settings_arms = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + let probability = biome.spawn_settings.probability; + + let fields = biome.spawn_settings.groups.iter().map(|parsed_biome|{ + let (_, (field, declaration)) = biome_group_spawn_types.iter().find(|(name,_)| parsed_biome.name.as_str() == **name).expect("Could not find previously generated spawn type"); + let capacity = &parsed_biome.capacity; + let despawn_range_start = &parsed_biome.despawn_range_start; + let despawn_range_immediate = &parsed_biome.despawn_range_immediate; + let is_peaceful = &parsed_biome.is_peaceful; + let is_rare = &parsed_biome.is_rare; + quote! { + #field: #declaration{ + capacity: #capacity, + despawn_range_start: #despawn_range_start, + despawn_range_immediate: #despawn_range_immediate, + is_peaceful: #is_peaceful, + is_rare: #is_rare + } + } + }); + quote! { + Self::#rustified_name => VanillaBiomeSpawnSettings { + probability: #probability, + #( #fields ),* + }, + } + }) + .collect::(); + + Ok(quote! { + pub trait BiomeSpawnSettings { + fn capacity(&self) -> i32; + fn despawn_range_start(&self) -> i32; + fn despawn_range_immediate(&self) -> i32; + fn is_peaceful(&self) -> bool; + fn is_rare(&self) -> bool; + } + + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct BiomeWeather { + pub precipitation: Precipitation, + pub temperature: f32, + pub downfall: f32, + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum Precipitation { + #precipitation_names + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct BiomeColor { + pub grass_modifier: GrassModifier, + pub grass: Option, + pub foliage: Option, + pub fog: i32, + pub sky: i32, + pub water_fog: i32, + pub water: i32, + } + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum GrassModifier { + #grass_modifier_names + } + + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct VanillaBiomeSpawnSettings { + pub probability: f32, + #biome_spawn_settings_fields + } + + #( #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct #biome_spawn_settings_structs { + pub capacity: i32, + pub despawn_range_start: i32, + pub despawn_range_immediate: i32, + pub is_peaceful: bool, + pub is_rare: bool, + } + + impl BiomeSpawnSettings for #biome_spawn_settings_structs{ + fn capacity(&self) -> i32 { + self.capacity + } + fn despawn_range_start(&self) -> i32 { + self.despawn_range_start + } + fn despawn_range_immediate(&self) -> i32 { + self.despawn_range_immediate + } + fn is_peaceful(&self) -> bool { + self.is_peaceful + } + fn is_rare(&self) -> bool { + self.is_rare + } + } )* + + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum BiomeKind { + #biome_kind_definitions + } + + impl BiomeKind { + /// Constructs an `BiomeKind` from a raw biome ID. + /// + /// If the given ID is invalid, `None` is returned. + pub const fn from_raw(id: u16) -> Option { + match id { + #biomekind_id_to_variant_lookup + _ => None + } + } + + /// Returns the raw biome ID. + pub const fn to_raw(self) -> u16 { + self as u16 + } + + /// Returns the biome name with both the namespace and path (eg: minecraft:plains) + pub const fn name(self) -> &'static str { + match self{ + #biomekind_names + } + } + + /// Gets the biome weather settings + pub const fn weather(self) -> BiomeWeather { + match self{ + #biomekind_weather + } + } + + /// Gets the biome color settings + pub const fn color(self) -> BiomeColor { + match self{ + #biomekind_color + } + } + + /// Gets the biome spawn settings + pub const fn spawn_settings(self) -> VanillaBiomeSpawnSettings { + match self{ + #biomekind_spawn_settings_arms + } + } + } + }) +} diff --git a/src/biomes.rs b/src/biomes.rs new file mode 100644 index 000000000..dd8f04eb5 --- /dev/null +++ b/src/biomes.rs @@ -0,0 +1,4 @@ +// biome.rs exposes constant values provided by the build script. +// All biome variants are located in `BiomeKind`. You can use the +// associated const fn functions of `BiomeKind` to access details about a biome type. +include!(concat!(env!("OUT_DIR"), "/biome.rs")); \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 8e00ce748..be880fb98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,6 +118,7 @@ mod slab_versioned; pub mod spatial_index; pub mod util; pub mod world; +pub mod biomes; /// Use `valence::prelude::*` to import the most commonly used items from the /// library. From db206150ab0317822599dfa3fd8708182a46376e Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 23 Oct 2022 22:48:43 +0200 Subject: [PATCH 31/75] Rework biome extraction: Spawn rates --- extracted/biomes.json | 9370 +++++++++-------- .../valence/extractor/extractors/Biomes.java | 24 +- 2 files changed, 5226 insertions(+), 4168 deletions(-) diff --git a/extracted/biomes.json b/extracted/biomes.json index da9810e47..c979de145 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -18,72 +18,16 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -105,72 +49,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -192,72 +180,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -279,72 +311,98 @@ }, "spawn_settings": { "probability": 0.07, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -366,72 +424,98 @@ }, "spawn_settings": { "probability": 0.07, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -453,72 +537,92 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 19 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:husk", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -540,72 +644,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -627,72 +775,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -714,72 +889,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -801,72 +1014,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -888,72 +1139,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -975,72 +1258,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1062,72 +1377,104 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1149,72 +1496,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 25 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1236,72 +1633,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1323,72 +1770,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1410,72 +1907,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1497,72 +2044,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1584,72 +2175,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1671,72 +2312,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1758,72 +2437,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1845,72 +2562,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -1932,72 +2687,116 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2019,72 +2818,128 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:ocelot", + "min_group_size": 1, + "max_group_size": 3, + "weight": 2 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "minecraft:panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2106,72 +2961,110 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2193,72 +3086,128 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:ocelot", + "min_group_size": 1, + "max_group_size": 1, + "weight": 2 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "minecraft:panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 80 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2280,72 +3229,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2367,72 +3323,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2454,72 +3417,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2541,72 +3511,98 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:donkey", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 6, + "weight": 2 + }, + { + "name": "minecraft:sheep", + "min_group_size": 2, + "max_group_size": 4, + "weight": 2 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2628,72 +3624,122 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "minecraft:pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2715,72 +3761,92 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2802,72 +3868,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2889,72 +3969,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -2976,72 +4070,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3063,72 +4164,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 100 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } }, { @@ -3150,72 +4278,99 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } }, { @@ -3237,72 +4392,86 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:turtle", + "min_group_size": 2, + "max_group_size": 5, + "weight": 5 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3324,72 +4493,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3411,72 +4587,79 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -3498,72 +4681,111 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 15 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3585,72 +4807,117 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 2, + "weight": 10 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3672,72 +4939,117 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 8 + }, + { + "name": "minecraft:pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -3759,72 +5071,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } }, { @@ -3846,72 +5191,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } }, { @@ -3933,72 +5311,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4020,72 +5431,105 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "minecraft:cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4107,72 +5551,106 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4194,72 +5672,106 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "minecraft:squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "minecraft:salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } }, { @@ -4281,72 +5793,37 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [ + { + "name": "minecraft:mooshroom", + "min_group_size": 4, + "max_group_size": 8, + "weight": 8 + } + ], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4368,72 +5845,85 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:drowned", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4455,72 +5945,93 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "minecraft:zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "minecraft:skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "minecraft:witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "minecraft:bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [ + { + "name": "minecraft:axolotl", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "underground_water_creature": [ + { + "name": "minecraft:glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "minecraft:tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } }, { @@ -4542,72 +6053,16 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4629,72 +6084,54 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "minecraft:zombified_piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "minecraft:magma_cube", + "min_group_size": 4, + "max_group_size": 4, + "weight": 2 + }, + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 15 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4716,72 +6153,30 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4803,72 +6198,42 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:zombified_piglin", + "min_group_size": 2, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "minecraft:hoglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 9 + }, + { + "name": "minecraft:piglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 5 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4890,72 +6255,42 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:skeleton", + "min_group_size": 5, + "max_group_size": 5, + "weight": 20 + }, + { + "name": "minecraft:ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -4977,72 +6312,36 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:ghast", + "min_group_size": 1, + "max_group_size": 1, + "weight": 40 + }, + { + "name": "minecraft:magma_cube", + "min_group_size": 2, + "max_group_size": 5, + "weight": 100 + } + ], + "creature": [ + { + "name": "minecraft:strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5064,72 +6363,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5151,72 +6401,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5238,72 +6439,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5325,72 +6477,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } }, { @@ -5412,72 +6515,23 @@ }, "spawn_settings": { "probability": 0.1, - "groups": [ - { - "name": "monster", - "capacity": 70, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": false, - "is_rare": false - }, - { - "name": "creature", - "capacity": 10, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - }, - { - "name": "ambient", - "capacity": 15, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "axolotls", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "underground_water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_creature", - "capacity": 5, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "water_ambient", - "capacity": 20, - "despawn_range_start": 32, - "despawn_range_immediate": 64, - "is_peaceful": true, - "is_rare": false - }, - { - "name": "misc", - "capacity": -1, - "despawn_range_start": 32, - "despawn_range_immediate": 128, - "is_peaceful": true, - "is_rare": true - } - ] + "groups": { + "monster": [ + { + "name": "minecraft:enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } ] \ No newline at end of file diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index 2a452f0f8..cb27981ad 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -2,6 +2,7 @@ import com.google.gson.*; import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; import rs.valence.extractor.Main; @@ -68,17 +69,20 @@ public JsonElement extract() { var spawnSettings = biome.getSpawnSettings(); spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); - var spawn_groups = new JsonArray(); + var spawn_groups = new JsonObject(); for (var spawn_group : SpawnGroup.values()){ - var group = new JsonObject(); - group.addProperty("name", spawn_group.getName()); - group.addProperty("capacity", spawn_group.getCapacity()); - group.addProperty("despawn_range_start", spawn_group.getDespawnStartRange()); - group.addProperty("despawn_range_immediate", spawn_group.getImmediateDespawnRange()); - group.addProperty("is_peaceful", spawn_group.isPeaceful()); - group.addProperty("is_rare", spawn_group.isRare()); - - spawn_groups.add(group); + var spawns_within_group = new JsonArray(); + for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()){ + var within_group = new JsonObject(); + // Depreciated method to get the entity namespace and path. + //noinspection deprecation + within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); + within_group.addProperty("min_group_size", entry.minGroupSize); + within_group.addProperty("max_group_size", entry.maxGroupSize); + within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawns_within_group.add(within_group); + } + spawn_groups.add(spawn_group.asString(), spawns_within_group); } spawnSettingsJson.add("groups", spawn_groups); From e2442b6690dde1b93b8628741e6ab74647ee4e8c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 24 Oct 2022 00:15:47 +0200 Subject: [PATCH 32/75] Rust part: Biome parsing --- build/biome.rs | 158 +++++++++++++++++-------------------------------- src/biomes.rs | 5 +- 2 files changed, 58 insertions(+), 105 deletions(-) diff --git a/build/biome.rs b/build/biome.rs index e8e5157d5..efaf8c7bf 100644 --- a/build/biome.rs +++ b/build/biome.rs @@ -1,40 +1,40 @@ -use std::collections::{BTreeMap}; +use std::collections::{BTreeMap, HashMap}; use heck::{ToPascalCase, ToSnakeCase}; use proc_macro2::{Ident, TokenStream}; -use quote::{quote}; +use quote::quote; use serde::Deserialize; use crate::ident; #[derive(Deserialize, Debug)] -pub struct ParsedBiome { +struct ParsedBiome { id: u16, name: String, weather: ParsedBiomeWeather, color: ParsedBiomeColor, - spawn_settings: ParsedBiomeSpawnSettings, + spawn_settings: ParsedBiomeSpawnRates, } #[derive(Debug)] -pub struct RenamedBiome { +struct RenamedBiome { id: u16, name: String, rustified_name: Ident, weather: ParsedBiomeWeather, color: ParsedBiomeColor, - spawn_settings: ParsedBiomeSpawnSettings, + spawn_rates: ParsedBiomeSpawnRates, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeWeather { +struct ParsedBiomeWeather { precipitation: String, temperature: f32, downfall: f32, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeColor { +struct ParsedBiomeColor { grass_modifier: String, grass: Option, foliage: Option, @@ -45,19 +45,17 @@ pub struct ParsedBiomeColor { } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeSpawnSettings { +struct ParsedBiomeSpawnRates { probability: f32, - groups: Vec, + groups: HashMap>, } #[derive(Deserialize, Debug)] -pub struct ParsedBiomeGroupSpawnSettings { +struct ParsedSpawnRate { name: String, - capacity: i32, - despawn_range_start: i32, - despawn_range_immediate: i32, - is_peaceful: bool, - is_rare: bool, + min_group_size: u32, + max_group_size: u32, + weight: i32, } pub fn build() -> anyhow::Result { @@ -71,13 +69,13 @@ pub fn build() -> anyhow::Result { name: biome.name, weather: biome.weather, color: biome.color, - spawn_settings: biome.spawn_settings, + spawn_rates: biome.spawn_settings, }) .collect::>(); let mut precipitation_types = BTreeMap::<&str, Ident>::new(); let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); - let mut biome_group_spawn_types = BTreeMap::<&str, (Ident, Ident)>::new(); + let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); for biome in biomes.iter() { precipitation_types .entry(biome.weather.precipitation.as_str()) @@ -85,23 +83,10 @@ pub fn build() -> anyhow::Result { grass_modifier_types .entry(biome.color.grass_modifier.as_str()) .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); - for group in biome.spawn_settings.groups.iter() { - biome_group_spawn_types - .entry(group.name.as_str()) - .or_insert_with(|| { - ( - ident({ - let mut identity = group.name.to_snake_case(); - identity.insert_str(0, "group_"); - identity - }), - ident({ - let mut identity = group.name.to_pascal_case(); - identity.push_str("SpawnSettings"); - identity - }), - ) - }); + for class in biome.spawn_rates.groups.keys() { + class_spawn_fields + .entry(class) + .or_insert_with(|| ident(class.to_snake_case())); } } @@ -138,7 +123,7 @@ pub fn build() -> anyhow::Result { .iter() .map(|(_, rust_id)| { quote! { - pub #rust_id, + #rust_id, } }) .collect::(); @@ -147,7 +132,7 @@ pub fn build() -> anyhow::Result { .iter() .map(|(_, rust_id)| { quote! { - pub #rust_id, + #rust_id, } }) .collect::(); @@ -163,17 +148,6 @@ pub fn build() -> anyhow::Result { }) .collect::(); - let biome_spawn_settings_fields = biome_group_spawn_types - .iter() - .map(|(_, (field, ident))| { - quote! { - pub #field: #ident, - } - }) - .collect::(); - - let biome_spawn_settings_structs = biome_group_spawn_types.iter().map(|(_, (_, ident))| ident); - let biomekind_weather = biomes .iter() .map(|biome| { @@ -224,27 +198,30 @@ pub fn build() -> anyhow::Result { .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let probability = biome.spawn_settings.probability; - - let fields = biome.spawn_settings.groups.iter().map(|parsed_biome|{ - let (_, (field, declaration)) = biome_group_spawn_types.iter().find(|(name,_)| parsed_biome.name.as_str() == **name).expect("Could not find previously generated spawn type"); - let capacity = &parsed_biome.capacity; - let despawn_range_start = &parsed_biome.despawn_range_start; - let despawn_range_immediate = &parsed_biome.despawn_range_immediate; - let is_peaceful = &parsed_biome.is_peaceful; - let is_rare = &parsed_biome.is_rare; - quote! { - #field: #declaration{ - capacity: #capacity, - despawn_range_start: #despawn_range_start, - despawn_range_immediate: #despawn_range_immediate, - is_peaceful: #is_peaceful, - is_rare: #is_rare + let probability = biome.spawn_rates.probability; + + let fields = biome.spawn_rates.groups.iter().map(|(class, rates)| { + let rates = rates.iter().map(|spawn_rate| { + let name = &spawn_rate.name; + let min_group_size = &spawn_rate.min_group_size; + let max_group_size = &spawn_rate.max_group_size; + let weight = &spawn_rate.weight; + quote! { + SpawnEntry { + name: #name, + min_group_size: #min_group_size, + max_group_size: #max_group_size, + weight: #weight + } } + }); + let class = ident(class); + quote! { + #class: &[#( #rates ),*] } }); quote! { - Self::#rustified_name => VanillaBiomeSpawnSettings { + Self::#rustified_name => VanillaBiomeSpawnRates { probability: #probability, #( #fields ),* }, @@ -252,13 +229,15 @@ pub fn build() -> anyhow::Result { }) .collect::(); + let spawn_classes = class_spawn_fields.values(); + Ok(quote! { - pub trait BiomeSpawnSettings { - fn capacity(&self) -> i32; - fn despawn_range_start(&self) -> i32; - fn despawn_range_immediate(&self) -> i32; - fn is_peaceful(&self) -> bool; - fn is_rare(&self) -> bool; + #[derive(Debug, Clone, PartialEq, PartialOrd)] + pub struct SpawnEntry { + pub name: &'static str, + pub min_group_size: u32, + pub max_group_size: u32, + pub weight: i32 } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] @@ -289,39 +268,12 @@ pub fn build() -> anyhow::Result { #grass_modifier_names } - #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] - pub struct VanillaBiomeSpawnSettings { + #[derive(Debug, Clone, PartialEq, PartialOrd)] + pub struct VanillaBiomeSpawnRates { pub probability: f32, - #biome_spawn_settings_fields + #( pub #spawn_classes: &'static [SpawnEntry] ),* } - #( #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct #biome_spawn_settings_structs { - pub capacity: i32, - pub despawn_range_start: i32, - pub despawn_range_immediate: i32, - pub is_peaceful: bool, - pub is_rare: bool, - } - - impl BiomeSpawnSettings for #biome_spawn_settings_structs{ - fn capacity(&self) -> i32 { - self.capacity - } - fn despawn_range_start(&self) -> i32 { - self.despawn_range_start - } - fn despawn_range_immediate(&self) -> i32 { - self.despawn_range_immediate - } - fn is_peaceful(&self) -> bool { - self.is_peaceful - } - fn is_rare(&self) -> bool { - self.is_rare - } - } )* - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BiomeKind { #biome_kind_definitions @@ -364,8 +316,8 @@ pub fn build() -> anyhow::Result { } } - /// Gets the biome spawn settings - pub const fn spawn_settings(self) -> VanillaBiomeSpawnSettings { + /// Gets the biome spawn rates + pub const fn spawn_rates(self) -> VanillaBiomeSpawnRates { match self{ #biomekind_spawn_settings_arms } diff --git a/src/biomes.rs b/src/biomes.rs index dd8f04eb5..96c84504b 100644 --- a/src/biomes.rs +++ b/src/biomes.rs @@ -1,4 +1,5 @@ // biome.rs exposes constant values provided by the build script. // All biome variants are located in `BiomeKind`. You can use the -// associated const fn functions of `BiomeKind` to access details about a biome type. -include!(concat!(env!("OUT_DIR"), "/biome.rs")); \ No newline at end of file +// associated const fn functions of `BiomeKind` to access details about a biome +// type. +include!(concat!(env!("OUT_DIR"), "/biome.rs")); From 354e165d0270aebef5c1df4143eb05e5adfc05c8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 23 Oct 2022 15:48:49 -0700 Subject: [PATCH 33/75] Run formatter --- .../valence/extractor/extractors/Biomes.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index cb27981ad..c829dcf0f 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -14,22 +14,22 @@ public Biomes() { } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private JsonElement optional_to_json(Optional var){ - if(var.isEmpty()){ + private JsonElement optional_to_json(Optional var) { + if (var.isEmpty()) { return JsonNull.INSTANCE; - }else{ + } else { var value = var.get(); - if(value instanceof Boolean){ + if (value instanceof Boolean) { return new JsonPrimitive((Boolean) value); - }else if(value instanceof Integer){ + } else if (value instanceof Integer) { return new JsonPrimitive((Integer) value); - }else if(value instanceof Float){ + } else if (value instanceof Float) { return new JsonPrimitive((Float) value); - }else if(value instanceof Long){ + } else if (value instanceof Long) { return new JsonPrimitive((Long) value); - }else if(value instanceof Number){ + } else if (value instanceof Number) { return new JsonPrimitive((Number) value); - }else{ + } else { throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); } } @@ -43,7 +43,7 @@ public String fileName() { @Override public JsonElement extract() { var results = new LinkedList(); - for (var biome_key : BuiltinRegistries.BIOME.getKeys()){ + for (var biome_key : BuiltinRegistries.BIOME.getKeys()) { var identifier = biome_key.getValue(); var biome = BuiltinRegistries.BIOME.get(identifier); assert biome != null; @@ -70,24 +70,24 @@ public JsonElement extract() { spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); var spawn_groups = new JsonObject(); - for (var spawn_group : SpawnGroup.values()){ + for (var spawn_group : SpawnGroup.values()) { var spawns_within_group = new JsonArray(); - for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()){ - var within_group = new JsonObject(); - // Depreciated method to get the entity namespace and path. - //noinspection deprecation - within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); - within_group.addProperty("min_group_size", entry.minGroupSize); - within_group.addProperty("max_group_size", entry.maxGroupSize); - within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); - spawns_within_group.add(within_group); - } + for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()) { + var within_group = new JsonObject(); + // Depreciated method to get the entity namespace and path. + //noinspection deprecation + within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); + within_group.addProperty("min_group_size", entry.minGroupSize); + within_group.addProperty("max_group_size", entry.maxGroupSize); + within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawns_within_group.add(within_group); + } spawn_groups.add(spawn_group.asString(), spawns_within_group); } spawnSettingsJson.add("groups", spawn_groups); - biomeJson.addProperty("name",identifier.toString()); - biomeJson.addProperty("id",BuiltinRegistries.BIOME.getRawId(biome)); + biomeJson.addProperty("name", identifier.toString()); + biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); biomeJson.add("weather", weatherJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); @@ -96,9 +96,9 @@ public JsonElement extract() { } results.sort((one, two) -> { - try{ + try { return one.get("id").getAsInt() - two.get("id").getAsInt(); - }catch (Exception e){ + } catch (Exception e) { throw new RuntimeException(e); } }); From e85034599684dc39719177a50f6899a73b06a652 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 23 Oct 2022 18:32:47 -0700 Subject: [PATCH 34/75] Adjustments --- extracted/biomes.json | 1578 ++++++++--------- .../valence/extractor/extractors/Biomes.java | 90 +- src/biome.rs | 10 + src/biomes.rs | 5 - 4 files changed, 837 insertions(+), 846 deletions(-) delete mode 100644 src/biomes.rs diff --git a/extracted/biomes.json b/extracted/biomes.json index c979de145..ae5d543b4 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -1,6 +1,6 @@ [ { - "name": "minecraft:the_void", + "name": "the_void", "id": 0, "weather": { "precipitation": "none", @@ -31,7 +31,7 @@ } }, { - "name": "minecraft:plains", + "name": "plains", "id": 1, "weather": { "precipitation": "rain", @@ -52,49 +52,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -102,37 +102,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 5 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 3, "weight": 1 @@ -140,7 +140,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -149,7 +149,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -162,7 +162,7 @@ } }, { - "name": "minecraft:sunflower_plains", + "name": "sunflower_plains", "id": 2, "weather": { "precipitation": "rain", @@ -183,49 +183,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -233,37 +233,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 5 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 3, "weight": 1 @@ -271,7 +271,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -280,7 +280,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -293,7 +293,7 @@ } }, { - "name": "minecraft:snowy_plains", + "name": "snowy_plains", "id": 3, "weather": { "precipitation": "snow", @@ -314,55 +314,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 20 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:stray", + "name": "stray", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -370,13 +370,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 10 }, { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -384,7 +384,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -393,7 +393,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -406,7 +406,7 @@ } }, { - "name": "minecraft:ice_spikes", + "name": "ice_spikes", "id": 4, "weather": { "precipitation": "snow", @@ -427,55 +427,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 20 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:stray", + "name": "stray", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -483,13 +483,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 10 }, { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -497,7 +497,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -506,7 +506,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -519,7 +519,7 @@ } }, { - "name": "minecraft:desert", + "name": "desert", "id": 5, "weather": { "precipitation": "none", @@ -540,55 +540,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 19 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 1 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:husk", + "name": "husk", "min_group_size": 4, "max_group_size": 4, "weight": 80 @@ -596,7 +596,7 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 @@ -604,7 +604,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -613,7 +613,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -626,7 +626,7 @@ } }, { - "name": "minecraft:swamp", + "name": "swamp", "id": 6, "weather": { "precipitation": "rain", @@ -647,55 +647,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -703,31 +703,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:frog", + "name": "frog", "min_group_size": 2, "max_group_size": 5, "weight": 10 @@ -735,7 +735,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -744,7 +744,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -757,7 +757,7 @@ } }, { - "name": "minecraft:mangrove_swamp", + "name": "mangrove_swamp", "id": 7, "weather": { "precipitation": "rain", @@ -778,55 +778,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -834,7 +834,7 @@ ], "creature": [ { - "name": "minecraft:frog", + "name": "frog", "min_group_size": 2, "max_group_size": 5, "weight": 10 @@ -842,7 +842,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -851,7 +851,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -860,7 +860,7 @@ "water_creature": [], "water_ambient": [ { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -871,7 +871,7 @@ } }, { - "name": "minecraft:forest", + "name": "forest", "id": 8, "weather": { "precipitation": "rain", @@ -892,49 +892,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -942,31 +942,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 5 @@ -974,7 +974,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -983,7 +983,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -996,7 +996,7 @@ } }, { - "name": "minecraft:flower_forest", + "name": "flower_forest", "id": 9, "weather": { "precipitation": "rain", @@ -1017,49 +1017,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1067,31 +1067,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 @@ -1099,7 +1099,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1108,7 +1108,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1121,7 +1121,7 @@ } }, { - "name": "minecraft:birch_forest", + "name": "birch_forest", "id": 10, "weather": { "precipitation": "rain", @@ -1142,49 +1142,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1192,25 +1192,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1218,7 +1218,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1227,7 +1227,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1240,7 +1240,7 @@ } }, { - "name": "minecraft:dark_forest", + "name": "dark_forest", "id": 11, "weather": { "precipitation": "rain", @@ -1261,49 +1261,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1311,25 +1311,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1337,7 +1337,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1346,7 +1346,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1359,7 +1359,7 @@ } }, { - "name": "minecraft:old_growth_birch_forest", + "name": "old_growth_birch_forest", "id": 12, "weather": { "precipitation": "rain", @@ -1380,49 +1380,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1430,25 +1430,25 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -1456,7 +1456,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1465,7 +1465,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1478,7 +1478,7 @@ } }, { - "name": "minecraft:old_growth_pine_taiga", + "name": "old_growth_pine_taiga", "id": 13, "weather": { "precipitation": "rain", @@ -1499,49 +1499,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 25 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1549,43 +1549,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1593,7 +1593,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1602,7 +1602,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1615,7 +1615,7 @@ } }, { - "name": "minecraft:old_growth_spruce_taiga", + "name": "old_growth_spruce_taiga", "id": 14, "weather": { "precipitation": "rain", @@ -1636,49 +1636,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1686,43 +1686,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1730,7 +1730,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1739,7 +1739,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1752,7 +1752,7 @@ } }, { - "name": "minecraft:taiga", + "name": "taiga", "id": 15, "weather": { "precipitation": "rain", @@ -1773,49 +1773,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1823,43 +1823,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -1867,7 +1867,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -1876,7 +1876,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -1889,7 +1889,7 @@ } }, { - "name": "minecraft:snowy_taiga", + "name": "snowy_taiga", "id": 16, "weather": { "precipitation": "snow", @@ -1910,49 +1910,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -1960,43 +1960,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -2004,7 +2004,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2013,7 +2013,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2026,7 +2026,7 @@ } }, { - "name": "minecraft:savanna", + "name": "savanna", "id": 17, "weather": { "precipitation": "none", @@ -2047,49 +2047,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2097,37 +2097,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -2135,7 +2135,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2144,7 +2144,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2157,7 +2157,7 @@ } }, { - "name": "minecraft:savanna_plateau", + "name": "savanna_plateau", "id": 18, "weather": { "precipitation": "none", @@ -2178,49 +2178,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2228,43 +2228,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 4, "weight": 8 @@ -2272,7 +2272,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2281,7 +2281,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2294,7 +2294,7 @@ } }, { - "name": "minecraft:windswept_hills", + "name": "windswept_hills", "id": 19, "weather": { "precipitation": "rain", @@ -2315,49 +2315,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2365,31 +2365,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2397,7 +2397,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2406,7 +2406,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2419,7 +2419,7 @@ } }, { - "name": "minecraft:windswept_gravelly_hills", + "name": "windswept_gravelly_hills", "id": 20, "weather": { "precipitation": "rain", @@ -2440,49 +2440,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2490,31 +2490,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2522,7 +2522,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2531,7 +2531,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2544,7 +2544,7 @@ } }, { - "name": "minecraft:windswept_forest", + "name": "windswept_forest", "id": 21, "weather": { "precipitation": "rain", @@ -2565,49 +2565,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2615,31 +2615,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:llama", + "name": "llama", "min_group_size": 4, "max_group_size": 6, "weight": 5 @@ -2647,7 +2647,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2656,7 +2656,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2669,7 +2669,7 @@ } }, { - "name": "minecraft:windswept_savanna", + "name": "windswept_savanna", "id": 22, "weather": { "precipitation": "none", @@ -2690,49 +2690,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -2740,37 +2740,37 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:horse", + "name": "horse", "min_group_size": 2, "max_group_size": 6, "weight": 1 }, { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -2778,7 +2778,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2787,7 +2787,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2800,7 +2800,7 @@ } }, { - "name": "minecraft:jungle", + "name": "jungle", "id": 23, "weather": { "precipitation": "rain", @@ -2821,55 +2821,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:ocelot", + "name": "ocelot", "min_group_size": 1, "max_group_size": 3, "weight": 2 @@ -2877,43 +2877,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:parrot", + "name": "parrot", "min_group_size": 1, "max_group_size": 2, "weight": 40 }, { - "name": "minecraft:panda", + "name": "panda", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -2921,7 +2921,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -2930,7 +2930,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -2943,7 +2943,7 @@ } }, { - "name": "minecraft:sparse_jungle", + "name": "sparse_jungle", "id": 24, "weather": { "precipitation": "rain", @@ -2964,49 +2964,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3014,31 +3014,31 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -3046,7 +3046,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3055,7 +3055,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3068,7 +3068,7 @@ } }, { - "name": "minecraft:bamboo_jungle", + "name": "bamboo_jungle", "id": 25, "weather": { "precipitation": "rain", @@ -3089,55 +3089,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:ocelot", + "name": "ocelot", "min_group_size": 1, "max_group_size": 1, "weight": 2 @@ -3145,43 +3145,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:parrot", + "name": "parrot", "min_group_size": 1, "max_group_size": 2, "weight": 40 }, { - "name": "minecraft:panda", + "name": "panda", "min_group_size": 1, "max_group_size": 2, "weight": 80 @@ -3189,7 +3189,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3198,7 +3198,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3211,7 +3211,7 @@ } }, { - "name": "minecraft:badlands", + "name": "badlands", "id": 26, "weather": { "precipitation": "none", @@ -3232,49 +3232,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3283,7 +3283,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3292,7 +3292,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3305,7 +3305,7 @@ } }, { - "name": "minecraft:eroded_badlands", + "name": "eroded_badlands", "id": 27, "weather": { "precipitation": "none", @@ -3326,49 +3326,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3377,7 +3377,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3386,7 +3386,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3399,7 +3399,7 @@ } }, { - "name": "minecraft:wooded_badlands", + "name": "wooded_badlands", "id": 28, "weather": { "precipitation": "none", @@ -3420,49 +3420,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3471,7 +3471,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3480,7 +3480,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3493,7 +3493,7 @@ } }, { - "name": "minecraft:meadow", + "name": "meadow", "id": 29, "weather": { "precipitation": "rain", @@ -3514,49 +3514,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3564,19 +3564,19 @@ ], "creature": [ { - "name": "minecraft:donkey", + "name": "donkey", "min_group_size": 1, "max_group_size": 2, "weight": 1 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 6, "weight": 2 }, { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 2, "max_group_size": 4, "weight": 2 @@ -3584,7 +3584,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3593,7 +3593,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3606,7 +3606,7 @@ } }, { - "name": "minecraft:grove", + "name": "grove", "id": 30, "weather": { "precipitation": "snow", @@ -3627,49 +3627,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3677,43 +3677,43 @@ ], "creature": [ { - "name": "minecraft:sheep", + "name": "sheep", "min_group_size": 4, "max_group_size": 4, "weight": 12 }, { - "name": "minecraft:pig", + "name": "pig", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:chicken", + "name": "chicken", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:cow", + "name": "cow", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:wolf", + "name": "wolf", "min_group_size": 4, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:fox", + "name": "fox", "min_group_size": 2, "max_group_size": 4, "weight": 8 @@ -3721,7 +3721,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3730,7 +3730,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3743,7 +3743,7 @@ } }, { - "name": "minecraft:snowy_slopes", + "name": "snowy_slopes", "id": 31, "weather": { "precipitation": "snow", @@ -3764,49 +3764,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3814,13 +3814,13 @@ ], "creature": [ { - "name": "minecraft:rabbit", + "name": "rabbit", "min_group_size": 2, "max_group_size": 3, "weight": 4 }, { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -3828,7 +3828,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3837,7 +3837,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3850,7 +3850,7 @@ } }, { - "name": "minecraft:frozen_peaks", + "name": "frozen_peaks", "id": 32, "weather": { "precipitation": "snow", @@ -3871,49 +3871,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -3921,7 +3921,7 @@ ], "creature": [ { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -3929,7 +3929,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -3938,7 +3938,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -3951,7 +3951,7 @@ } }, { - "name": "minecraft:jagged_peaks", + "name": "jagged_peaks", "id": 33, "weather": { "precipitation": "snow", @@ -3972,49 +3972,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4022,7 +4022,7 @@ ], "creature": [ { - "name": "minecraft:goat", + "name": "goat", "min_group_size": 1, "max_group_size": 3, "weight": 5 @@ -4030,7 +4030,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4039,7 +4039,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4052,7 +4052,7 @@ } }, { - "name": "minecraft:stony_peaks", + "name": "stony_peaks", "id": 34, "weather": { "precipitation": "rain", @@ -4073,49 +4073,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4124,7 +4124,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4133,7 +4133,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4146,7 +4146,7 @@ } }, { - "name": "minecraft:river", + "name": "river", "id": 35, "weather": { "precipitation": "rain", @@ -4167,55 +4167,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 100 @@ -4224,7 +4224,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4233,7 +4233,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4241,7 +4241,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 2 @@ -4249,7 +4249,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 5 @@ -4260,7 +4260,7 @@ } }, { - "name": "minecraft:frozen_river", + "name": "frozen_river", "id": 36, "weather": { "precipitation": "snow", @@ -4281,55 +4281,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 1 @@ -4338,7 +4338,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4347,7 +4347,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4355,7 +4355,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 2 @@ -4363,7 +4363,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 5 @@ -4374,7 +4374,7 @@ } }, { - "name": "minecraft:beach", + "name": "beach", "id": 37, "weather": { "precipitation": "rain", @@ -4395,49 +4395,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4445,7 +4445,7 @@ ], "creature": [ { - "name": "minecraft:turtle", + "name": "turtle", "min_group_size": 2, "max_group_size": 5, "weight": 5 @@ -4453,7 +4453,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4462,7 +4462,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4475,7 +4475,7 @@ } }, { - "name": "minecraft:snowy_beach", + "name": "snowy_beach", "id": 38, "weather": { "precipitation": "snow", @@ -4496,49 +4496,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4547,7 +4547,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4556,7 +4556,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4569,7 +4569,7 @@ } }, { - "name": "minecraft:stony_shore", + "name": "stony_shore", "id": 39, "weather": { "precipitation": "rain", @@ -4590,49 +4590,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4641,7 +4641,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4650,7 +4650,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4663,7 +4663,7 @@ } }, { - "name": "minecraft:warm_ocean", + "name": "warm_ocean", "id": 40, "weather": { "precipitation": "rain", @@ -4684,55 +4684,55 @@ "groups": { "monster": [ { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4741,7 +4741,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4750,7 +4750,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4758,13 +4758,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 4, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -4772,13 +4772,13 @@ ], "water_ambient": [ { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 15 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -4789,7 +4789,7 @@ } }, { - "name": "minecraft:lukewarm_ocean", + "name": "lukewarm_ocean", "id": 41, "weather": { "precipitation": "rain", @@ -4810,55 +4810,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4867,7 +4867,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -4876,7 +4876,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -4884,13 +4884,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 2, "weight": 10 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -4898,19 +4898,19 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 5 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -4921,7 +4921,7 @@ } }, { - "name": "minecraft:deep_lukewarm_ocean", + "name": "deep_lukewarm_ocean", "id": 42, "weather": { "precipitation": "rain", @@ -4942,55 +4942,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -4999,7 +4999,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5008,7 +5008,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5016,13 +5016,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 8 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 2 @@ -5030,19 +5030,19 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 8 }, { - "name": "minecraft:pufferfish", + "name": "pufferfish", "min_group_size": 1, "max_group_size": 3, "weight": 5 }, { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -5053,7 +5053,7 @@ } }, { - "name": "minecraft:ocean", + "name": "ocean", "id": 43, "weather": { "precipitation": "rain", @@ -5074,55 +5074,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5131,7 +5131,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5140,7 +5140,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5148,13 +5148,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5162,7 +5162,7 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 10 @@ -5173,7 +5173,7 @@ } }, { - "name": "minecraft:deep_ocean", + "name": "deep_ocean", "id": 44, "weather": { "precipitation": "rain", @@ -5194,55 +5194,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5251,7 +5251,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5260,7 +5260,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5268,13 +5268,13 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:dolphin", + "name": "dolphin", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5282,7 +5282,7 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 10 @@ -5293,7 +5293,7 @@ } }, { - "name": "minecraft:cold_ocean", + "name": "cold_ocean", "id": 45, "weather": { "precipitation": "rain", @@ -5314,55 +5314,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5371,7 +5371,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5380,7 +5380,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5388,7 +5388,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 3 @@ -5396,13 +5396,13 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5413,7 +5413,7 @@ } }, { - "name": "minecraft:deep_cold_ocean", + "name": "deep_cold_ocean", "id": 46, "weather": { "precipitation": "rain", @@ -5434,55 +5434,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5491,7 +5491,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5500,7 +5500,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5508,7 +5508,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 3 @@ -5516,13 +5516,13 @@ ], "water_ambient": [ { - "name": "minecraft:cod", + "name": "cod", "min_group_size": 3, "max_group_size": 6, "weight": 15 }, { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5533,7 +5533,7 @@ } }, { - "name": "minecraft:frozen_ocean", + "name": "frozen_ocean", "id": 47, "weather": { "precipitation": "snow", @@ -5554,55 +5554,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5610,7 +5610,7 @@ ], "creature": [ { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5618,7 +5618,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5627,7 +5627,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5635,7 +5635,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 @@ -5643,7 +5643,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5654,7 +5654,7 @@ } }, { - "name": "minecraft:deep_frozen_ocean", + "name": "deep_frozen_ocean", "id": 48, "weather": { "precipitation": "rain", @@ -5675,55 +5675,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5731,7 +5731,7 @@ ], "creature": [ { - "name": "minecraft:polar_bear", + "name": "polar_bear", "min_group_size": 1, "max_group_size": 2, "weight": 1 @@ -5739,7 +5739,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5748,7 +5748,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5756,7 +5756,7 @@ ], "water_creature": [ { - "name": "minecraft:squid", + "name": "squid", "min_group_size": 1, "max_group_size": 4, "weight": 1 @@ -5764,7 +5764,7 @@ ], "water_ambient": [ { - "name": "minecraft:salmon", + "name": "salmon", "min_group_size": 1, "max_group_size": 5, "weight": 15 @@ -5775,7 +5775,7 @@ } }, { - "name": "minecraft:mushroom_fields", + "name": "mushroom_fields", "id": 49, "weather": { "precipitation": "rain", @@ -5797,7 +5797,7 @@ "monster": [], "creature": [ { - "name": "minecraft:mooshroom", + "name": "mooshroom", "min_group_size": 4, "max_group_size": 8, "weight": 8 @@ -5805,7 +5805,7 @@ ], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5814,7 +5814,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5827,7 +5827,7 @@ } }, { - "name": "minecraft:dripstone_caves", + "name": "dripstone_caves", "id": 50, "weather": { "precipitation": "rain", @@ -5848,55 +5848,55 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:drowned", + "name": "drowned", "min_group_size": 4, "max_group_size": 4, "weight": 95 @@ -5905,7 +5905,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -5914,7 +5914,7 @@ "axolotls": [], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -5927,7 +5927,7 @@ } }, { - "name": "minecraft:lush_caves", + "name": "lush_caves", "id": 51, "weather": { "precipitation": "rain", @@ -5948,49 +5948,49 @@ "groups": { "monster": [ { - "name": "minecraft:spider", + "name": "spider", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:zombie", + "name": "zombie", "min_group_size": 4, "max_group_size": 4, "weight": 95 }, { - "name": "minecraft:zombie_villager", + "name": "zombie_villager", "min_group_size": 1, "max_group_size": 1, "weight": 5 }, { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:creeper", + "name": "creeper", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:slime", + "name": "slime", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 1, "max_group_size": 4, "weight": 10 }, { - "name": "minecraft:witch", + "name": "witch", "min_group_size": 1, "max_group_size": 1, "weight": 5 @@ -5999,7 +5999,7 @@ "creature": [], "ambient": [ { - "name": "minecraft:bat", + "name": "bat", "min_group_size": 8, "max_group_size": 8, "weight": 10 @@ -6007,7 +6007,7 @@ ], "axolotls": [ { - "name": "minecraft:axolotl", + "name": "axolotl", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -6015,7 +6015,7 @@ ], "underground_water_creature": [ { - "name": "minecraft:glow_squid", + "name": "glow_squid", "min_group_size": 4, "max_group_size": 6, "weight": 10 @@ -6024,7 +6024,7 @@ "water_creature": [], "water_ambient": [ { - "name": "minecraft:tropical_fish", + "name": "tropical_fish", "min_group_size": 8, "max_group_size": 8, "weight": 25 @@ -6035,7 +6035,7 @@ } }, { - "name": "minecraft:deep_dark", + "name": "deep_dark", "id": 52, "weather": { "precipitation": "rain", @@ -6066,7 +6066,7 @@ } }, { - "name": "minecraft:nether_wastes", + "name": "nether_wastes", "id": 53, "weather": { "precipitation": "none", @@ -6087,31 +6087,31 @@ "groups": { "monster": [ { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 4, "max_group_size": 4, "weight": 50 }, { - "name": "minecraft:zombified_piglin", + "name": "zombified_piglin", "min_group_size": 4, "max_group_size": 4, "weight": 100 }, { - "name": "minecraft:magma_cube", + "name": "magma_cube", "min_group_size": 4, "max_group_size": 4, "weight": 2 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:piglin", + "name": "piglin", "min_group_size": 4, "max_group_size": 4, "weight": 15 @@ -6119,7 +6119,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6135,7 +6135,7 @@ } }, { - "name": "minecraft:warped_forest", + "name": "warped_forest", "id": 54, "weather": { "precipitation": "none", @@ -6156,7 +6156,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 @@ -6164,7 +6164,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6180,7 +6180,7 @@ } }, { - "name": "minecraft:crimson_forest", + "name": "crimson_forest", "id": 55, "weather": { "precipitation": "none", @@ -6201,19 +6201,19 @@ "groups": { "monster": [ { - "name": "minecraft:zombified_piglin", + "name": "zombified_piglin", "min_group_size": 2, "max_group_size": 4, "weight": 1 }, { - "name": "minecraft:hoglin", + "name": "hoglin", "min_group_size": 3, "max_group_size": 4, "weight": 9 }, { - "name": "minecraft:piglin", + "name": "piglin", "min_group_size": 3, "max_group_size": 4, "weight": 5 @@ -6221,7 +6221,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6237,7 +6237,7 @@ } }, { - "name": "minecraft:soul_sand_valley", + "name": "soul_sand_valley", "id": 56, "weather": { "precipitation": "none", @@ -6258,19 +6258,19 @@ "groups": { "monster": [ { - "name": "minecraft:skeleton", + "name": "skeleton", "min_group_size": 5, "max_group_size": 5, "weight": 20 }, { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 4, "max_group_size": 4, "weight": 50 }, { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 1 @@ -6278,7 +6278,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6294,7 +6294,7 @@ } }, { - "name": "minecraft:basalt_deltas", + "name": "basalt_deltas", "id": 57, "weather": { "precipitation": "none", @@ -6315,13 +6315,13 @@ "groups": { "monster": [ { - "name": "minecraft:ghast", + "name": "ghast", "min_group_size": 1, "max_group_size": 1, "weight": 40 }, { - "name": "minecraft:magma_cube", + "name": "magma_cube", "min_group_size": 2, "max_group_size": 5, "weight": 100 @@ -6329,7 +6329,7 @@ ], "creature": [ { - "name": "minecraft:strider", + "name": "strider", "min_group_size": 1, "max_group_size": 2, "weight": 60 @@ -6345,7 +6345,7 @@ } }, { - "name": "minecraft:the_end", + "name": "the_end", "id": 58, "weather": { "precipitation": "none", @@ -6366,7 +6366,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6383,7 +6383,7 @@ } }, { - "name": "minecraft:end_highlands", + "name": "end_highlands", "id": 59, "weather": { "precipitation": "none", @@ -6404,7 +6404,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6421,7 +6421,7 @@ } }, { - "name": "minecraft:end_midlands", + "name": "end_midlands", "id": 60, "weather": { "precipitation": "none", @@ -6442,7 +6442,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6459,7 +6459,7 @@ } }, { - "name": "minecraft:small_end_islands", + "name": "small_end_islands", "id": 61, "weather": { "precipitation": "none", @@ -6480,7 +6480,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 @@ -6497,7 +6497,7 @@ } }, { - "name": "minecraft:end_barrens", + "name": "end_barrens", "id": 62, "weather": { "precipitation": "none", @@ -6518,7 +6518,7 @@ "groups": { "monster": [ { - "name": "minecraft:enderman", + "name": "enderman", "min_group_size": 4, "max_group_size": 4, "weight": 10 diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index c829dcf0f..0c88b1e98 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -4,9 +4,9 @@ import net.minecraft.entity.SpawnGroup; import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; import rs.valence.extractor.Main; -import java.util.LinkedList; import java.util.Optional; public class Biomes implements Main.Extractor { @@ -14,21 +14,21 @@ public Biomes() { } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private JsonElement optional_to_json(Optional var) { + private static JsonElement optional_to_json(Optional var) { if (var.isEmpty()) { return JsonNull.INSTANCE; } else { var value = var.get(); - if (value instanceof Boolean) { - return new JsonPrimitive((Boolean) value); - } else if (value instanceof Integer) { - return new JsonPrimitive((Integer) value); - } else if (value instanceof Float) { - return new JsonPrimitive((Float) value); - } else if (value instanceof Long) { - return new JsonPrimitive((Long) value); - } else if (value instanceof Number) { - return new JsonPrimitive((Number) value); + if (value instanceof Boolean b) { + return new JsonPrimitive(b); + } else if (value instanceof Integer i) { + return new JsonPrimitive(i); + } else if (value instanceof Float f) { + return new JsonPrimitive(f); + } else if (value instanceof Long l) { + return new JsonPrimitive(l); + } else if (value instanceof Number n) { + return new JsonPrimitive(n); } else { throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); } @@ -42,13 +42,10 @@ public String fileName() { @Override public JsonElement extract() { - var results = new LinkedList(); - for (var biome_key : BuiltinRegistries.BIOME.getKeys()) { - var identifier = biome_key.getValue(); - var biome = BuiltinRegistries.BIOME.get(identifier); - assert biome != null; + var biomesJson = new JsonArray(); - var biomeJson = new JsonObject(); + for (var biome : BuiltinRegistries.BIOME) { + var biomeIdent = BuiltinRegistries.BIOME.getId(biome); var weatherJson = new JsonObject(); weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); @@ -56,55 +53,44 @@ public JsonElement extract() { weatherJson.addProperty("downfall", biome.getDownfall()); var colorJson = new JsonObject(); - var biome_effects = biome.getEffects(); - colorJson.add("grass", optional_to_json(biome_effects.getGrassColor())); - colorJson.addProperty("grass_modifier", biome_effects.getGrassColorModifier().getName()); - colorJson.add("foliage", optional_to_json(biome_effects.getFoliageColor())); - colorJson.addProperty("fog", biome_effects.getFogColor()); - colorJson.addProperty("sky", biome_effects.getSkyColor()); - colorJson.addProperty("water_fog", biome_effects.getWaterFogColor()); - colorJson.addProperty("water", biome_effects.getWaterColor()); + var biomeEffects = biome.getEffects(); + colorJson.add("grass", optional_to_json(biomeEffects.getGrassColor())); + colorJson.addProperty("grass_modifier", biomeEffects.getGrassColorModifier().getName()); + colorJson.add("foliage", optional_to_json(biomeEffects.getFoliageColor())); + colorJson.addProperty("fog", biomeEffects.getFogColor()); + colorJson.addProperty("sky", biomeEffects.getSkyColor()); + colorJson.addProperty("water_fog", biomeEffects.getWaterFogColor()); + colorJson.addProperty("water", biomeEffects.getWaterColor()); var spawnSettingsJson = new JsonObject(); var spawnSettings = biome.getSpawnSettings(); spawnSettingsJson.addProperty("probability", spawnSettings.getCreatureSpawnProbability()); - var spawn_groups = new JsonObject(); - for (var spawn_group : SpawnGroup.values()) { - var spawns_within_group = new JsonArray(); - for (var entry : spawnSettings.getSpawnEntries(spawn_group).getEntries()) { - var within_group = new JsonObject(); - // Depreciated method to get the entity namespace and path. - //noinspection deprecation - within_group.addProperty("name", entry.type.getRegistryEntry().registryKey().getValue().toString()); - within_group.addProperty("min_group_size", entry.minGroupSize); - within_group.addProperty("max_group_size", entry.maxGroupSize); - within_group.addProperty("weight", ((Weighted) entry).getWeight().getValue()); - spawns_within_group.add(within_group); + var spawnGroupsJson = new JsonObject(); + for (var spawnGroup : SpawnGroup.values()) { + var spawnGroupJson = new JsonArray(); + for (var entry : spawnSettings.getSpawnEntries(spawnGroup).getEntries()) { + var groupEntryJson = new JsonObject(); + groupEntryJson.addProperty("name", Registry.ENTITY_TYPE.getId(entry.type).getPath()); + groupEntryJson.addProperty("min_group_size", entry.minGroupSize); + groupEntryJson.addProperty("max_group_size", entry.maxGroupSize); + groupEntryJson.addProperty("weight", ((Weighted) entry).getWeight().getValue()); + spawnGroupJson.add(groupEntryJson); } - spawn_groups.add(spawn_group.asString(), spawns_within_group); + spawnGroupsJson.add(spawnGroup.getName(), spawnGroupJson); } - spawnSettingsJson.add("groups", spawn_groups); + spawnSettingsJson.add("groups", spawnGroupsJson); - biomeJson.addProperty("name", identifier.toString()); + var biomeJson = new JsonObject(); + biomeJson.addProperty("name", biomeIdent.getPath()); biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); biomeJson.add("weather", weatherJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); - results.add(biomeJson); + biomesJson.add(biomeJson); } - results.sort((one, two) -> { - try { - return one.get("id").getAsInt() - two.get("id").getAsInt(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - - var biomesJson = new JsonArray(results.size()); - results.forEach(biomesJson::add); return biomesJson; } } diff --git a/src/biome.rs b/src/biome.rs index 676a6f328..9279b40f1 100644 --- a/src/biome.rs +++ b/src/biome.rs @@ -8,6 +8,16 @@ use valence_nbt::{compound, Compound}; use valence_protocol::ident; use valence_protocol::ident::Ident; +pub mod default { + //! Contains data for the default Minecraft biomes. + //! + //! All biome variants are located in [`BiomeKind`]. You can use the + //! associated const functions of [`BiomeKind`] to access details about a + //! biome type. + + include!(concat!(env!("OUT_DIR"), "/biome.rs")); +} + /// Identifies a particular [`Biome`] on the server. /// /// The default biome ID refers to the first biome added in the server's diff --git a/src/biomes.rs b/src/biomes.rs deleted file mode 100644 index 96c84504b..000000000 --- a/src/biomes.rs +++ /dev/null @@ -1,5 +0,0 @@ -// biome.rs exposes constant values provided by the build script. -// All biome variants are located in `BiomeKind`. You can use the -// associated const fn functions of `BiomeKind` to access details about a biome -// type. -include!(concat!(env!("OUT_DIR"), "/biome.rs")); From 4f7be795565f1c58f5e0a9e428453928e4919917 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 24 Oct 2022 21:54:47 +0200 Subject: [PATCH 35/75] Unify extracted biomes with valence --- build/biome.rs | 177 ++++++++---------- extracted/biomes.json | 126 ++++++------- .../valence/extractor/extractors/Biomes.java | 10 +- 3 files changed, 144 insertions(+), 169 deletions(-) diff --git a/build/biome.rs b/build/biome.rs index efaf8c7bf..1845cddb7 100644 --- a/build/biome.rs +++ b/build/biome.rs @@ -11,7 +11,7 @@ use crate::ident; struct ParsedBiome { id: u16, name: String, - weather: ParsedBiomeWeather, + climate: ParsedBiomeClimate, color: ParsedBiomeColor, spawn_settings: ParsedBiomeSpawnRates, } @@ -21,13 +21,13 @@ struct RenamedBiome { id: u16, name: String, rustified_name: Ident, - weather: ParsedBiomeWeather, + climate: ParsedBiomeClimate, color: ParsedBiomeColor, spawn_rates: ParsedBiomeSpawnRates, } #[derive(Deserialize, Debug)] -struct ParsedBiomeWeather { +struct ParsedBiomeClimate { precipitation: String, temperature: f32, downfall: f32, @@ -36,12 +36,12 @@ struct ParsedBiomeWeather { #[derive(Deserialize, Debug)] struct ParsedBiomeColor { grass_modifier: String, - grass: Option, - foliage: Option, - fog: i32, - sky: i32, - water_fog: i32, - water: i32, + grass: Option, + foliage: Option, + fog: u32, + sky: u32, + water_fog: u32, + water: u32, } #[derive(Deserialize, Debug)] @@ -67,7 +67,7 @@ pub fn build() -> anyhow::Result { id: biome.id, rustified_name: ident(&biome.name.replace("minecraft:", "").to_pascal_case()), name: biome.name, - weather: biome.weather, + climate: biome.climate, color: biome.color, spawn_rates: biome.spawn_settings, }) @@ -78,8 +78,8 @@ pub fn build() -> anyhow::Result { let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); for biome in biomes.iter() { precipitation_types - .entry(biome.weather.precipitation.as_str()) - .or_insert_with(|| ident(biome.weather.precipitation.to_pascal_case())); + .entry(biome.climate.precipitation.as_str()) + .or_insert_with(|| ident(biome.climate.precipitation.to_pascal_case())); grass_modifier_types .entry(biome.color.grass_modifier.as_str()) .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); @@ -119,77 +119,69 @@ pub fn build() -> anyhow::Result { }) .collect::(); - let precipitation_names = precipitation_types + let biomekind_name_lookup = biomes .iter() - .map(|(_, rust_id)| { - quote! { - #rust_id, - } - }) - .collect::(); - - let grass_modifier_names = grass_modifier_types - .iter() - .map(|(_, rust_id)| { + .map(|biome| { + let rustified_name = &biome.rustified_name; + let name = &biome.name; quote! { - #rust_id, + #name => Some(Self::#rustified_name), } }) .collect::(); - let biomekind_names = biomes + let biomekind_temperatures_arms = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let name = &biome.name; + let temp = &biome.climate.temperature; quote! { - Self::#rustified_name => #name, + Self::#rustified_name => #temp, } }) .collect::(); - let biomekind_weather = biomes + let biomekind_downfall_arms = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let precipitation = precipitation_types - .get(biome.weather.precipitation.as_str()) - .expect("Could not find previously generated precipitation"); - let downfall = &biome.weather.downfall; - let temperature = &biome.weather.temperature; + let downfall = &biome.climate.downfall; quote! { - Self::#rustified_name => BiomeWeather { - precipitation: Precipitation::#precipitation, - downfall: #downfall, - temperature: #temperature, - }, + Self::#rustified_name => #downfall, } }) .collect::(); - let biomekind_color = biomes + let biomekind_to_biome = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; - let grass_modifier = grass_modifier_types - .get(biome.color.grass_modifier.as_str()) - .expect("Could not find previously generated grass modifier"); - let grass = option_to_quote(&biome.color.grass); - let foliage = option_to_quote(&biome.color.foliage); - let fog = &biome.color.fog; - let sky = &biome.color.sky; + let name = &biome.name; + let precipitation = ident(&biome.climate.precipitation.to_pascal_case()); + let sky_color = &biome.color.sky; let water_fog = &biome.color.water_fog; - let water = &biome.color.water; + let fog = &biome.color.fog; + let water_color = &biome.color.water; + let foliage_color = option_to_quote(&biome.color.foliage); + let grass_color = option_to_quote(&biome.color.grass); + let grass_modifier = ident(&biome.color.grass_modifier.to_pascal_case()); quote! { - Self::#rustified_name => BiomeColor { - grass_modifier: GrassModifier::#grass_modifier, - grass: #grass, - foliage: #foliage, - fog: #fog, - sky: #sky, - water_fog: #water_fog, - water: #water, - }, + Self::#rustified_name => Ok(Biome{ + name: Ident::from_str(#name)?, + precipitation: BiomePrecipitation::#precipitation, + sky_color: #sky_color, + water_fog_color: #water_fog, + fog_color: #fog, + water_color: #water_color, + foliage_color: #foliage_color, + grass_color: #grass_color, + grass_color_modifier: BiomeGrassColorModifier::#grass_modifier, + music: None, + ambient_sound: None, + additions_sound: None, + mood_sound: None, + particle: None, + }), } }) .collect::(); @@ -207,7 +199,7 @@ pub fn build() -> anyhow::Result { let max_group_size = &spawn_rate.max_group_size; let weight = &spawn_rate.weight; quote! { - SpawnEntry { + SpawnProperty { name: #name, min_group_size: #min_group_size, max_group_size: #max_group_size, @@ -221,7 +213,7 @@ pub fn build() -> anyhow::Result { } }); quote! { - Self::#rustified_name => VanillaBiomeSpawnRates { + Self::#rustified_name => SpawnSettings { probability: #probability, #( #fields ),* }, @@ -232,46 +224,22 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { + use super::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; + use crate::ident::{Ident,IdentError}; + use std::str::FromStr; + #[derive(Debug, Clone, PartialEq, PartialOrd)] - pub struct SpawnEntry { + pub struct SpawnProperty { pub name: &'static str, pub min_group_size: u32, pub max_group_size: u32, pub weight: i32 } - #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] - pub struct BiomeWeather { - pub precipitation: Precipitation, - pub temperature: f32, - pub downfall: f32, - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum Precipitation { - #precipitation_names - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct BiomeColor { - pub grass_modifier: GrassModifier, - pub grass: Option, - pub foliage: Option, - pub fog: i32, - pub sky: i32, - pub water_fog: i32, - pub water: i32, - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum GrassModifier { - #grass_modifier_names - } - #[derive(Debug, Clone, PartialEq, PartialOrd)] - pub struct VanillaBiomeSpawnRates { + pub struct SpawnSettings { pub probability: f32, - #( pub #spawn_classes: &'static [SpawnEntry] ),* + #( pub #spawn_classes: &'static [SpawnProperty] ),* } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -295,31 +263,38 @@ pub fn build() -> anyhow::Result { self as u16 } - /// Returns the biome name with both the namespace and path (eg: minecraft:plains) - pub const fn name(self) -> &'static str { + pub fn from_ident>(ident: &Ident) -> Option { + if ident.namespace() != "minecraft"{ + return None; + } + match ident.path() { + #biomekind_name_lookup + _ => None + } + } + + pub fn biome(self) -> Result> { match self{ - #biomekind_names + #biomekind_to_biome } } - /// Gets the biome weather settings - pub const fn weather(self) -> BiomeWeather { + /// Gets the biome spawn rates + pub const fn spawn_rates(self) -> SpawnSettings { match self{ - #biomekind_weather + #biomekind_spawn_settings_arms } } - /// Gets the biome color settings - pub const fn color(self) -> BiomeColor { + pub const fn temperature(self) -> f32 { match self{ - #biomekind_color + #biomekind_temperatures_arms } } - /// Gets the biome spawn rates - pub const fn spawn_rates(self) -> VanillaBiomeSpawnRates { + pub const fn downfall(self) -> f32 { match self{ - #biomekind_spawn_settings_arms + #biomekind_downfall_arms } } } diff --git a/extracted/biomes.json b/extracted/biomes.json index ae5d543b4..e0571e5d8 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -2,7 +2,7 @@ { "name": "the_void", "id": 0, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -33,7 +33,7 @@ { "name": "plains", "id": 1, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -164,7 +164,7 @@ { "name": "sunflower_plains", "id": 2, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -295,7 +295,7 @@ { "name": "snowy_plains", "id": 3, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -408,7 +408,7 @@ { "name": "ice_spikes", "id": 4, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -521,7 +521,7 @@ { "name": "desert", "id": 5, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -628,7 +628,7 @@ { "name": "swamp", "id": 6, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.9 @@ -759,7 +759,7 @@ { "name": "mangrove_swamp", "id": 7, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.9 @@ -873,7 +873,7 @@ { "name": "forest", "id": 8, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -998,7 +998,7 @@ { "name": "flower_forest", "id": 9, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -1123,7 +1123,7 @@ { "name": "birch_forest", "id": 10, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.6, "downfall": 0.6 @@ -1242,7 +1242,7 @@ { "name": "dark_forest", "id": 11, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.7, "downfall": 0.8 @@ -1361,7 +1361,7 @@ { "name": "old_growth_birch_forest", "id": 12, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.6, "downfall": 0.6 @@ -1480,7 +1480,7 @@ { "name": "old_growth_pine_taiga", "id": 13, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.3, "downfall": 0.8 @@ -1617,7 +1617,7 @@ { "name": "old_growth_spruce_taiga", "id": 14, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.25, "downfall": 0.8 @@ -1754,7 +1754,7 @@ { "name": "taiga", "id": 15, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.25, "downfall": 0.8 @@ -1891,7 +1891,7 @@ { "name": "snowy_taiga", "id": 16, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.5, "downfall": 0.4 @@ -2028,7 +2028,7 @@ { "name": "savanna", "id": 17, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2159,7 +2159,7 @@ { "name": "savanna_plateau", "id": 18, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2296,7 +2296,7 @@ { "name": "windswept_hills", "id": 19, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2421,7 +2421,7 @@ { "name": "windswept_gravelly_hills", "id": 20, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2546,7 +2546,7 @@ { "name": "windswept_forest", "id": 21, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -2671,7 +2671,7 @@ { "name": "windswept_savanna", "id": 22, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -2802,7 +2802,7 @@ { "name": "jungle", "id": 23, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.9 @@ -2945,7 +2945,7 @@ { "name": "sparse_jungle", "id": 24, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.8 @@ -3070,7 +3070,7 @@ { "name": "bamboo_jungle", "id": 25, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.95, "downfall": 0.9 @@ -3213,7 +3213,7 @@ { "name": "badlands", "id": 26, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3307,7 +3307,7 @@ { "name": "eroded_badlands", "id": 27, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3401,7 +3401,7 @@ { "name": "wooded_badlands", "id": 28, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -3495,7 +3495,7 @@ { "name": "meadow", "id": 29, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.8 @@ -3608,7 +3608,7 @@ { "name": "grove", "id": 30, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.2, "downfall": 0.8 @@ -3745,7 +3745,7 @@ { "name": "snowy_slopes", "id": 31, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.3, "downfall": 0.9 @@ -3852,7 +3852,7 @@ { "name": "frozen_peaks", "id": 32, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.7, "downfall": 0.9 @@ -3953,7 +3953,7 @@ { "name": "jagged_peaks", "id": 33, - "weather": { + "climate": { "precipitation": "snow", "temperature": -0.7, "downfall": 0.9 @@ -4054,7 +4054,7 @@ { "name": "stony_peaks", "id": 34, - "weather": { + "climate": { "precipitation": "rain", "temperature": 1.0, "downfall": 0.3 @@ -4148,7 +4148,7 @@ { "name": "river", "id": 35, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4262,7 +4262,7 @@ { "name": "frozen_river", "id": 36, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -4376,7 +4376,7 @@ { "name": "beach", "id": 37, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -4477,7 +4477,7 @@ { "name": "snowy_beach", "id": 38, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.05, "downfall": 0.3 @@ -4571,7 +4571,7 @@ { "name": "stony_shore", "id": 39, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.2, "downfall": 0.3 @@ -4665,7 +4665,7 @@ { "name": "warm_ocean", "id": 40, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4791,7 +4791,7 @@ { "name": "lukewarm_ocean", "id": 41, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -4923,7 +4923,7 @@ { "name": "deep_lukewarm_ocean", "id": 42, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5055,7 +5055,7 @@ { "name": "ocean", "id": 43, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5175,7 +5175,7 @@ { "name": "deep_ocean", "id": 44, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5295,7 +5295,7 @@ { "name": "cold_ocean", "id": 45, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5415,7 +5415,7 @@ { "name": "deep_cold_ocean", "id": 46, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5535,7 +5535,7 @@ { "name": "frozen_ocean", "id": 47, - "weather": { + "climate": { "precipitation": "snow", "temperature": 0.0, "downfall": 0.5 @@ -5656,7 +5656,7 @@ { "name": "deep_frozen_ocean", "id": 48, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -5777,7 +5777,7 @@ { "name": "mushroom_fields", "id": 49, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.9, "downfall": 1.0 @@ -5829,7 +5829,7 @@ { "name": "dripstone_caves", "id": 50, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -5929,7 +5929,7 @@ { "name": "lush_caves", "id": 51, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.5, "downfall": 0.5 @@ -6037,7 +6037,7 @@ { "name": "deep_dark", "id": 52, - "weather": { + "climate": { "precipitation": "rain", "temperature": 0.8, "downfall": 0.4 @@ -6068,7 +6068,7 @@ { "name": "nether_wastes", "id": 53, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6137,7 +6137,7 @@ { "name": "warped_forest", "id": 54, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6182,7 +6182,7 @@ { "name": "crimson_forest", "id": 55, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6239,7 +6239,7 @@ { "name": "soul_sand_valley", "id": 56, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6296,7 +6296,7 @@ { "name": "basalt_deltas", "id": 57, - "weather": { + "climate": { "precipitation": "none", "temperature": 2.0, "downfall": 0.0 @@ -6347,7 +6347,7 @@ { "name": "the_end", "id": 58, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6385,7 +6385,7 @@ { "name": "end_highlands", "id": 59, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6423,7 +6423,7 @@ { "name": "end_midlands", "id": 60, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6461,7 +6461,7 @@ { "name": "small_end_islands", "id": 61, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 @@ -6499,7 +6499,7 @@ { "name": "end_barrens", "id": 62, - "weather": { + "climate": { "precipitation": "none", "temperature": 0.5, "downfall": 0.5 diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index 0c88b1e98..c078e08e2 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -47,10 +47,10 @@ public JsonElement extract() { for (var biome : BuiltinRegistries.BIOME) { var biomeIdent = BuiltinRegistries.BIOME.getId(biome); - var weatherJson = new JsonObject(); - weatherJson.addProperty("precipitation", biome.getPrecipitation().getName()); - weatherJson.addProperty("temperature", biome.getTemperature()); - weatherJson.addProperty("downfall", biome.getDownfall()); + var climateJson = new JsonObject(); + climateJson.addProperty("precipitation", biome.getPrecipitation().getName()); + climateJson.addProperty("temperature", biome.getTemperature()); + climateJson.addProperty("downfall", biome.getDownfall()); var colorJson = new JsonObject(); var biomeEffects = biome.getEffects(); @@ -84,7 +84,7 @@ public JsonElement extract() { var biomeJson = new JsonObject(); biomeJson.addProperty("name", biomeIdent.getPath()); biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); - biomeJson.add("weather", weatherJson); + biomeJson.add("climate", climateJson); biomeJson.add("color", colorJson); biomeJson.add("spawn_settings", spawnSettingsJson); From 376c6174d88fff52f3cce45e09000b328824f6ef Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Fri, 28 Oct 2022 21:26:47 +0200 Subject: [PATCH 36/75] Move biomes into valence_anvil crate --- src/biome.rs | 10 ---- valence_anvil/Cargo.toml | 14 ++++- {build => valence_anvil/build}/biome.rs | 29 +++++++-- valence_anvil/build/main.rs | 38 ++++++++++++ valence_anvil/examples/java_region.rs | 24 ++++---- valence_anvil/src/biome.rs | 7 +++ valence_anvil/src/lib.rs | 78 +++++++++++++++---------- 7 files changed, 140 insertions(+), 60 deletions(-) rename {build => valence_anvil/build}/biome.rs (91%) create mode 100644 valence_anvil/build/main.rs create mode 100644 valence_anvil/src/biome.rs diff --git a/src/biome.rs b/src/biome.rs index 9279b40f1..676a6f328 100644 --- a/src/biome.rs +++ b/src/biome.rs @@ -8,16 +8,6 @@ use valence_nbt::{compound, Compound}; use valence_protocol::ident; use valence_protocol::ident::Ident; -pub mod default { - //! Contains data for the default Minecraft biomes. - //! - //! All biome variants are located in [`BiomeKind`]. You can use the - //! associated const functions of [`BiomeKind`] to access details about a - //! biome type. - - include!(concat!(env!("OUT_DIR"), "/biome.rs")); -} - /// Identifies a particular [`Biome`] on the server. /// /// The default biome ID refers to the first biome added in the server's diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 588af4f6e..bcaf9dd97 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -8,13 +8,23 @@ license = "MIT" keywords = ["anvil", "minecraft", "serialization"] version = "0.1.0" authors = ["Ryan Johnson ", "TerminatorNL "] +build = "build/main.rs" edition = "2021" [dependencies] valence = {path = ".."} -valence_nbt = {path = "../valence_nbt"} rayon = "1.5.3" async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} byteorder = "1" tokio = {version = "1", features = ["fs", "io-util", "full"]} -futures = "0.3.24" \ No newline at end of file +futures = "0.3.24" + +[build-dependencies] +anyhow = "1.0.65" +heck = "0.4.0" +proc-macro2 = "1.0.43" +quote = "1.0.21" +serde = { version = "1.0.145", features = ["derive"] } +serde_json = "1.0.85" +rayon = "1.5.3" +num = "0.4.0" \ No newline at end of file diff --git a/build/biome.rs b/valence_anvil/build/biome.rs similarity index 91% rename from build/biome.rs rename to valence_anvil/build/biome.rs index 1845cddb7..4b4443303 100644 --- a/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -59,9 +59,10 @@ struct ParsedSpawnRate { } pub fn build() -> anyhow::Result { - let biomes: Vec = serde_json::from_str(include_str!("../extracted/biomes.json"))?; + let biomes: Vec = + serde_json::from_str(include_str!("../../extracted/biomes.json"))?; - let biomes = biomes + let mut biomes = biomes .into_iter() .map(|biome| RenamedBiome { id: biome.id, @@ -73,6 +74,9 @@ pub fn build() -> anyhow::Result { }) .collect::>(); + //Ensure biomes are sorted, even if the JSON changes later. + biomes.sort_by(|one, two| one.id.cmp(&two.id)); + let mut precipitation_types = BTreeMap::<&str, Ident>::new(); let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); @@ -97,7 +101,7 @@ pub fn build() -> anyhow::Result { } } - let biome_kind_definitions = biomes + let biome_kind_enum_declare = biomes .iter() .map(|biome| { let rustified_name = &biome.rustified_name; @@ -108,6 +112,16 @@ pub fn build() -> anyhow::Result { }) .collect::(); + let biome_kind_enum_names = biomes + .iter() + .map(|biome| { + let rustified_name = &biome.rustified_name; + quote! { + #rustified_name + } + }) + .collect::>(); + let biomekind_id_to_variant_lookup = biomes .iter() .map(|biome| { @@ -224,8 +238,8 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { - use super::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; - use crate::ident::{Ident,IdentError}; + use valence::biome::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; + use valence::ident::{Ident,IdentError}; use std::str::FromStr; #[derive(Debug, Clone, PartialEq, PartialOrd)] @@ -244,10 +258,13 @@ pub fn build() -> anyhow::Result { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BiomeKind { - #biome_kind_definitions + #biome_kind_enum_declare } impl BiomeKind { + /// All imported vanilla biomes (All variants of `BiomeKind`) + pub const ALL: &'static [Self] = &[#(Self::#biome_kind_enum_names),*]; + /// Constructs an `BiomeKind` from a raw biome ID. /// /// If the given ID is invalid, `None` is returned. diff --git a/valence_anvil/build/main.rs b/valence_anvil/build/main.rs new file mode 100644 index 000000000..d7200f067 --- /dev/null +++ b/valence_anvil/build/main.rs @@ -0,0 +1,38 @@ +use std::path::Path; +use std::process::Command; +use std::{env, fs}; + +use anyhow::Context; +use proc_macro2::{Ident, Span}; + +mod biome; + +pub fn main() -> anyhow::Result<()> { + println!("cargo:rerun-if-changed=extracted/"); + + let generators = [(biome::build, "biome.rs")]; + + let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?; + + for (g, file_name) in generators { + let path = Path::new(&out_dir).join(file_name); + let code = g()?.to_string(); + fs::write(&path, &code)?; + + // Format the output for debugging purposes. + // Doesn't matter if rustfmt is unavailable. + let _ = Command::new("rustfmt").arg(path).output(); + } + + Ok(()) +} + +fn ident(s: impl AsRef) -> Ident { + let s = s.as_ref().trim(); + + match s.as_bytes() { + // TODO: check for the other rust keywords. + [b'0'..=b'9', ..] | b"type" => Ident::new(&format!("_{s}"), Span::call_site()), + _ => Ident::new(s, Span::call_site()), + } +} diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 25c5edc96..8b759099e 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -6,6 +6,7 @@ use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::async_trait; +use valence::biome::Biome; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::client::{handle_event_default, GameMode}; use valence::config::{Config, ServerListPing}; @@ -15,17 +16,13 @@ use valence::player_list::PlayerListId; use valence::server::{Server, SharedServer, ShutdownResult}; use valence::text::{Color, TextFormat}; use valence::util::chunks_in_view_distance; +use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; pub fn main() -> ShutdownResult { - let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); - - println!("World folder: {:?}", world_folder.canonicalize()); - valence::start_server( Game { player_count: AtomicUsize::new(0), - anvil_world: AnvilWorld::new(world_folder), }, None, ) @@ -33,7 +30,6 @@ pub fn main() -> ShutdownResult { struct Game { player_count: AtomicUsize, - anvil_world: AnvilWorld, } const MAX_PLAYERS: usize = 10; @@ -44,7 +40,7 @@ impl Config for Game { type ServerState = Option; type ClientState = EntityId; type EntityState = (); - type WorldState = (); + type WorldState = AnvilWorld; /// If the chunk should stay loaded at the end of the tick. type ChunkState = bool; type PlayerListState = (); @@ -54,6 +50,10 @@ impl Config for Game { MAX_PLAYERS + 64 } + fn biomes(&self) -> Vec { + BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() + } + async fn server_list_ping( &self, _server: &SharedServer, @@ -74,7 +74,11 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - server.worlds.insert(DimensionId::default(), ()); + let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + server.worlds.insert( + DimensionId::default(), + AnvilWorld::new(world_folder, &server.shared), + ); server.state = Some(server.player_lists.insert(()).0); } @@ -151,7 +155,7 @@ impl Config for Game { } }); - let future = self.anvil_world.load_chunks(new_chunks); + let future = world.state.load_chunks(new_chunks); let parsed_chunks = futures::executor::block_on(future).unwrap(); for (pos, chunk) in parsed_chunks { if let Some(chunk) = chunk { @@ -180,4 +184,4 @@ impl Config for Game { } }); } -} \ No newline at end of file +} diff --git a/valence_anvil/src/biome.rs b/valence_anvil/src/biome.rs new file mode 100644 index 000000000..5d3d19536 --- /dev/null +++ b/valence_anvil/src/biome.rs @@ -0,0 +1,7 @@ +//! This module contains data for the default Minecraft biomes. +//! +//! All biome variants are located in [`BiomeKind`]. You can use the +//! associated const functions of [`BiomeKind`] to access details about a +//! biome type. + +include!(concat!(env!("OUT_DIR"), "/biome.rs")); diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index be47f9469..12ab88859 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -3,7 +3,7 @@ mod palette; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::{SeekFrom}; +use std::io::SeekFrom; use std::path::{Path, PathBuf}; use async_compression::tokio::bufread::ZlibDecoder; @@ -18,19 +18,35 @@ use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; +pub mod biome; + +use valence::config::Config; +use valence::server::SharedServer; + use crate::error::Error; use crate::palette::DataFormat; +pub enum Test { + One, + Two, +} + #[derive(Debug)] pub struct AnvilWorld { world_root: PathBuf, + biomes: BTreeMap, BiomeId>, region_files: Mutex>>>, } impl AnvilWorld { - pub fn new(directory: PathBuf) -> Self { + pub fn new(directory: PathBuf, server: &SharedServer) -> Self { + let mut biomes = BTreeMap::new(); + for (id, biome) in server.biomes() { + biomes.insert(biome.name.clone(), id); + } Self { world_root: directory, + biomes, region_files: Mutex::new(BTreeMap::new()), } } @@ -59,7 +75,7 @@ impl AnvilWorld { } }) { // A region file exists, and it is loaded. - result_vec.extend(region.parse_chunks(chunk_pos_vec).await?); + result_vec.extend(region.parse_chunks(self, chunk_pos_vec).await?); } else { // No region file exists, there is no data to load here. result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); @@ -157,6 +173,7 @@ impl Region { pub async fn parse_chunks>( &self, + world: &AnvilWorld, positions: I, ) -> Result)>, Error> { let mut results = Vec::<(ChunkPos, Option)>::new(); @@ -165,7 +182,7 @@ impl Region { let chunk_data = self.read_chunk_data(pos).await?; if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - let parsed_chunk = Self::parse_chunk_nbt(&mut nbt)?; + let parsed_chunk = Self::parse_chunk_nbt(&mut nbt, world)?; results.push((pos, Some(parsed_chunk))); } else { results.push((pos, None)); @@ -175,10 +192,10 @@ impl Region { Ok(results) } - fn parse_chunk_nbt(nbt: &mut Compound) -> Result { + fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { fn take_assume(compound: &mut Compound, key: &'static str) -> Result - where - Option: From, + where + Option: From, { match compound.remove(key) { None => Err(Error::missing_nbt_value(key)), @@ -193,8 +210,8 @@ impl Region { } fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option - where - Option: From, + where + Option: From, { match compound.remove(key) { None => None, @@ -205,7 +222,7 @@ impl Region { // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; -// + // // let _status: String = take_assume(nbt, "Status")?; // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; @@ -222,7 +239,8 @@ impl Region { } } - // Max should always be equal or higher than 'lower'. Therefore, this is positive. + // Max should always be equal or higher than 'lower'. Therefore, this is + // positive. let section_height = ((y_max - y_min) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; @@ -236,7 +254,7 @@ impl Region { let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; let parsed_block_state_palette: Vec = if let Some(Value::List(List::Compound(nbt_palette_vec))) = - nbt_block_states.remove("palette") + nbt_block_states.remove("palette") { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); @@ -253,14 +271,14 @@ impl Region { }; let mut block_state = BlockState::from_kind(block_kind); if let Some(Value::Compound(nbt_palette_properties)) = - nbt_palette.remove("Properties") + nbt_palette.remove("Properties") { for (property_name, property_value) in nbt_palette_properties { if let Value::String(property_value) = property_value { let property_name = PropName::from_str(&property_name); let property_value = PropValue::from_str(&property_value); if let (Some(property_name), Some(property_value)) = - (property_name, property_value) + (property_name, property_value) { block_state = block_state.set(property_name, property_value); @@ -286,7 +304,7 @@ impl Region { }; // Block state palette - palette::parse_palette::( + palette::parse_palette::( &parsed_block_state_palette, take_assume_optional(&mut nbt_block_states, "data"), 4, @@ -329,22 +347,25 @@ impl Region { let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; let parsed_biome_palette: Vec = if let Some(Value::List(List::String(biome_names))) = - nbt_biomes.remove("palette") + nbt_biomes.remove("palette") { let mut biomes: Vec = Vec::with_capacity(biome_names.len()); for biome in biome_names { - let _identity_IMPLEMENT_ME = Ident::new(biome)?; - - //TODO: EXTRACT BIOME IDs - //TODO: BiomeId::from_str(identity.path()); - biomes.push(BiomeId::default()); + let biome_identity = Ident::new(biome)?; + if let Some(biome) = world.biomes.get(&biome_identity) { + biomes.push(*biome); + } else { + return Err(Error::invalid_nbt( + "sections/*/palette/ Unknown biome", + )); + } } biomes } else { return Err(Error::invalid_nbt("sections/*/palette.")); }; - palette::parse_palette::( + palette::parse_palette::( &parsed_biome_palette, take_assume_optional(&mut nbt_biomes, "data"), 0, @@ -370,12 +391,7 @@ impl Region { let x = index & 0b11; let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); - chunk.set_biome( - x, - final_y as usize, - z, - biome, - ); + chunk.set_biome(x, final_y as usize, z, biome); } } Ok(()) @@ -516,9 +532,7 @@ impl CompressionScheme { decoder.read_to_end(&mut vec).await?; Ok(vec) } - CompressionScheme::Raw => { - Ok(raw_data) - } + CompressionScheme::Raw => Ok(raw_data), } } -} \ No newline at end of file +} From 87262edf97b8da7118ea94c01f23d98f337ad8bb Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 29 Oct 2022 13:56:29 +0200 Subject: [PATCH 37/75] Require position to be within region --- valence_anvil/src/error.rs | 2 +- valence_anvil/src/lib.rs | 43 ++++++++++++++++++++++++++++++------ valence_anvil/src/palette.rs | 10 ++++----- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 1da656e8f..74c7a6645 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -125,4 +125,4 @@ impl Display for SerializeError { fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { write!(f, "Serialization failed") } -} \ No newline at end of file +} diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 12ab88859..2ef68f02f 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -69,7 +69,7 @@ impl AnvilWorld { if let Some(region) = lock.entry(region_pos).or_insert({ let path = region_pos.path(&self.world_root); if path.exists() { - Some(Region::from_file(File::open(&path).await?).await?) + Some(Region::from_file(File::open(&path).await?, region_pos).await?) } else { None } @@ -108,26 +108,36 @@ impl RegionPos { .join("region") .join(format!("r.{}.{}.mca", self.x, self.z)) } + + pub fn contains(self, chunk_pos: ChunkPos) -> bool { + Self::from(chunk_pos) == self + } } #[derive(Debug)] pub struct Region { source: Mutex, offset: u64, + position: RegionPos, header: AnvilHeader, } impl Region { - /// Convenience method, creates a Region object from the given file. - pub async fn from_file(source: File) -> Result { - Self::from_seek(Mutex::new(source), 0).await + /// Convenience method, creates a Region object from the given file and + /// position. + pub async fn from_file(source: File, position: RegionPos) -> Result { + Self::from_seek(Mutex::new(source), 0, position).await } } impl Region { /// Creates a Region object using the incoming stream. The offset defines /// the position of the header start. - pub async fn from_seek(source: Mutex, offset: u64) -> Result { + pub async fn from_seek( + source: Mutex, + offset: u64, + position: RegionPos, + ) -> Result { let mut lock = source.lock().await; lock.seek(SeekFrom::Start(offset)).await?; let header = AnvilHeader::parse(&mut *lock).await?; @@ -136,10 +146,17 @@ impl Region { Ok(Self { source, offset, + position, header, }) } + /// Get the last time the chunk was modified in seconds since epoch. + pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> &ChunkTimestamp { + self.header + .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) + } + async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { let seek_pos = self .header @@ -179,6 +196,13 @@ impl Region { let mut results = Vec::<(ChunkPos, Option)>::new(); for pos in positions.into_iter() { + assert!( + self.position.contains(pos), + "Chunk position {:?} was not found in region {:?}", + pos, + self.position + ); + let chunk_data = self.read_chunk_data(pos).await?; if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; @@ -241,7 +265,7 @@ impl Region { // Max should always be equal or higher than 'lower'. Therefore, this is // positive. - let section_height = ((y_max - y_min) as usize * 16) + 16; + let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; //Parsing sections @@ -477,7 +501,7 @@ impl ChunkLocation { /// The timestamp when the chunk was last modified in seconds since epoch. #[derive(Copy, Clone)] -struct ChunkTimestamp(u32); +pub struct ChunkTimestamp(u32); impl Debug for ChunkTimestamp { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { @@ -493,6 +517,11 @@ impl ChunkTimestamp { fn load(&mut self, chunk: [u8; 4]) { self.0 = BigEndian::read_u32(&chunk) } + + #[inline(always)] + pub fn seconds_since_epoch(&self) -> u32 { + self.0 + } } #[derive(Debug, Copy, Clone)] diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 3113e5fc9..6fe5b051a 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -1,15 +1,13 @@ -use crate::error::Error; use std::ops::BitXor; +use crate::error::Error; + pub enum DataFormat { All(T), Palette(usize, T), } -pub fn parse_palette< - T: Copy, - F: (FnMut(DataFormat) -> Result<(), Error>) ->( +pub fn parse_palette) -> Result<(), Error>)>( source: &Vec, data: Option>, min_bits: usize, @@ -64,4 +62,4 @@ pub fn parse_palette< fun(DataFormat::All(source[0]))?; Ok(()) } -} \ No newline at end of file +} From 1bcf60551bb1fbe82835e8bec087d4df12a2697c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 20:50:57 +0100 Subject: [PATCH 38/75] Refactor everything --- valence_anvil/build/biome.rs | 2 +- valence_anvil/examples/java_region.rs | 21 +- valence_anvil/src/compression.rs | 49 +++ valence_anvil/src/error.rs | 135 +++--- valence_anvil/src/lib.rs | 575 +++++++------------------- valence_anvil/src/palette.rs | 12 +- valence_anvil/src/region.rs | 394 ++++++++++++++++++ 7 files changed, 657 insertions(+), 531 deletions(-) create mode 100644 valence_anvil/src/compression.rs create mode 100644 valence_anvil/src/region.rs diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 4b4443303..3f20c5652 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -242,7 +242,7 @@ pub fn build() -> anyhow::Result { use valence::ident::{Ident,IdentError}; use std::str::FromStr; - #[derive(Debug, Clone, PartialEq, PartialOrd)] + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] pub struct SpawnProperty { pub name: &'static str, pub min_group_size: u32, diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 8b759099e..9b34b7942 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -33,7 +33,12 @@ struct Game { } const MAX_PLAYERS: usize = 10; -const WORLD_FOLDER: &'static str = "./test_data/"; + +/// # IMPORTANT +/// Change the following to the world file you wish to load. +/// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most +/// importantly `region` directories. Only the `region` directory is accessed. +const WORLD_FOLDER: &str = "./test_data/"; #[async_trait] impl Config for Game { @@ -146,16 +151,18 @@ impl Config for Game { let dist = client.view_distance(); let p = client.position(); - let new_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist).filter(|pos| { - if let Some(existing) = world.chunks.get_mut(*pos) { + let required_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); + let mut new_chunks = Vec::new(); + for pos in required_chunks { + if let Some(existing) = world.chunks.get_mut(pos) { existing.state = true; - false } else { - true + new_chunks.push(pos); } - }); + } + + let future = world.state.load_chunks(new_chunks.into_iter()); - let future = world.state.load_chunks(new_chunks); let parsed_chunks = futures::executor::block_on(future).unwrap(); for (pos, chunk) in parsed_chunks { if let Some(chunk) = chunk { diff --git a/valence_anvil/src/compression.rs b/valence_anvil/src/compression.rs new file mode 100644 index 000000000..5393d4abe --- /dev/null +++ b/valence_anvil/src/compression.rs @@ -0,0 +1,49 @@ +use async_compression::tokio::bufread::ZlibDecoder; +use async_compression::tokio::write::GzipDecoder; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; + +use crate::error::{DataFormatError, Error}; + +#[derive(Debug, Copy, Clone)] +pub enum CompressionScheme { + GZip = 1, + Zlib = 2, + Raw = 3, +} + +impl CompressionScheme { + pub(crate) fn from_raw(mode: u8) -> Result { + match mode { + 1 => Ok(Self::GZip), + 2 => Ok(Self::Zlib), + 3 => Ok(Self::Raw), + scheme => Err(Error::DataFormatError( + DataFormatError::UnknownCompressionScheme(scheme), + )), + } + } + + pub(crate) async fn read_to_vec( + self, + source: &mut R, + length: usize, + ) -> Result, std::io::Error> { + let mut raw_data = vec![0u8; length]; + source.read_exact(&mut raw_data).await?; + match self { + CompressionScheme::GZip => { + let mut decoder = GzipDecoder::new(Vec::::new()); + decoder.write_all(&raw_data).await?; + decoder.shutdown().await?; + Ok(decoder.into_inner()) + } + CompressionScheme::Zlib => { + let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); + let mut vec = Vec::::new(); + decoder.read_to_end(&mut vec).await?; + Ok(vec) + } + CompressionScheme::Raw => Ok(raw_data), + } + } +} diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 74c7a6645..a11960bec 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -2,57 +2,36 @@ use std::error::Error as StdError; use std::fmt::{Display, Formatter}; use std::io; -use valence::ident::Ident; +use valence::ident::{Ident, IdentError}; -/// Errors that can occur when encoding or decoding. #[derive(Debug)] -pub struct Error { - /// Box this to keep the size of `Result` small. - cause: Box, +pub enum Error { + Io(io::Error), + DataFormatError(DataFormatError), + NbtParseError(valence::nbt::Error), + NbtFormatError(NbtFormatError), } -impl Error { - pub(crate) fn unknown_compression_scheme(mode: u8) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::UnknownCompressionScheme(mode))), - } - } - - pub(crate) fn invalid_chunk_size(size: usize) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidChunkSize(size))), - } - } - - pub(crate) fn missing_nbt_value(key: &'static str) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::MissingNBT(key))), - } - } - - pub(crate) fn invalid_nbt(message: &'static str) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidNBT(message))), - } - } - - pub(crate) fn invalid_palette() -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::InvalidPalette)), - } - } +#[derive(Debug)] +pub enum NbtFormatError { + MissingKey(String), + InvalidType(String), +} - pub(crate) fn unknown_type(ident: Ident) -> Self { - Self { - cause: Box::new(Cause::Parse(ParseError::UnknownType(ident))), - } - } +#[derive(Debug)] +pub enum DataFormatError { + UnknownCompressionScheme(u8), + InvalidChunkSize(usize), + IdentityError(IdentError), + UnknownType(Ident), + InvalidChunkState(String), + InvalidPalette, } impl StdError for Error { fn source(&self) -> Option<&(dyn StdError + 'static)> { - match &*self.cause { - Cause::Io(e) => Some(e), + match self { + Self::Io(e) => Some(e), _ => None, } } @@ -60,69 +39,55 @@ impl StdError for Error { impl From for Error { fn from(e: io::Error) -> Self { - Self { - cause: Box::new(Cause::Io(e)), - } + Self::Io(e) } } + impl From for Error { fn from(e: valence::nbt::Error) -> Self { - Self { - cause: Box::new(Cause::NBT(e)), - } + Self::NbtParseError(e) } } impl From> for Error { fn from(e: valence::ident::IdentError) -> Self { - Self { - cause: Box::new(Cause::IdentityError(e)), - } + Self::DataFormatError(DataFormatError::IdentityError(e)) } } -#[derive(Debug)] -pub enum Cause { - Io(io::Error), - Parse(ParseError), - NBT(valence::nbt::Error), - IdentityError(valence::ident::IdentError), -} - -#[derive(Debug)] -pub enum ParseError { - UnknownCompressionScheme(u8), - InvalidChunkSize(usize), - MissingNBT(&'static str), - InvalidNBT(&'static str), - InvalidPalette, - UnknownType(Ident), -} - -#[derive(Debug)] -pub enum SerializeError { - // ChunkTooLarge -} - impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match &*self.cause { - Cause::Io(e) => e.fmt(f), - Cause::Parse(err) => err.fmt(f), - Cause::NBT(e) => e.fmt(f), - Cause::IdentityError(e) => e.fmt(f), + match self { + Error::Io(e) => e.fmt(f), + Error::DataFormatError(e) => e.fmt(f), + Error::NbtParseError(e) => e.fmt(f), + Error::NbtFormatError(e) => e.fmt(f), } } } -impl Display for ParseError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { - write!(f, "Parse failed") +impl Display for DataFormatError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + match self { + DataFormatError::UnknownCompressionScheme(scheme) => { + write!(f, "Unknown compression scheme: {scheme}") + } + DataFormatError::InvalidChunkSize(size) => write!(f, "Invalid chunk size: {size}"), + DataFormatError::IdentityError(e) => e.fmt(f), + DataFormatError::UnknownType(identity) => write!(f, "Unknown identity: {identity}"), + DataFormatError::InvalidChunkState(state) => write!(f, "Unknown chunk state: {state}"), + DataFormatError::InvalidPalette => write!(f, "Invalid chunk palette"), + } } } -impl Display for SerializeError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::vek::serde::__private::fmt::Result { - write!(f, "Serialization failed") +impl Display for NbtFormatError { + fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + match self { + NbtFormatError::MissingKey(key) => { + write!(f, "Could not find key: \"{key}\" in nbt data.") + } + NbtFormatError::InvalidType(key) => write!(f, "Unexpected type for key: \"{key}\""), + } } } diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 2ef68f02f..234b0738e 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,35 +1,25 @@ -mod error; -mod palette; - use std::collections::BTreeMap; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::SeekFrom; use std::path::{Path, PathBuf}; -use async_compression::tokio::bufread::ZlibDecoder; -use async_compression::tokio::write::GzipDecoder; use byteorder::{BigEndian, ByteOrder}; +use region::Region; use tokio::fs::File; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWriteExt}; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, MutexGuard}; use valence::biome::BiomeId; -use valence::block::{BlockKind, BlockState, PropName, PropValue}; -use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::ident::Ident; -use valence::nbt::{Compound, List, Value}; - -pub mod biome; - +use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; +use valence::ident::Ident; use valence::server::SharedServer; use crate::error::Error; -use crate::palette::DataFormat; -pub enum Test { - One, - Two, -} +pub mod error; +pub mod biome; +pub mod compression; + +mod palette; +mod region; #[derive(Debug)] pub struct AnvilWorld { @@ -39,6 +29,31 @@ pub struct AnvilWorld { } impl AnvilWorld { + //noinspection ALL + /// Creates an `AnvilWorld` instance. + /// + /// # Arguments + /// + /// * `directory`: A path to the world folder. Inside this folder you should + /// see the `region` directory. + /// * `server`: The shared server. This is used to initialize which biomes + /// to use. + /// + /// returns: AnvilWorld + /// + /// # Examples + /// + /// ``` + /// impl Config for Game { + /// fn init(&self, server: &mut Server) { + /// let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); + /// server.worlds.insert( + /// DimensionId::default(), + /// AnvilWorld::new(world_folder, &server.shared), + /// ); + /// } + /// } + /// ``` pub fn new(directory: PathBuf, server: &SharedServer) -> Self { let mut biomes = BTreeMap::new(); for (id, biome) in server.biomes() { @@ -51,29 +66,57 @@ impl AnvilWorld { } } - pub async fn load_chunks>( + //noinspection ALL + /// Load chunks from the available region files within the world directory. + /// This operation will temporarily block operations on all region files + /// within `AnvilWorld`. + /// + /// # Arguments + /// + /// * `positions`: Any iterator of `valence::chunk_pos::ChunkPos` + /// + /// returns: An iterator of the requested chunk positions and their + /// associated chunks + /// + /// # Examples + /// + /// ``` + /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); + /// let future = world.state.load_chunks(to_load); + /// let parsed_chunks = futures::executor::block_on(future).unwrap(); + /// for (pos, chunk) in parsed_chunks { + /// if let Some(chunk) = chunk { + /// // A chunk has successfully loaded from the region file. + /// world.chunks.insert(pos, chunk, true); + /// } else { + /// // There is no information on this chunk in the region file. + /// let mut blank_chunk = UnloadedChunk::new(16); + /// blank_chunk.set_block_state( + /// 0, + /// 0, + /// 0, + /// valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + /// ); + /// world.chunks.insert(pos, blank_chunk, true); + /// } + /// } + /// ``` + pub async fn load_chunks>( &self, positions: I, - ) -> Result)>, Error> { + ) -> Result)>, Error> { let mut map = BTreeMap::>::new(); - for pos in positions.into_iter() { + for pos in positions { let region_pos = RegionPos::from(pos); map.entry(region_pos) .and_modify(|v| v.push(pos)) - .or_insert(vec![pos]); + .or_insert_with(|| vec![pos]); } let mut result_vec = Vec::<(ChunkPos, Option)>::new(); let mut lock = self.region_files.lock().await; for (region_pos, chunk_pos_vec) in map.into_iter() { - if let Some(region) = lock.entry(region_pos).or_insert({ - let path = region_pos.path(&self.world_root); - if path.exists() { - Some(Region::from_file(File::open(&path).await?, region_pos).await?) - } else { - None - } - }) { + if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { // A region file exists, and it is loaded. result_vec.extend(region.parse_chunks(self, chunk_pos_vec).await?); } else { @@ -82,7 +125,63 @@ impl AnvilWorld { } } - Ok(result_vec) + Ok(result_vec.into_iter()) + } + + /// Get the last time the chunk was modified in seconds since epoch. + /// This operation will temporarily block operations on all region files + /// within `AnvilWorld`. + /// + /// # Arguments + /// + /// * `positions`: An iterator of chunk positions + /// + /// returns: An iterator with `ChunkPos` and the respective + /// `Option` as tuple. + pub async fn chunk_timestamps>( + &self, + positions: I, + ) -> Result)>, Error> { + let mut map = BTreeMap::>::new(); + for pos in positions { + let region_pos = RegionPos::from(pos); + map.entry(region_pos) + .and_modify(|v| v.push(pos)) + .or_insert_with(|| vec![pos]); + } + + let mut result_vec = Vec::<(ChunkPos, Option)>::new(); + let mut lock = self.region_files.lock().await; + for (region_pos, chunk_pos_vec) in map.into_iter() { + if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { + for chunk_pos in chunk_pos_vec { + result_vec.push((chunk_pos, region.chunk_timestamp(chunk_pos))); + } + } else { + for chunk_pos in chunk_pos_vec { + result_vec.push((chunk_pos, None)); + } + } + } + Ok(result_vec.into_iter()) + } + + async fn access_region_mut<'a>( + &self, + lock: &'a mut MutexGuard<'_, BTreeMap>>>, + region_pos: RegionPos, + ) -> Result>, Error> { + Ok(lock + .entry(region_pos) + .or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path).await?, region_pos).await?) + } else { + None + } + }) + .as_mut()) } } @@ -114,370 +213,14 @@ impl RegionPos { } } -#[derive(Debug)] -pub struct Region { - source: Mutex, - offset: u64, - position: RegionPos, - header: AnvilHeader, -} - -impl Region { - /// Convenience method, creates a Region object from the given file and - /// position. - pub async fn from_file(source: File, position: RegionPos) -> Result { - Self::from_seek(Mutex::new(source), 0, position).await - } -} - -impl Region { - /// Creates a Region object using the incoming stream. The offset defines - /// the position of the header start. - pub async fn from_seek( - source: Mutex, - offset: u64, - position: RegionPos, - ) -> Result { - let mut lock = source.lock().await; - lock.seek(SeekFrom::Start(offset)).await?; - let header = AnvilHeader::parse(&mut *lock).await?; - drop(lock); - - Ok(Self { - source, - offset, - position, - header, - }) - } - - /// Get the last time the chunk was modified in seconds since epoch. - pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> &ChunkTimestamp { - self.header - .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) - } - - async fn read_chunk_data(&self, chunk_pos: ChunkPos) -> Result>, Error> { - let seek_pos = self - .header - .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); - - let mut lock = self.source.lock().await; - - lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) - .await?; - - if seek_pos.len() == 0 { - return Ok(None); - } - - let compressed_chunk_size = { - let mut buf = [0u8; 4]; - lock.read_exact(&mut buf).await?; - BigEndian::read_u32(&buf) as usize - }; - - if compressed_chunk_size == 0 { - return Err(Error::invalid_chunk_size(compressed_chunk_size)); - } - - let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; - let uncompressed_buffer = compression - .read_to_vec(&mut *lock, compressed_chunk_size - 1) - .await?; - Ok(Some(uncompressed_buffer)) - } - - pub async fn parse_chunks>( - &self, - world: &AnvilWorld, - positions: I, - ) -> Result)>, Error> { - let mut results = Vec::<(ChunkPos, Option)>::new(); - - for pos in positions.into_iter() { - assert!( - self.position.contains(pos), - "Chunk position {:?} was not found in region {:?}", - pos, - self.position - ); - - let chunk_data = self.read_chunk_data(pos).await?; - if let Some(chunk_data) = chunk_data { - let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - let parsed_chunk = Self::parse_chunk_nbt(&mut nbt, world)?; - results.push((pos, Some(parsed_chunk))); - } else { - results.push((pos, None)); - } - } - - Ok(results) - } - - fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { - fn take_assume(compound: &mut Compound, key: &'static str) -> Result - where - Option: From, - { - match compound.remove(key) { - None => Err(Error::missing_nbt_value(key)), - Some(value) => { - if let Some(value) = Option::::from(value) { - Ok(value) - } else { - Err(Error::invalid_nbt(key)) - } - } - } - } - - fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option - where - Option: From, - { - match compound.remove(key) { - None => None, - Some(value) => Option::::from(value), - } - } - - // let _chunk_x_pos: i32 = take_assume(nbt, "xPos")?; - // let _chunk_y_pos: i32 = take_assume(nbt, "yPos")?; - // let _chunk_z_pos: i32 = take_assume(nbt, "zPos")?; - // - // let _status: String = take_assume(nbt, "Status")?; - // let _last_update: i64 = take_assume(nbt, "LastUpdate")?; - - if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { - let mut y_max = 0i8; - let mut y_min = 0i8; - - for chunk_nbt in nbt_sections.iter() { - if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { - y_max = y_max.max(*section_y); - y_min = y_min.min(*section_y); - } else { - return Err(Error::missing_nbt_value("sections/*/Y")); - } - } - - // Max should always be equal or higher than 'lower'. Therefore, this is - // positive. - let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; - let y_raise = isize::from(-y_min) * 16; - - //Parsing sections - let mut chunk = UnloadedChunk::new(section_height); - for mut nbt_section in nbt_sections.into_iter() { - let chunk_y_offset: isize = - isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; - - // Block states - let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; - let parsed_block_state_palette: Vec = - if let Some(Value::List(List::Compound(nbt_palette_vec))) = - nbt_block_states.remove("palette") - { - let mut palette_vec: Vec = - Vec::with_capacity(nbt_palette_vec.len()); - for mut nbt_palette in nbt_palette_vec { - let block_id = valence::ident::Ident::new(take_assume::( - &mut nbt_palette, - "Name", - )?)?; - let block_kind = - if let Some(block_kind) = BlockKind::from_str(block_id.path()) { - block_kind - } else { - return Err(Error::unknown_type(block_id)); - }; - let mut block_state = BlockState::from_kind(block_kind); - if let Some(Value::Compound(nbt_palette_properties)) = - nbt_palette.remove("Properties") - { - for (property_name, property_value) in nbt_palette_properties { - if let Value::String(property_value) = property_value { - let property_name = PropName::from_str(&property_name); - let property_value = PropValue::from_str(&property_value); - if let (Some(property_name), Some(property_value)) = - (property_name, property_value) - { - block_state = - block_state.set(property_name, property_value); - } else { - return Err(Error::invalid_nbt( - "sections/*/block_states/Properties/*/property \ - value is not recognized.", - )); - } - } else { - return Err(Error::invalid_nbt( - "sections/*/block_states/Properties/*/property value \ - is invalid.", - )); - } - } - } - palette_vec.push(block_state); - } - palette_vec - } else { - return Err(Error::invalid_nbt("sections/*/palette")); - }; - - // Block state palette - palette::parse_palette::( - &parsed_block_state_palette, - take_assume_optional(&mut nbt_block_states, "data"), - 4, - &mut |data| { - match data { - DataFormat::All(state) => { - if !state.is_air() { - for x in 0..16 { - for y in 0..16isize { - for z in 0..16 { - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - } - } - } - DataFormat::Palette(index, state) => { - let y = (index >> 8 & 0b1111) as isize; - let z = index >> 4 & 0b1111; - let x = index & 0b1111; - - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - Ok(()) - }, - )?; - - // Biome palette - let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; - let parsed_biome_palette: Vec = - if let Some(Value::List(List::String(biome_names))) = - nbt_biomes.remove("palette") - { - let mut biomes: Vec = Vec::with_capacity(biome_names.len()); - for biome in biome_names { - let biome_identity = Ident::new(biome)?; - if let Some(biome) = world.biomes.get(&biome_identity) { - biomes.push(*biome); - } else { - return Err(Error::invalid_nbt( - "sections/*/palette/ Unknown biome", - )); - } - } - biomes - } else { - return Err(Error::invalid_nbt("sections/*/palette.")); - }; - - palette::parse_palette::( - &parsed_biome_palette, - take_assume_optional(&mut nbt_biomes, "data"), - 0, - &mut |data| { - match data { - DataFormat::All(biome) => { - for x in 0..4 { - for y in 0..4isize { - for z in 0..4 { - chunk.set_biome( - x, - (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, - z, - biome, - ); - } - } - } - } - DataFormat::Palette(index, biome) => { - let y = (index >> 4 & 0b11) as isize; - let z = index >> 2 & 0b11; - let x = index & 0b11; - - let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); - chunk.set_biome(x, final_y as usize, z, biome); - } - } - Ok(()) - }, - )?; - } - - //sections - - Ok(chunk) - } else { - return Err(Error::invalid_nbt("sections tag invalid.")); - } - } -} - -#[derive(Copy, Clone, Debug)] -struct AnvilHeader { - offsets: [ChunkLocation; 1024], - timestamps: [ChunkTimestamp; 1024], -} - -impl AnvilHeader { - /// Parses the header bytes from the current position - async fn parse(source: &mut R) -> Result { - let mut offsets = [ChunkLocation::zero(); 1024]; - for offset in &mut offsets { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; - offset.load(buf); - } - let mut timestamps = [ChunkTimestamp::zero(); 1024]; - for timestamp in &mut timestamps { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; - timestamp.load(buf); - } - Ok(Self { - offsets, - timestamps, - }) - } - - #[inline(always)] - fn offset(&self, x: usize, z: usize) -> &ChunkLocation { - &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] - } - - #[inline(always)] - fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { - &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] - } -} - /// The location of the chunk inside the region file. #[derive(Copy, Clone, Debug)] -struct ChunkLocation { +struct ChunkSeekLocation { offset_sectors: u32, len_sectors: u8, } -impl ChunkLocation { +impl ChunkSeekLocation { const fn zero() -> Self { Self { offset_sectors: 0, @@ -518,50 +261,16 @@ impl ChunkTimestamp { self.0 = BigEndian::read_u32(&chunk) } - #[inline(always)] - pub fn seconds_since_epoch(&self) -> u32 { - self.0 - } -} - -#[derive(Debug, Copy, Clone)] -enum CompressionScheme { - GZip = 1, - Zlib = 2, - Raw = 3, -} - -impl CompressionScheme { - fn from_raw(mode: u8) -> Result { - match mode { - 1 => Ok(Self::GZip), - 2 => Ok(Self::Zlib), - 3 => Ok(Self::Raw), - mode => Err(Error::unknown_compression_scheme(mode)), + fn into_option(self) -> Option { + if self.0 == 0 { + None + } else { + Some(self) } } - async fn read_to_vec( - self, - source: &mut R, - length: usize, - ) -> Result, std::io::Error> { - let mut raw_data = vec![0u8; length]; - source.read_exact(&mut raw_data).await?; - match self { - CompressionScheme::GZip => { - let mut decoder = GzipDecoder::new(Vec::::new()); - decoder.write_all(&mut raw_data).await?; - decoder.shutdown().await?; - Ok(decoder.into_inner()) - } - CompressionScheme::Zlib => { - let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); - let mut vec = Vec::::new(); - decoder.read_to_end(&mut vec).await?; - Ok(vec) - } - CompressionScheme::Raw => Ok(raw_data), - } + #[inline(always)] + pub fn seconds_since_epoch(self) -> u32 { + self.0 } } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 6fe5b051a..65d8ffcc7 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -1,6 +1,6 @@ use std::ops::BitXor; -use crate::error::Error; +use crate::error::{DataFormatError, Error}; pub enum DataFormat { All(T), @@ -28,9 +28,9 @@ pub fn parse_palette) -> Result<(), Error>)>( let mut entry_mask = (u64::MAX << bits_per_index).bitxor(u64::MAX); let mut mask_fields: Vec<(u64, usize)> = vec![(0u64, 0usize); entries_per_integer]; - for i in 0..mask_fields.len() { - mask_fields[i] = (entry_mask, (i * bits_per_index)); - entry_mask = entry_mask << bits_per_index; + for (i, mask_field) in mask_fields.iter_mut().enumerate() { + *mask_field = (entry_mask, (i * bits_per_index)); + entry_mask <<= bits_per_index; } let mut index: usize = 0; @@ -49,7 +49,9 @@ pub fn parse_palette) -> Result<(), Error>)>( //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", // palette_index_shifted, choice_len, // bits_per_index, source, source.len()); - return Err(crate::error::Error::invalid_palette()); + return Err(crate::error::Error::DataFormatError( + DataFormatError::InvalidPalette, + )); } else { fun(DataFormat::Palette(index, source[palette_index_shifted]))?; index += 1; diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs new file mode 100644 index 000000000..6d9e48576 --- /dev/null +++ b/valence_anvil/src/region.rs @@ -0,0 +1,394 @@ +use std::io::SeekFrom; + +use byteorder::{BigEndian, ByteOrder}; +use tokio::fs::File; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; +use tokio::sync::Mutex; +use valence::biome::BiomeId; +use valence::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; +use valence::ident::Ident; +use valence::nbt::{Compound, List, Value}; + +use crate::compression::CompressionScheme; +use crate::error::{DataFormatError, Error, NbtFormatError}; +use crate::palette::DataFormat; +use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; + +#[derive(Debug)] +pub struct Region { + source: Mutex, + offset: u64, + position: RegionPos, + header: AnvilHeader, +} + +impl Region { + /// Convenience method, creates a Region object from the given file and + /// position. + pub async fn from_file(source: File, position: RegionPos) -> Result { + Self::from_seek(Mutex::new(source), 0, position).await + } +} + +impl Region { + /// Creates a Region object using the incoming stream. The offset defines + /// the position of the header start. + pub async fn from_seek( + source: Mutex, + offset: u64, + position: RegionPos, + ) -> Result { + let mut lock = source.lock().await; + lock.seek(SeekFrom::Start(offset)).await?; + let header = AnvilHeader::parse(&mut *lock).await?; + drop(lock); + + Ok(Self { + source, + offset, + position, + header, + }) + } + + /// Get the last time the chunk was modified in seconds since epoch. + pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> Option { + self.header + .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) + .into_option() + } + + async fn read_chunk_bytes(&self, chunk_pos: ChunkPos) -> Result>, Error> { + let seek_pos = self + .header + .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); + + let mut lock = self.source.lock().await; + + lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) + .await?; + + if seek_pos.len() == 0 { + return Ok(None); + } + + let compressed_chunk_size = { + let mut buf = [0u8; 4]; + lock.read_exact(&mut buf).await?; + BigEndian::read_u32(&buf) as usize + }; + + if compressed_chunk_size == 0 { + return Err(Error::DataFormatError(DataFormatError::InvalidChunkSize( + compressed_chunk_size, + ))); + } + + let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; + let uncompressed_buffer = compression + .read_to_vec(&mut *lock, compressed_chunk_size - 1) + .await?; + Ok(Some(uncompressed_buffer)) + } + + pub(crate) async fn parse_chunks>( + &self, + world: &AnvilWorld, + positions: I, + ) -> Result)>, Error> { + let mut results = Vec::<(ChunkPos, Option)>::new(); + + for pos in positions.into_iter() { + assert!( + self.position.contains(pos), + "Chunk position {:?} was not found in region {:?}", + pos, + self.position + ); + + let chunk_data = self.read_chunk_bytes(pos).await?; + if let Some(chunk_data) = chunk_data { + let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; + match Self::parse_chunk_nbt(&mut nbt, world) { + Err(Error::NbtParseError(_)) => { + results.push((pos, None)); + } + Err(e) => return Err(e), + Ok(parsed_chunk) => { + results.push((pos, Some(parsed_chunk))); + } + } + } else { + results.push((pos, None)); + } + } + + Ok(results.into_iter()) + } + + //TODO: This function is very large and should be separated into dedicated + // functions at some point. + fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { + fn take_assume(compound: &mut Compound, key: &'static str) -> Result + where + Option: From, + { + match compound.remove(key) { + None => Err(Error::NbtFormatError(NbtFormatError::MissingKey( + key.to_string(), + ))), + Some(value) => { + if let Some(value) = Option::::from(value) { + Ok(value) + } else { + Err(Error::NbtFormatError(NbtFormatError::InvalidType( + key.to_string(), + ))) + } + } + } + } + + fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option + where + Option: From, + { + match compound.remove(key) { + None => None, + Some(value) => Option::::from(value), + } + } + + let status: String = take_assume(nbt, "Status")?; + if status.as_str() != "full" { + return Err(Error::DataFormatError(DataFormatError::InvalidChunkState( + status, + ))); + } + + if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { + let mut y_max = 0i8; + let mut y_min = 0i8; + + for chunk_nbt in nbt_sections.iter() { + if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { + y_max = y_max.max(*section_y); + y_min = y_min.min(*section_y); + } else { + return Err(Error::NbtFormatError(NbtFormatError::MissingKey( + "Y".to_string(), + ))); + } + } + + // `y_max` should always be equal or higher than `y_min`. Therefore, + // section_height is positive. + let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; + let y_raise = isize::from(-y_min) * 16; + + //Parsing sections + let mut chunk = UnloadedChunk::new(section_height); + for mut nbt_section in nbt_sections.into_iter() { + let chunk_y_offset: isize = + isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; + + // Block states + let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; + let parsed_block_state_palette: Vec = + if let Some(Value::List(List::Compound(nbt_palette_vec))) = + nbt_block_states.remove("palette") + { + let mut palette_vec: Vec = + Vec::with_capacity(nbt_palette_vec.len()); + for mut nbt_palette in nbt_palette_vec { + let block_id = valence::ident::Ident::new(take_assume::( + &mut nbt_palette, + "Name", + )?)?; + let block_kind = + if let Some(block_kind) = BlockKind::from_str(block_id.path()) { + block_kind + } else { + return Err(Error::DataFormatError( + DataFormatError::UnknownType(block_id), + )); + }; + let mut block_state = BlockState::from_kind(block_kind); + if let Some(Value::Compound(nbt_palette_properties)) = + nbt_palette.remove("Properties") + { + for (property_name_raw, property_value) in nbt_palette_properties { + if let Value::String(property_value) = property_value { + let property_name = PropName::from_str(&property_name_raw); + let property_value = PropValue::from_str(&property_value); + if let (Some(property_name), Some(property_value)) = + (property_name, property_value) + { + block_state = + block_state.set(property_name, property_value); + } else { + return Err(Error::NbtFormatError( + NbtFormatError::MissingKey(property_name_raw), + )); + } + } else { + return Err(Error::NbtFormatError( + NbtFormatError::InvalidType(property_name_raw), + )); + } + } + } + palette_vec.push(block_state); + } + palette_vec + } else { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "palette".to_string(), + ))); + }; + + // Block state palette + palette::parse_palette::( + &parsed_block_state_palette, + take_assume_optional(&mut nbt_block_states, "data"), + 4, + &mut |data| { + match data { + DataFormat::All(state) => { + if !state.is_air() { + for x in 0..16 { + for y in 0..16isize { + for z in 0..16 { + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + } + } + } + DataFormat::Palette(index, state) => { + let y = (index >> 8 & 0b1111) as isize; + let z = index >> 4 & 0b1111; + let x = index & 0b1111; + + chunk.set_block_state( + x, + (y + chunk_y_offset + y_raise) as usize, + z, + state, + ); + } + } + Ok(()) + }, + )?; + + // Biome palette + let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; + let parsed_biome_palette: Vec = + if let Some(Value::List(List::String(biome_names))) = + nbt_biomes.remove("palette") + { + let mut biomes: Vec = Vec::with_capacity(biome_names.len()); + for biome in biome_names { + let biome_identity = Ident::new(biome)?; + if let Some(biome) = world.biomes.get(&biome_identity) { + biomes.push(*biome); + } else { + return Err(Error::DataFormatError(DataFormatError::UnknownType( + biome_identity, + ))); + } + } + biomes + } else { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "palette".to_string(), + ))); + }; + + palette::parse_palette::( + &parsed_biome_palette, + take_assume_optional(&mut nbt_biomes, "data"), + 0, + &mut |data| { + match data { + DataFormat::All(biome) => { + for x in 0..4 { + for y in 0..4isize { + for z in 0..4 { + chunk.set_biome( + x, + (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, + z, + biome, + ); + } + } + } + } + DataFormat::Palette(index, biome) => { + let y = (index >> 4 & 0b11) as isize; + let z = index >> 2 & 0b11; + let x = index & 0b11; + + let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); + chunk.set_biome(x, final_y as usize, z, biome); + } + } + Ok(()) + }, + )?; + } + + Ok(chunk) + } else { + Err(Error::NbtFormatError(NbtFormatError::InvalidType( + "sections".to_string(), + ))) + } + } +} + +#[derive(Copy, Clone, Debug)] +struct AnvilHeader { + offsets: [ChunkSeekLocation; 1024], + timestamps: [ChunkTimestamp; 1024], +} + +impl AnvilHeader { + /// Parses the header bytes from the current position + async fn parse(source: &mut R) -> Result { + let mut offsets = [ChunkSeekLocation::zero(); 1024]; + for offset in &mut offsets { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + offset.load(buf); + } + let mut timestamps = [ChunkTimestamp::zero(); 1024]; + for timestamp in &mut timestamps { + let mut buf = [0u8; 4]; + source.read_exact(&mut buf).await?; + timestamp.load(buf); + } + Ok(Self { + offsets, + timestamps, + }) + } + + #[inline(always)] + fn offset(&self, x: usize, z: usize) -> &ChunkSeekLocation { + &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] + } + + #[inline(always)] + fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { + &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] + } +} From 29f4308cd569ab2c8f0630f2ad3e4114e4f92e5c Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 21:06:33 +0100 Subject: [PATCH 39/75] Fix remnant of Result refactor --- valence_anvil/src/region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 6d9e48576..d1d28d656 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -111,7 +111,7 @@ impl Region { if let Some(chunk_data) = chunk_data { let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; match Self::parse_chunk_nbt(&mut nbt, world) { - Err(Error::NbtParseError(_)) => { + Err(Error::DataFormatError(DataFormatError::InvalidChunkState(..))) => { results.push((pos, None)); } Err(e) => return Err(e), From b49fbc338c37350f438a88ebb5e4e51654f52496 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 21:07:50 +0100 Subject: [PATCH 40/75] Update message at log-in --- valence_anvil/examples/java_region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 9b34b7942..229fef801 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -131,7 +131,7 @@ impl Config for Game { ); } - client.send_message("Welcome to the terrain example!".italic()); + client.send_message("Welcome to the java chunk parsing example!".italic()); } if client.is_disconnected() { From 5d8c83d2b8c620b276cf085e905a9d4d4cb44a5d Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 23:20:14 +0100 Subject: [PATCH 41/75] Cargo fmt --- valence_anvil/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 234b0738e..9c3f1eb2d 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -14,9 +14,9 @@ use valence::server::SharedServer; use crate::error::Error; -pub mod error; pub mod biome; pub mod compression; +pub mod error; mod palette; mod region; From eb4409810e23c3a1a08d46ada968899feac4d32b Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 30 Oct 2022 23:46:41 +0100 Subject: [PATCH 42/75] Define valence version --- valence_anvil/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index bcaf9dd97..d69bc80fb 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -12,7 +12,7 @@ build = "build/main.rs" edition = "2021" [dependencies] -valence = {path = ".."} +valence = {version = "0.1.0+mc1.19.2", path = ".."} rayon = "1.5.3" async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} byteorder = "1" From 4b82557429b66cdc47ed75db3a1cd73192510a08 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 3 Nov 2022 01:30:15 -0700 Subject: [PATCH 43/75] Syntax tweaks --- Cargo.toml | 2 +- valence_anvil/Cargo.toml | 10 +++++----- valence_anvil/build/biome.rs | 10 +++++----- valence_anvil/examples/java_region.rs | 20 +++----------------- valence_anvil/src/error.rs | 12 ++++++------ valence_anvil/src/lib.rs | 11 ++++------- valence_anvil/src/region.rs | 6 +++--- 7 files changed, 27 insertions(+), 44 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8023cb25e..c395d3b42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ valence_protocol = { version = "0.1.0", path = "valence_protocol", features = [" vek = "0.15.8" [dependencies.tokio] -version = "1.21.1" +version = "1.21.2" features = ["macros", "rt-multi-thread", "net", "io-util", "sync", "time"] [dependencies.reqwest] diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index d69bc80fb..ebb735fc7 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -12,11 +12,11 @@ build = "build/main.rs" edition = "2021" [dependencies] -valence = {version = "0.1.0+mc1.19.2", path = ".."} +valence = { version = "0.1.0", path = ".." } rayon = "1.5.3" -async-compression = {version = "0.3.15", features = ["tokio", "gzip", "zlib"]} -byteorder = "1" -tokio = {version = "1", features = ["fs", "io-util", "full"]} +async-compression = { version = "0.3.15", features = ["tokio", "gzip", "zlib"] } +byteorder = "1.4.3" +tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" [build-dependencies] @@ -27,4 +27,4 @@ quote = "1.0.21" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.85" rayon = "1.5.3" -num = "0.4.0" \ No newline at end of file +num = "0.4.0" diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 3f20c5652..268d5a77b 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -281,7 +281,7 @@ pub fn build() -> anyhow::Result { } pub fn from_ident>(ident: &Ident) -> Option { - if ident.namespace() != "minecraft"{ + if ident.namespace() != "minecraft" { return None; } match ident.path() { @@ -291,26 +291,26 @@ pub fn build() -> anyhow::Result { } pub fn biome(self) -> Result> { - match self{ + match self { #biomekind_to_biome } } /// Gets the biome spawn rates pub const fn spawn_rates(self) -> SpawnSettings { - match self{ + match self { #biomekind_spawn_settings_arms } } pub const fn temperature(self) -> f32 { - match self{ + match self { #biomekind_temperatures_arms } } pub const fn downfall(self) -> f32 { - match self{ + match self { #biomekind_downfall_arms } } diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 229fef801..ec629c841 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -5,17 +5,7 @@ use std::path::PathBuf; use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; -use valence::async_trait; -use valence::biome::Biome; -use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::client::{handle_event_default, GameMode}; -use valence::config::{Config, ServerListPing}; -use valence::dimension::DimensionId; -use valence::entity::{EntityId, EntityKind}; -use valence::player_list::PlayerListId; -use valence::server::{Server, SharedServer, ShutdownResult}; -use valence::text::{Color, TextFormat}; -use valence::util::chunks_in_view_distance; +use valence::prelude::*; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; @@ -35,6 +25,7 @@ struct Game { const MAX_PLAYERS: usize = 10; /// # IMPORTANT +/// /// Change the following to the world file you wish to load. /// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most /// importantly `region` directories. Only the `region` directory is accessed. @@ -50,11 +41,6 @@ impl Config for Game { type ChunkState = bool; type PlayerListState = (); - fn max_connections(&self) -> usize { - // We want status pings to be successful even if the server is full. - MAX_PLAYERS + 64 - } - fn biomes(&self) -> Vec { BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() } @@ -173,7 +159,7 @@ impl Config for Game { 0, 0, 0, - valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), + BlockState::from_kind(BlockKind::Lava), ); world.chunks.insert(pos, blank_chunk, true); } diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index a11960bec..c2c180da2 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,6 +1,6 @@ use std::error::Error as StdError; use std::fmt::{Display, Formatter}; -use std::io; +use std::{fmt, io}; use valence::ident::{Ident, IdentError}; @@ -49,14 +49,14 @@ impl From for Error { } } -impl From> for Error { - fn from(e: valence::ident::IdentError) -> Self { +impl From> for Error { + fn from(e: IdentError) -> Self { Self::DataFormatError(DataFormatError::IdentityError(e)) } } impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Error::Io(e) => e.fmt(f), Error::DataFormatError(e) => e.fmt(f), @@ -67,7 +67,7 @@ impl Display for Error { } impl Display for DataFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { DataFormatError::UnknownCompressionScheme(scheme) => { write!(f, "Unknown compression scheme: {scheme}") @@ -82,7 +82,7 @@ impl Display for DataFormatError { } impl Display for NbtFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> valence::prelude::vek::serde::__private::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { NbtFormatError::MissingKey(key) => { write!(f, "Could not find key: \"{key}\" in nbt data.") diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 9c3f1eb2d..880365583 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -81,6 +81,8 @@ impl AnvilWorld { /// # Examples /// /// ``` + /// use valence::prelude::*; + /// /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); /// let future = world.state.load_chunks(to_load); /// let parsed_chunks = futures::executor::block_on(future).unwrap(); @@ -91,12 +93,7 @@ impl AnvilWorld { /// } else { /// // There is no information on this chunk in the region file. /// let mut blank_chunk = UnloadedChunk::new(16); - /// blank_chunk.set_block_state( - /// 0, - /// 0, - /// 0, - /// valence::block::BlockState::from_kind(valence::block::BlockKind::Lava), - /// ); + /// blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); /// world.chunks.insert(pos, blank_chunk, true); /// } /// } @@ -104,7 +101,7 @@ impl AnvilWorld { pub async fn load_chunks>( &self, positions: I, - ) -> Result)>, Error> { + ) -> Result)>, Error> { let mut map = BTreeMap::>::new(); for pos in positions { let region_pos = RegionPos::from(pos); diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index d1d28d656..bce082d06 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -16,7 +16,7 @@ use crate::palette::DataFormat; use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; #[derive(Debug)] -pub struct Region { +pub struct Region { source: Mutex, offset: u64, position: RegionPos, @@ -187,7 +187,7 @@ impl Region { let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; let y_raise = isize::from(-y_min) * 16; - //Parsing sections + // Parsing sections let mut chunk = UnloadedChunk::new(section_height); for mut nbt_section in nbt_sections.into_iter() { let chunk_y_offset: isize = @@ -202,7 +202,7 @@ impl Region { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); for mut nbt_palette in nbt_palette_vec { - let block_id = valence::ident::Ident::new(take_assume::( + let block_id = Ident::new(take_assume::( &mut nbt_palette, "Name", )?)?; From 84bf30f1adb8083669150c0d33d440cf03fd5884 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 3 Nov 2022 01:41:06 -0700 Subject: [PATCH 44/75] Fix formatting --- valence_anvil/examples/java_region.rs | 7 +------ valence_anvil/src/region.rs | 6 ++---- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index ec629c841..5e27d59de 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -155,12 +155,7 @@ impl Config for Game { world.chunks.insert(pos, chunk, true); } else { let mut blank_chunk = UnloadedChunk::new(16); - blank_chunk.set_block_state( - 0, - 0, - 0, - BlockState::from_kind(BlockKind::Lava), - ); + blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); world.chunks.insert(pos, blank_chunk, true); } } diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index bce082d06..4e595c0d0 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -202,10 +202,8 @@ impl Region { let mut palette_vec: Vec = Vec::with_capacity(nbt_palette_vec.len()); for mut nbt_palette in nbt_palette_vec { - let block_id = Ident::new(take_assume::( - &mut nbt_palette, - "Name", - )?)?; + let block_id = + Ident::new(take_assume::(&mut nbt_palette, "Name")?)?; let block_kind = if let Some(block_kind) = BlockKind::from_str(block_id.path()) { block_kind From 4ca2617e3f1e2624dd2146da0e3b7a78848da6a1 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Fri, 4 Nov 2022 23:30:01 +0100 Subject: [PATCH 45/75] Fix bug: Palette data wrapping around when palette array and bitmask do not align. This fixes blocks randomly repeating at the start of chunk subsections --- valence_anvil/Cargo.toml | 1 + valence_anvil/examples/java_region.rs | 71 +++++++++++++++++++-------- valence_anvil/src/error.rs | 13 +---- valence_anvil/src/lib.rs | 15 +++--- valence_anvil/src/palette.rs | 18 ++++--- valence_anvil/src/region.rs | 2 + 6 files changed, 73 insertions(+), 47 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index ebb735fc7..e9b941da0 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -18,6 +18,7 @@ async-compression = { version = "0.3.15", features = ["tokio", "gzip", "zlib"] } byteorder = "1.4.3" tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" +thiserror = "1.0.37" [build-dependencies] anyhow = "1.0.65" diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 5e27d59de..8060a13ca 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -2,39 +2,64 @@ extern crate valence; use std::net::SocketAddr; use std::path::PathBuf; -use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::prelude::*; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; +/// # IMPORTANT +/// +/// Run this example with one argument containing the path of the the following +/// to the world directory you wish to load. Inside this directory you can +/// commonly see `advancements`, `DIM1`, `DIM-1` and most importantly `region` +/// subdirectories. Only the `region` directory is accessed. pub fn main() -> ShutdownResult { - valence::start_server( - Game { - player_count: AtomicUsize::new(0), - }, - None, - ) + let args: Vec = std::env::args().collect(); + if let Some(world_folder) = args.get(1) { + let world_folder = PathBuf::from(world_folder); + if world_folder.exists() && world_folder.is_dir() { + if !world_folder.join("region").exists() { + ShutdownResult::Err( + "Could not find the `region` folder inside the world directory.".into(), + ) + } else { + // This actually starts and runs the server. + valence::start_server( + Game { + world_dir: world_folder, + player_count: AtomicUsize::new(0), + }, + None, + ) + } + } else { + ShutdownResult::Err( + "World directory argument is not valid: Must be a folder that exists.".into(), + ) + } + } else { + ShutdownResult::Err("Please add the world directory as program argument.".into()) + } +} + +#[derive(Debug, Default)] +struct ClientData { + id: EntityId, + //block: valence::block::BlockKind } struct Game { + world_dir: PathBuf, player_count: AtomicUsize, } const MAX_PLAYERS: usize = 10; -/// # IMPORTANT -/// -/// Change the following to the world file you wish to load. -/// Inside this folder you should see `advancements`, `DIM1`, `DIM-1` and most -/// importantly `region` directories. Only the `region` directory is accessed. -const WORLD_FOLDER: &str = "./test_data/"; - #[async_trait] impl Config for Game { type ServerState = Option; - type ClientState = EntityId; + type ClientState = ClientData; type EntityState = (); type WorldState = AnvilWorld; /// If the chunk should stay loaded at the end of the tick. @@ -65,10 +90,9 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); server.worlds.insert( DimensionId::default(), - AnvilWorld::new(world_folder, &server.shared), + AnvilWorld::new::(&self.world_dir, server.shared.biomes()), ); server.state = Some(server.player_lists.insert(()).0); } @@ -93,7 +117,7 @@ impl Config for Game { .entities .insert_with_uuid(EntityKind::Player, client.uuid(), ()) { - Some((id, _)) => client.state = id, + Some((id, _)) => client.state.id = id, None => { client.disconnect("Conflicting UUID"); return false; @@ -117,7 +141,12 @@ impl Config for Game { ); } - client.send_message("Welcome to the java chunk parsing example!".italic()); + client.send_message("Welcome to the java chunk parsing example!"); + client.send_message( + "Chunks with a single lava source block indicates that the chunk is not \ + (fully) generated." + .italic(), + ); } if client.is_disconnected() { @@ -125,12 +154,12 @@ impl Config for Game { if let Some(id) = &server.state { server.player_lists.get_mut(id).remove(client.uuid()); } - server.entities.remove(client.state); + server.entities.remove(client.state.id); return false; } - if let Some(entity) = server.entities.get_mut(client.state) { + if let Some(entity) = server.entities.get_mut(client.state.id) { while handle_event_default(client, entity).is_some() {} } diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index c2c180da2..417c341a5 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,10 +1,10 @@ -use std::error::Error as StdError; use std::fmt::{Display, Formatter}; use std::{fmt, io}; +use thiserror::Error; use valence::ident::{Ident, IdentError}; -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Error { Io(io::Error), DataFormatError(DataFormatError), @@ -28,15 +28,6 @@ pub enum DataFormatError { InvalidPalette, } -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - Self::Io(e) => Some(e), - _ => None, - } - } -} - impl From for Error { fn from(e: io::Error) -> Self { Self::Io(e) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 880365583..857e8b06c 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -6,11 +6,10 @@ use byteorder::{BigEndian, ByteOrder}; use region::Region; use tokio::fs::File; use tokio::sync::{Mutex, MutexGuard}; -use valence::biome::BiomeId; +use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; use valence::ident::Ident; -use valence::server::SharedServer; use crate::error::Error; @@ -46,21 +45,23 @@ impl AnvilWorld { /// ``` /// impl Config for Game { /// fn init(&self, server: &mut Server) { - /// let world_folder = PathBuf::from_str(WORLD_FOLDER).unwrap(); /// server.worlds.insert( /// DimensionId::default(), - /// AnvilWorld::new(world_folder, &server.shared), + /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), /// ); /// } /// } /// ``` - pub fn new(directory: PathBuf, server: &SharedServer) -> Self { + pub fn new<'a, C: Config>( + directory: impl Into, + server_biomes: impl Iterator, + ) -> Self { let mut biomes = BTreeMap::new(); - for (id, biome) in server.biomes() { + for (id, biome) in server_biomes { biomes.insert(biome.name.clone(), id); } Self { - world_root: directory, + world_root: directory.into(), biomes, region_files: Mutex::new(BTreeMap::new()), } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 65d8ffcc7..490eb552d 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -11,9 +11,15 @@ pub fn parse_palette) -> Result<(), Error>)>( source: &Vec, data: Option>, min_bits: usize, + expected_len: usize, fun: &mut F, ) -> Result<(), Error> { let palette_len = source.len(); + if palette_len == 0 { + return Err(crate::error::Error::DataFormatError( + DataFormatError::InvalidPalette, + )); + } if let Some(data) = data { if palette_len < 2 || data.is_empty() { fun(DataFormat::All(source[0]))?; @@ -40,21 +46,17 @@ pub fn parse_palette) -> Result<(), Error>)>( let palette_index_unshifted = (integer & mask) as usize; let palette_index_shifted = palette_index_unshifted >> rev_shift; - // Uncomment the following to aid in debugging. - // println!("IN - // \t{integer:064b}\nMSK\t{mask:064b}({bits_per_index})\nRES\ - // t{palette_index_unshifted:064b}\nSFT\t{palette_index_shifted:064b} - // ({rev_shift} - {trailing_bits})\n"); if palette_index_shifted > choice_len { - //panic!("############### INVALID: {:?} {:?} {:?} {:?} {:?}", - // palette_index_shifted, choice_len, - // bits_per_index, source, source.len()); return Err(crate::error::Error::DataFormatError( DataFormatError::InvalidPalette, )); } else { fun(DataFormat::Palette(index, source[palette_index_shifted]))?; index += 1; + // Prevents interpreting the rest of the long as data. + if index == expected_len { + return Ok(()); + } } } } diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 4e595c0d0..7468362bd 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -251,6 +251,7 @@ impl Region { &parsed_block_state_palette, take_assume_optional(&mut nbt_block_states, "data"), 4, + 16 * 16 * 16, &mut |data| { match data { DataFormat::All(state) => { @@ -314,6 +315,7 @@ impl Region { &parsed_biome_palette, take_assume_optional(&mut nbt_biomes, "data"), 0, + 4 * 4 * 4, &mut |data| { match data { DataFormat::All(biome) => { From 04657d7a6a05d2dc8ae697606a2dcd213000ef21 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 5 Nov 2022 12:09:24 +0100 Subject: [PATCH 46/75] Change error implementations to `thiserror` macro derive where possible --- valence_anvil/src/error.rs | 88 +++++++++++--------------------------- 1 file changed, 25 insertions(+), 63 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 417c341a5..d87de06f1 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,84 +1,46 @@ -use std::fmt::{Display, Formatter}; -use std::{fmt, io}; +use std::io; use thiserror::Error; use valence::ident::{Ident, IdentError}; -#[derive(Debug, Error)] +#[derive(Error, Debug)] pub enum Error { - Io(io::Error), - DataFormatError(DataFormatError), - NbtParseError(valence::nbt::Error), - NbtFormatError(NbtFormatError), + #[error(transparent)] + Io(#[from] io::Error), + #[error(transparent)] + DataFormatError(#[from] DataFormatError), + #[error(transparent)] + NbtParseError(#[from] valence::nbt::Error), + #[error(transparent)] + NbtFormatError(#[from] NbtFormatError), } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum NbtFormatError { + #[error("Missing key: {0}")] MissingKey(String), + #[error("Invalid type: {0}")] InvalidType(String), } -#[derive(Debug)] +#[derive(Error, Debug)] pub enum DataFormatError { + #[error("Unknown compression scheme: {0}")] UnknownCompressionScheme(u8), + #[error("Invalid chunk size: {0}")] InvalidChunkSize(usize), - IdentityError(IdentError), + #[error(transparent)] + IdentityError(#[from] IdentError), + #[error("Unknown identity: {0}")] UnknownType(Ident), + #[error("Invalid chunk state: {0}")] InvalidChunkState(String), + #[error("Invalid chunk palette")] InvalidPalette, } -impl From for Error { - fn from(e: io::Error) -> Self { - Self::Io(e) +impl From> for Error{ + fn from(err: IdentError) -> Self { + Self::DataFormatError(DataFormatError::IdentityError(err)) } -} - -impl From for Error { - fn from(e: valence::nbt::Error) -> Self { - Self::NbtParseError(e) - } -} - -impl From> for Error { - fn from(e: IdentError) -> Self { - Self::DataFormatError(DataFormatError::IdentityError(e)) - } -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Error::Io(e) => e.fmt(f), - Error::DataFormatError(e) => e.fmt(f), - Error::NbtParseError(e) => e.fmt(f), - Error::NbtFormatError(e) => e.fmt(f), - } - } -} - -impl Display for DataFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - DataFormatError::UnknownCompressionScheme(scheme) => { - write!(f, "Unknown compression scheme: {scheme}") - } - DataFormatError::InvalidChunkSize(size) => write!(f, "Invalid chunk size: {size}"), - DataFormatError::IdentityError(e) => e.fmt(f), - DataFormatError::UnknownType(identity) => write!(f, "Unknown identity: {identity}"), - DataFormatError::InvalidChunkState(state) => write!(f, "Unknown chunk state: {state}"), - DataFormatError::InvalidPalette => write!(f, "Invalid chunk palette"), - } - } -} - -impl Display for NbtFormatError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - NbtFormatError::MissingKey(key) => { - write!(f, "Could not find key: \"{key}\" in nbt data.") - } - NbtFormatError::InvalidType(key) => write!(f, "Unexpected type for key: \"{key}\""), - } - } -} +} \ No newline at end of file From 3313d31594f97a7ea82817f7cdb46c193fdb379d Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 5 Nov 2022 12:13:59 +0100 Subject: [PATCH 47/75] cargo fmt --- valence_anvil/src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index d87de06f1..ba594a6ce 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -39,8 +39,8 @@ pub enum DataFormatError { InvalidPalette, } -impl From> for Error{ +impl From> for Error { fn from(err: IdentError) -> Self { Self::DataFormatError(DataFormatError::IdentityError(err)) } -} \ No newline at end of file +} From 35cc20bc788bad1a28cc1e1a894ed369d96fc435 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 6 Nov 2022 12:42:22 +0100 Subject: [PATCH 48/75] Refactor components. Move from lib.rs to region.rs --- valence_anvil/src/lib.rs | 97 ++----------------------------------- valence_anvil/src/region.rs | 95 +++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 857e8b06c..e2db7b1bd 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,9 +1,8 @@ use std::collections::BTreeMap; -use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::path::{Path, PathBuf}; +use std::fmt::Debug; +use std::path::PathBuf; -use byteorder::{BigEndian, ByteOrder}; -use region::Region; +use region::{ChunkTimestamp, Region, RegionPos}; use tokio::fs::File; use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; @@ -182,93 +181,3 @@ impl AnvilWorld { .as_mut()) } } - -#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] -pub struct RegionPos { - x: i32, - z: i32, -} - -impl From for RegionPos { - fn from(pos: ChunkPos) -> Self { - Self { - x: pos.x >> 5, - z: pos.z >> 5, - } - } -} - -impl RegionPos { - pub fn path(self, world_root: impl AsRef) -> PathBuf { - world_root - .as_ref() - .join("region") - .join(format!("r.{}.{}.mca", self.x, self.z)) - } - - pub fn contains(self, chunk_pos: ChunkPos) -> bool { - Self::from(chunk_pos) == self - } -} - -/// The location of the chunk inside the region file. -#[derive(Copy, Clone, Debug)] -struct ChunkSeekLocation { - offset_sectors: u32, - len_sectors: u8, -} - -impl ChunkSeekLocation { - const fn zero() -> Self { - Self { - offset_sectors: 0, - len_sectors: 0, - } - } - - const fn offset(&self) -> u64 { - self.offset_sectors as u64 * 1024 * 4 - } - - const fn len(&self) -> usize { - self.len_sectors as usize * 1024 * 4 - } - - fn load(&mut self, chunk: [u8; 4]) { - self.offset_sectors = BigEndian::read_u24(&chunk[..3]); - self.len_sectors = chunk[3]; - } -} - -/// The timestamp when the chunk was last modified in seconds since epoch. -#[derive(Copy, Clone)] -pub struct ChunkTimestamp(u32); - -impl Debug for ChunkTimestamp { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}s", self.0) - } -} - -impl ChunkTimestamp { - const fn zero() -> Self { - Self(0) - } - - fn load(&mut self, chunk: [u8; 4]) { - self.0 = BigEndian::read_u32(&chunk) - } - - fn into_option(self) -> Option { - if self.0 == 0 { - None - } else { - Some(self) - } - } - - #[inline(always)] - pub fn seconds_since_epoch(self) -> u32 { - self.0 - } -} diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 7468362bd..83e7e3ab4 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -1,4 +1,5 @@ use std::io::SeekFrom; +use std::path::{Path, PathBuf}; use byteorder::{BigEndian, ByteOrder}; use tokio::fs::File; @@ -9,11 +10,13 @@ use valence::block::{BlockKind, BlockState, PropName, PropValue}; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; +use valence::prelude::vek::serde::__private::fmt::{Debug, Result as FmtResult}; +use valence::prelude::vek::serde::__private::Formatter; use crate::compression::CompressionScheme; use crate::error::{DataFormatError, Error, NbtFormatError}; use crate::palette::DataFormat; -use crate::{palette, AnvilWorld, ChunkSeekLocation, ChunkTimestamp, RegionPos}; +use crate::{palette, AnvilWorld}; #[derive(Debug)] pub struct Region { @@ -392,3 +395,93 @@ impl AnvilHeader { &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] } } + +/// The location of the chunk inside the region file. +#[derive(Copy, Clone, Debug)] +struct ChunkSeekLocation { + offset_sectors: u32, + len_sectors: u8, +} + +impl ChunkSeekLocation { + const fn zero() -> Self { + Self { + offset_sectors: 0, + len_sectors: 0, + } + } + + const fn offset(&self) -> u64 { + self.offset_sectors as u64 * 1024 * 4 + } + + const fn len(&self) -> usize { + self.len_sectors as usize * 1024 * 4 + } + + fn load(&mut self, chunk: [u8; 4]) { + self.offset_sectors = BigEndian::read_u24(&chunk[..3]); + self.len_sectors = chunk[3]; + } +} + +/// The timestamp when the chunk was last modified in seconds since epoch. +#[derive(Copy, Clone)] +pub struct ChunkTimestamp(u32); + +impl Debug for ChunkTimestamp { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!(f, "{}s", self.0) + } +} + +impl ChunkTimestamp { + const fn zero() -> Self { + Self(0) + } + + fn load(&mut self, chunk: [u8; 4]) { + self.0 = BigEndian::read_u32(&chunk) + } + + fn into_option(self) -> Option { + if self.0 == 0 { + None + } else { + Some(self) + } + } + + #[inline(always)] + pub fn seconds_since_epoch(self) -> u32 { + self.0 + } +} + +#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] +pub struct RegionPos { + x: i32, + z: i32, +} + +impl From for RegionPos { + fn from(pos: ChunkPos) -> Self { + Self { + x: pos.x >> 5, + z: pos.z >> 5, + } + } +} + +impl RegionPos { + pub fn path(self, world_root: impl AsRef) -> PathBuf { + world_root + .as_ref() + .join("region") + .join(format!("r.{}.{}.mca", self.x, self.z)) + } + + pub fn contains(self, chunk_pos: ChunkPos) -> bool { + Self::from(chunk_pos) == self + } +} From 5571416ad4fa82be5fef6f032ae769ca5b5d6624 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Mon, 7 Nov 2022 20:50:09 +0100 Subject: [PATCH 49/75] Allow taking an owned or borrowed value for Biome. Prevents boilerplate. --- valence_anvil/examples/java_region.rs | 2 +- valence_anvil/src/lib.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 8060a13ca..569a4187a 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -92,7 +92,7 @@ impl Config for Game { fn init(&self, server: &mut Server) { server.worlds.insert( DimensionId::default(), - AnvilWorld::new::(&self.world_dir, server.shared.biomes()), + AnvilWorld::new::(&self.world_dir, server.shared.biomes()), ); server.state = Some(server.player_lists.insert(()).0); } diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index e2db7b1bd..9c938f057 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,3 +1,4 @@ +use std::borrow::Borrow; use std::collections::BTreeMap; use std::fmt::Debug; use std::path::PathBuf; @@ -46,18 +47,18 @@ impl AnvilWorld { /// fn init(&self, server: &mut Server) { /// server.worlds.insert( /// DimensionId::default(), - /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), + /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), /// ); /// } /// } /// ``` - pub fn new<'a, C: Config>( + pub fn new>( directory: impl Into, - server_biomes: impl Iterator, + server_biomes: impl Iterator, ) -> Self { let mut biomes = BTreeMap::new(); for (id, biome) in server_biomes { - biomes.insert(biome.name.clone(), id); + biomes.insert(biome.borrow().name.clone(), id); } Self { world_root: directory.into(), From 834e6a9c3b0238619fe8dd1213c0296c1ae2335a Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 13 Nov 2022 13:53:54 +0100 Subject: [PATCH 50/75] NONFUNCTIONAL: Benchmark set-up. Still needs a way to download one git directory only --- .gitignore | 1 + valence_anvil/Cargo.toml | 7 ++ valence_anvil/benches/world_parsing.rs | 106 +++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 valence_anvil/benches/world_parsing.rs diff --git a/.gitignore b/.gitignore index 5ae13276c..546f059ae 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ Cargo.lock flamegraph.svg perf.data perf.data.old +/valence_anvil/.asset_cache/ diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index e9b941da0..4b788f560 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -20,6 +20,13 @@ tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" thiserror = "1.0.37" +[dev-dependencies] +criterion = { version = "0.4.0", features = ["async", "async_tokio"] } + +[[bench]] +name = "world_parsing" +harness = false + [build-dependencies] anyhow = "1.0.65" heck = "0.4.0" diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs new file mode 100644 index 000000000..709ef7686 --- /dev/null +++ b/valence_anvil/benches/world_parsing.rs @@ -0,0 +1,106 @@ +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use tokio::runtime::Builder; +use valence::biome::BiomeId; +use valence::chunk::ChunkPos; +use valence::config::Config; +use valence_anvil::biome::BiomeKind; +use valence_anvil::AnvilWorld; +use std::process::{Command, Stdio}; +use std::io::Write; +use std::fs::create_dir_all; + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); + +const BENCHMARK_WORLD_ASSET: GitAsset = GitAsset::new( + "https://github.com/TerminatorNL/valence-test-data.git", + "Worlds/1.19.2/Benchmark world SP" +); + +struct GitAsset<'a> { + repository: &'a str, + repo_path: &'a str, +} + +impl<'a> GitAsset<'a> { + pub const fn new(repository: &'a str, repo_path: &'a str) -> Self { + GitAsset { + repository, + repo_path + } + } + + /// Downloads the asset from git if they aren't already downloaded. + /// This download uses the 'git' command. + /// Returns the location of the downloaded asset. + pub fn load(&self) -> PathBuf { + let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); + + + create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache`"); + let asset_cache_dir = asset_cache_dir.canonicalize().expect("Unable to resolve `.asset_cache` directory"); + +// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["clone", ""]).spawn().expect("Failed to execute `git clone` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git clone` command output").stdout); +// +// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["sparse-checkout", "set", self.repo_path]).spawn().expect("Failed to execute `git sparse-checkout` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git sparse-checkout` command output").stdout); +// +// let cmd = Command::new("pwd").current_dir(&asset_cache_dir).spawn().expect("Failed to execute `pwd` command"); +// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `pwd` command output").stdout).expect("Unable to write output to console"); + + unimplemented!("Asset downloading is not yet implemented") + } +} + +struct BenchmarkConfig; +impl Config for BenchmarkConfig { + type ServerState = (); + type ClientState = (); + type EntityState = (); + type WorldState = (); + type ChunkState = (); + type PlayerListState = (); +} + +fn criterion_benchmark(c: &mut Criterion) { + let world_directory = BENCHMARK_WORLD_ASSET.load(); + + let world = AnvilWorld::new::( + world_directory, + BiomeKind::ALL + .iter() + .map(|b| (BiomeId::default(), b.biome().unwrap())), + ); + + let mut load_targets = Vec::new(); + for x in -5..5 { + for z in -5..5 { + load_targets.push(ChunkPos::new(x, z)); + } + } + + let runtime = Builder::new_multi_thread() + .enable_all() + .build() + .expect("Creating runtime failed"); + + c.bench_function("Load square 10x10", |b| { + b.to_async(&runtime).iter_with_setup( + || load_targets.clone().into_iter(), + |targets| async { + for (chunk_pos, chunk) in world.load_chunks(black_box(targets)).await.unwrap() { + assert!( + chunk.is_some(), + "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ + generated?" + ); + black_box(chunk); + } + }, + ); + }); +} From 1a2873a9231df214c2822c2915b0f1c4f78959db Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 13 Nov 2022 20:10:30 +0100 Subject: [PATCH 51/75] Add benchmarks to valence_anvil --- valence_anvil/Cargo.toml | 6 + valence_anvil/benches/benchtools.rs | 178 +++++++++++++++++++++++++ valence_anvil/benches/world_parsing.rs | 53 +------- 3 files changed, 191 insertions(+), 46 deletions(-) create mode 100644 valence_anvil/benches/benchtools.rs diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 4b788f560..96858bf6c 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -21,6 +21,12 @@ futures = "0.3.24" thiserror = "1.0.37" [dev-dependencies] +reqwest = { version = "0.11.12", features = ["blocking", "stream"] } +tempfile = "3.3.0" +zip = "0.5" +fs_extra = "1.2.0" +zip-extensions = "0.6.1" + criterion = { version = "0.4.0", features = ["async", "async_tokio"] } [[bench]] diff --git a/valence_anvil/benches/benchtools.rs b/valence_anvil/benches/benchtools.rs new file mode 100644 index 000000000..c4fb1d6c1 --- /dev/null +++ b/valence_anvil/benches/benchtools.rs @@ -0,0 +1,178 @@ +use std::fs::{create_dir_all, DirEntry}; +use std::io; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use fs_extra::dir::CopyOptions; +use reqwest::IntoUrl; + +/// Describes where to find the asset if it already has been downloaded and from +/// which URL the asset can be downloaded. More asset types can be added on +/// demand by modifying this enum. +pub enum WebAsset, URL: IntoUrl> { + ZippedDirectory { + destination_path: DestinationPath, + remove_top_level_dir: bool, + url: URL, + }, +} + +impl, URL: IntoUrl + Clone> WebAsset { + /// Creates a ZippedDirectory asset type. + /// + /// # Arguments + /// + /// * `destination_path`: A unique path for this asset. If the path is + /// relative, it will be placed under the `.asset_cache` directory. + /// Relative paths are recommended. + /// * `remove_top_level_dir`: Some zip files wrap all their contents in an + /// additional folder. Setting this value to `true` will remove that + /// redundant directory. If the Zip file contains multiple + /// files/directories in the root, this will cause a panic. + /// * `url`: The URL from which to download the Zip file. + /// + /// returns: `WebAsset` The created asset. + /// + /// # Examples + /// + /// ``` + /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + /// "BenchmarkWorld", + /// true, + /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", + /// ); + /// ``` + pub const fn zipped_directory( + destination_path: DestinationPath, + remove_top_level_dir: bool, + url: URL, + ) -> Self { + Self::ZippedDirectory { + destination_path, + remove_top_level_dir, + url, + } + } + + fn url(&self) -> URL { + match self { + WebAsset::ZippedDirectory { url, .. } => url.clone(), + } + } + + fn destination_path(&self) -> &DestinationPath { + match self { + WebAsset::ZippedDirectory { + destination_path: directory_name, + .. + } => directory_name, + } + } + + /// Loads the asset. If the asset is already present on the system due to a + /// prior run, the cached asset is used instead. If the asset is not + /// cached yet, this function downloads the asset using the current thread. + /// This will block until the download is complete. + /// + /// returns: `PathBuf` The reference to the asset on the file system + /// + /// # Examples + /// + /// ``` + /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + /// "BenchmarkWorld", + /// true, + /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", + /// ); + /// let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); + /// ``` + pub fn load_blocking_panic(&self) -> PathBuf { + let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); + create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache` directory"); + let final_path = asset_cache_dir.join(self.destination_path()); + if final_path.exists() { + return final_path; + } + + let mut request = reqwest::blocking::get(self.url()) + .expect("File download request failed") + .error_for_status() + .unwrap(); + + let cache_download_directory = asset_cache_dir.join("downloads"); + create_dir_all(&cache_download_directory) + .expect("Unable to create `.asset_cache/downloads` directory"); + + let mut downloaded_zip_file = tempfile::tempfile_in(&cache_download_directory) + .expect("Could not create the temporary file"); + + println!( + "Downloading {:?} from {}", + self.destination_path().as_ref(), + self.url().as_str() + ); + request + .copy_to(&mut downloaded_zip_file) + .expect("Could not write web contents to the temporary file"); + + match self { + WebAsset::ZippedDirectory { + remove_top_level_dir: remove_single_top_level_dir, + .. + } => { + let mut zip_archive = zip::ZipArchive::new(downloaded_zip_file) + .expect("unable to create zip archive from downloaded content"); + if *remove_single_top_level_dir { + let temporary_directory = tempfile::tempdir_in(&cache_download_directory) + .expect("Unable to create temporary directory in `.asset_cache`"); + zip_archive + .extract(&temporary_directory) + .expect("Unable to unzip downloaded contents"); + let mut entries: Vec> = temporary_directory + .path() + .read_dir() + .expect("Could not read the contents of the temporary directory") + .into_iter() + .collect(); + if let Some(top_level_directory) = entries.pop() { + assert_eq!( + entries.len(), + 0, + "Found more than one entry in the top level directory of the Zip file." + ); + let top_level_directory = top_level_directory.unwrap(); + let top_level_directory = top_level_directory.path(); + assert!( + top_level_directory.is_dir(), + "The only content in the Zip is a file!" + ); + create_dir_all(&final_path) + .expect("Could not create a directory inside the asset cache"); + fs_extra::move_items( + top_level_directory + .read_dir() + .unwrap() + .map(|v| v.unwrap().path()) + .collect::>() + .as_slice(), + &final_path, + &CopyOptions::new(), + ) + .unwrap(); + // We keep the temporary directory around until we're done moving files out + // of it. + drop(temporary_directory); + final_path + } else { + panic!("The downloaded zip file was empty"); + } + } else { + zip_archive + .extract(&final_path) + .expect("Unable to unzip downloaded contents"); + final_path + } + } + } + } +} diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 709ef7686..2acf585b5 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -1,6 +1,3 @@ -use std::path::{Path, PathBuf}; -use std::str::FromStr; - use criterion::{black_box, criterion_group, criterion_main, Criterion}; use tokio::runtime::Builder; use valence::biome::BiomeId; @@ -8,53 +5,17 @@ use valence::chunk::ChunkPos; use valence::config::Config; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -use std::process::{Command, Stdio}; -use std::io::Write; -use std::fs::create_dir_all; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -const BENCHMARK_WORLD_ASSET: GitAsset = GitAsset::new( - "https://github.com/TerminatorNL/valence-test-data.git", - "Worlds/1.19.2/Benchmark world SP" -); - -struct GitAsset<'a> { - repository: &'a str, - repo_path: &'a str, -} - -impl<'a> GitAsset<'a> { - pub const fn new(repository: &'a str, repo_path: &'a str) -> Self { - GitAsset { - repository, - repo_path - } - } - - /// Downloads the asset from git if they aren't already downloaded. - /// This download uses the 'git' command. - /// Returns the location of the downloaded asset. - pub fn load(&self) -> PathBuf { - let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); - - - create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache`"); - let asset_cache_dir = asset_cache_dir.canonicalize().expect("Unable to resolve `.asset_cache` directory"); - -// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["clone", ""]).spawn().expect("Failed to execute `git clone` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git clone` command output").stdout); -// -// let cmd = Command::new("git").current_dir(&asset_cache_dir).args(["sparse-checkout", "set", self.repo_path]).spawn().expect("Failed to execute `git sparse-checkout` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `git sparse-checkout` command output").stdout); -// -// let cmd = Command::new("pwd").current_dir(&asset_cache_dir).spawn().expect("Failed to execute `pwd` command"); -// std::io::stdout().write_all(&cmd.wait_with_output().expect("Failed to get `pwd` command output").stdout).expect("Unable to write output to console"); +mod benchtools; - unimplemented!("Asset downloading is not yet implemented") - } -} +const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( + "1.19.2 benchmark world", + true, + "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", +); struct BenchmarkConfig; impl Config for BenchmarkConfig { @@ -67,7 +28,7 @@ impl Config for BenchmarkConfig { } fn criterion_benchmark(c: &mut Criterion) { - let world_directory = BENCHMARK_WORLD_ASSET.load(); + let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); let world = AnvilWorld::new::( world_directory, From bb0489455378d304644e9ca25d595996ecc72e9c Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 14 Nov 2022 22:51:29 -0800 Subject: [PATCH 52/75] Fix imports --- valence_anvil/build/biome.rs | 4 ++-- valence_anvil/src/error.rs | 2 +- valence_anvil/src/lib.rs | 2 +- valence_anvil/src/region.rs | 9 ++++----- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 268d5a77b..993494f81 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -238,8 +238,8 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { - use valence::biome::{Biome,BiomeGrassColorModifier,BiomePrecipitation}; - use valence::ident::{Ident,IdentError}; + use valence::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation}; + use valence::protocol::ident::{Ident, IdentError}; use std::str::FromStr; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index ba594a6ce..76bb2f9af 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,7 +1,7 @@ use std::io; use thiserror::Error; -use valence::ident::{Ident, IdentError}; +use valence::protocol::ident::{Ident, IdentError}; #[derive(Error, Debug)] pub enum Error { diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 9c938f057..398767b8f 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -9,7 +9,7 @@ use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; -use valence::ident::Ident; +use valence::protocol::Ident; use crate::error::Error; diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 83e7e3ab4..22e9de154 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -1,3 +1,4 @@ +use std::fmt::{self, Debug, Formatter}; use std::io::SeekFrom; use std::path::{Path, PathBuf}; @@ -6,12 +7,10 @@ use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; use tokio::sync::Mutex; use valence::biome::BiomeId; -use valence::block::{BlockKind, BlockState, PropName, PropValue}; use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::ident::Ident; use valence::nbt::{Compound, List, Value}; -use valence::prelude::vek::serde::__private::fmt::{Debug, Result as FmtResult}; -use valence::prelude::vek::serde::__private::Formatter; +use valence::protocol::block::{BlockKind, BlockState, PropName, PropValue}; +use valence::protocol::Ident; use crate::compression::CompressionScheme; use crate::error::{DataFormatError, Error, NbtFormatError}; @@ -430,7 +429,7 @@ impl ChunkSeekLocation { pub struct ChunkTimestamp(u32); impl Debug for ChunkTimestamp { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}s", self.0) } } From 4b7f877f4194e2f898829c09f20627e04df4a131 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 14 Nov 2022 22:59:14 -0800 Subject: [PATCH 53/75] Avoid OpenSSL dependency on linux --- valence_anvil/Cargo.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 96858bf6c..87a64dd23 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -21,14 +21,18 @@ futures = "0.3.24" thiserror = "1.0.37" [dev-dependencies] -reqwest = { version = "0.11.12", features = ["blocking", "stream"] } tempfile = "3.3.0" zip = "0.5" fs_extra = "1.2.0" zip-extensions = "0.6.1" - criterion = { version = "0.4.0", features = ["async", "async_tokio"] } +[dev-dependencies.reqwest] +version = "0.11.12" +default-features = false +# Avoid OpenSSL dependency on Linux. +features = ["rustls-tls", "blocking", "stream"] + [[bench]] name = "world_parsing" harness = false From 828bb6e985fd09e52e09ca019a8abfee3040fd32 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Thu, 1 Dec 2022 22:32:25 +0100 Subject: [PATCH 54/75] Update valence_anvil --- Cargo.toml | 1 + src/lib.rs | 1 - valence_anvil/benches/world_parsing.rs | 1 + valence_anvil/examples/java_region.rs | 7 +++++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c395d3b42..1e851aec4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,7 @@ members = [ "valence_nbt", "valence_protocol", "packet_inspector", + "valence_anvil", "benchmarks/bench_players" ] exclude = ["benchmarks/rust-mc-bot"] diff --git a/src/lib.rs b/src/lib.rs index be880fb98..8e00ce748 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,7 +118,6 @@ mod slab_versioned; pub mod spatial_index; pub mod util; pub mod world; -pub mod biomes; /// Use `valence::prelude::*` to import the most commonly used items from the /// library. diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 2acf585b5..568f68cd4 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -25,6 +25,7 @@ impl Config for BenchmarkConfig { type WorldState = (); type ChunkState = (); type PlayerListState = (); + type InventoryState = (); } fn criterion_benchmark(c: &mut Criterion) { diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 569a4187a..4f4cf155d 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -65,6 +65,7 @@ impl Config for Game { /// If the chunk should stay loaded at the end of the tick. type ChunkState = bool; type PlayerListState = (); + type InventoryState = (); fn biomes(&self) -> Vec { BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() @@ -124,7 +125,7 @@ impl Config for Game { } } - client.spawn(world_id); + client.respawn(world_id); client.set_flat(true); client.set_game_mode(GameMode::Spectator); client.teleport([0.0, 200.0, 0.0], 0.0, 0.0); @@ -160,7 +161,9 @@ impl Config for Game { } if let Some(entity) = server.entities.get_mut(client.state.id) { - while handle_event_default(client, entity).is_some() {} + while let Some(event) = client.next_event() { + event.handle_default(client, entity); + } } let dist = client.view_distance(); From 91808e720203177bce77cd37419f635eeb0343ee Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Fri, 2 Dec 2022 00:30:57 +0100 Subject: [PATCH 55/75] Remove git merge remnant --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3408389aa..021f267ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,6 @@ members = [ "valence_anvil", "valence_protocol", "packet_inspector", - "valence_anvil", "benchmarks/bench_players" ] exclude = ["benchmarks/rust-mc-bot"] From a4877c1cf77c4ceeae2ed20f388997200cfa8402 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 4 Dec 2022 18:43:43 +0100 Subject: [PATCH 56/75] Cleanup tests. Add example usage of using assets.rs through #[path] Do not compile example usage in lib.rs --- valence_anvil/benches/world_parsing.rs | 5 +- valence_anvil/src/lib.rs | 6 +- .../benchtools.rs => tests/assets.rs} | 0 valence_anvil/tests/parse_world.rs | 56 +++++++++++++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) rename valence_anvil/{benches/benchtools.rs => tests/assets.rs} (100%) create mode 100644 valence_anvil/tests/parse_world.rs diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 568f68cd4..d019ad9f8 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -9,9 +9,10 @@ use valence_anvil::AnvilWorld; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -mod benchtools; +#[path="../tests/assets.rs"] +pub mod assets; -const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( +const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( "1.19.2 benchmark world", true, "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 398767b8f..da66bb642 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -28,7 +28,6 @@ pub struct AnvilWorld { } impl AnvilWorld { - //noinspection ALL /// Creates an `AnvilWorld` instance. /// /// # Arguments @@ -42,7 +41,7 @@ impl AnvilWorld { /// /// # Examples /// - /// ``` + /// ```ignore /// impl Config for Game { /// fn init(&self, server: &mut Server) { /// server.worlds.insert( @@ -67,7 +66,6 @@ impl AnvilWorld { } } - //noinspection ALL /// Load chunks from the available region files within the world directory. /// This operation will temporarily block operations on all region files /// within `AnvilWorld`. @@ -81,7 +79,7 @@ impl AnvilWorld { /// /// # Examples /// - /// ``` + /// ```ignore /// use valence::prelude::*; /// /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); diff --git a/valence_anvil/benches/benchtools.rs b/valence_anvil/tests/assets.rs similarity index 100% rename from valence_anvil/benches/benchtools.rs rename to valence_anvil/tests/assets.rs diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs new file mode 100644 index 000000000..e2a1a20ce --- /dev/null +++ b/valence_anvil/tests/parse_world.rs @@ -0,0 +1,56 @@ +use valence::biome::BiomeId; +use valence::chunk::ChunkPos; +use valence::config::Config; +use valence_anvil::biome::BiomeKind; +use valence_anvil::AnvilWorld; +use tokio::runtime::Builder; + +#[path="../tests/assets.rs"] +pub mod assets; + +const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( + "1.19.2 benchmark world", + true, + "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", +); + +struct TestConfig; +impl Config for TestConfig { + type ServerState = (); + type ClientState = (); + type EntityState = (); + type WorldState = (); + type ChunkState = (); + type PlayerListState = (); + type InventoryState = (); +} + +#[test] +pub fn parse_world(){ + let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); + let world = AnvilWorld::new::( + world_directory, + BiomeKind::ALL + .iter() + .map(|b| (BiomeId::default(), b.biome().unwrap())), + ); + let mut load_targets = Vec::new(); + for x in -5..5 { + for z in -5..5 { + load_targets.push(ChunkPos::new(x, z)); + } + } + + let runtime = Builder::new_current_thread() + .enable_all() + .build() + .expect("Creating runtime failed"); + + for (chunk_pos, chunk) in runtime.block_on(world.load_chunks(load_targets.into_iter())).unwrap() { + assert!( + chunk.is_some(), + "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ + generated?" + ); + } +} \ No newline at end of file From 2b2224aa7d49e3e68bb0f7f3816c26398a4ee5b3 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 4 Dec 2022 19:30:45 +0100 Subject: [PATCH 57/75] Cargo fmt --- valence_anvil/benches/world_parsing.rs | 2 +- valence_anvil/tests/parse_world.rs | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index d019ad9f8..4029aebeb 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -9,7 +9,7 @@ use valence_anvil::AnvilWorld; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -#[path="../tests/assets.rs"] +#[path = "../tests/assets.rs"] pub mod assets; const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs index e2a1a20ce..91719cd1a 100644 --- a/valence_anvil/tests/parse_world.rs +++ b/valence_anvil/tests/parse_world.rs @@ -1,11 +1,11 @@ +use tokio::runtime::Builder; use valence::biome::BiomeId; use valence::chunk::ChunkPos; use valence::config::Config; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -use tokio::runtime::Builder; -#[path="../tests/assets.rs"] +#[path = "../tests/assets.rs"] pub mod assets; const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( @@ -26,7 +26,7 @@ impl Config for TestConfig { } #[test] -pub fn parse_world(){ +pub fn parse_world() { let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); let world = AnvilWorld::new::( world_directory, @@ -46,11 +46,13 @@ pub fn parse_world(){ .build() .expect("Creating runtime failed"); - for (chunk_pos, chunk) in runtime.block_on(world.load_chunks(load_targets.into_iter())).unwrap() { + for (chunk_pos, chunk) in runtime + .block_on(world.load_chunks(load_targets.into_iter())) + .unwrap() + { assert!( chunk.is_some(), - "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ - generated?" + "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world generated?" ); } -} \ No newline at end of file +} From 61cdafbc54084f6a3672367ef09ea101d387f3bc Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 11 Dec 2022 17:39:24 +0100 Subject: [PATCH 58/75] Reformat chunk parsing Revert 03e89adeb8fc286ef24b1e21f5c78908276fef18 --- valence_anvil/Cargo.toml | 1 + valence_anvil/examples/java_region.rs | 11 +- valence_anvil/src/chunk.rs | 266 ++++++++++++++++++++++++++ valence_anvil/src/error.rs | 20 +- valence_anvil/src/lib.rs | 20 +- valence_anvil/src/palette.rs | 178 ++++++++++++++++- valence_anvil/src/region.rs | 247 +----------------------- valence_nbt/src/value.rs | 120 ------------ 8 files changed, 489 insertions(+), 374 deletions(-) create mode 100644 valence_anvil/src/chunk.rs diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 87a64dd23..2d08703dc 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -19,6 +19,7 @@ byteorder = "1.4.3" tokio = { version = "1.21.2", features = ["fs", "io-util"] } futures = "0.3.24" thiserror = "1.0.37" +num-traits = "0.2.15" [dev-dependencies] tempfile = "3.3.0" diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 4f4cf155d..122a0dcfe 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -1,5 +1,4 @@ extern crate valence; - use std::net::SocketAddr; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -91,10 +90,12 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - server.worlds.insert( - DimensionId::default(), - AnvilWorld::new::(&self.world_dir, server.shared.biomes()), - ); + for (id, dimension) in server.shared.dimensions() { + server.worlds.insert( + id, + AnvilWorld::new::(&dimension, &self.world_dir, server.shared.biomes()), + ); + } server.state = Some(server.player_lists.insert(()).0); } diff --git a/valence_anvil/src/chunk.rs b/valence_anvil/src/chunk.rs new file mode 100644 index 000000000..71c6502fd --- /dev/null +++ b/valence_anvil/src/chunk.rs @@ -0,0 +1,266 @@ +use std::fmt; + +use num_traits::FromPrimitive; +use valence::nbt::{List, Value}; +use valence::prelude::*; + +use crate::error::{DataFormatError, Error, NbtFormatError}; +use crate::palette::{ + parse_identity_list_palette, parse_palette_identities_with_properties, DataFormat, +}; +use crate::AnvilWorld; + +#[derive(Debug, Copy, Clone)] +pub enum ChunkStatus { + Empty, + StructureStarts, + StructureReferences, + Biomes, + Noise, + Surface, + Carvers, + LiquidCarvers, + Features, + Light, + Spawn, + Heightmaps, + Full, +} + +impl ChunkStatus { + /// Retrieves the "Status" field from the NBT compound and parses it to + /// `Self` + /// + /// # Arguments + /// + /// * `nbt`: The chunk NBT compound + /// + /// returns: the status or `Self::Unknown` if no valid status was found. + pub fn from_nbt(nbt: &Compound) -> Result { + match nbt.get("Status") { + None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: None, + key: "Status".to_string(), + })), + Some(Value::String(x)) => match x.as_str() { + "full" => Ok(Self::Full), + "empty" => Ok(Self::Empty), + "structure_starts" => Ok(Self::StructureStarts), + "structure_references" => Ok(Self::StructureReferences), + "biomes" => Ok(Self::Biomes), + "noise" => Ok(Self::Noise), + "surface" => Ok(Self::Surface), + "carvers" => Ok(Self::Carvers), + "liquid_carvers" => Ok(Self::LiquidCarvers), + "features" => Ok(Self::Features), + "light" => Ok(Self::Light), + "spawn" => Ok(Self::Spawn), + "heightmaps" => Ok(Self::Heightmaps), + raw => Err(Error::DataFormatError(DataFormatError::InvalidChunkState( + raw.to_string(), + ))), + }, + Some(_) => Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: None, + key: "Status".to_string(), + })), + } + } + + pub fn is_fully_generated(&self) -> bool { + if let ChunkStatus::Full = self { + true + } else { + false + } + } + + pub fn raw_status(&self) -> &str { + match self { + Self::Full => "full", + Self::Empty => "empty", + Self::StructureStarts => "structure_starts", + Self::StructureReferences => "structure_references", + Self::Biomes => "biomes", + Self::Noise => "noise", + Self::Surface => "surface", + Self::Carvers => "carvers", + Self::LiquidCarvers => "liquid_carvers", + Self::Features => "features", + Self::Light => "light", + Self::Spawn => "spawn", + Self::Heightmaps => "heightmaps", + } + } +} + +impl fmt::Display for ChunkStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.raw_status()) + } +} + +pub fn parse_chunk_nbt(mut nbt: Compound, world: &AnvilWorld) -> Result { + let status: ChunkStatus = ChunkStatus::from_nbt(&nbt)?; + if !status.is_fully_generated() { + return Err(Error::DataFormatError( + DataFormatError::UnexpectedChunkState(status), + )); + } + + if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { + // Parsing sections + let mut chunk = UnloadedChunk::new(world.height); + for mut nbt_section in nbt_sections.into_iter() { + let chunk_y_offset: isize = if let Some(Value::Byte(y)) = nbt_section.get("Y") { + match isize::from_i8(*y) { + None => { + return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { + tag: Some(nbt_section), + key: "Y", + })); + } + Some(height) => height * 16, + } + } else { + return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { + tag: Some(nbt_section), + key: "Y", + })); + }; + + // Block states + match nbt_section.remove("block_states") { + Some(Value::Compound(tag)) => { + parse_palette_identities_with_properties::( + tag, + 4, + 16 * 16 * 16, + |identity: Ident| { + if let Some(block_kind) = BlockKind::from_str(identity.path()) { + Ok(BlockState::from_kind(block_kind)) + } else { + Err(Error::DataFormatError(DataFormatError::UnknownType( + identity, + ))) + } + }, + |state: BlockState, property: PropName, value: PropValue| { + Ok(state.set(property, value)) + }, + |data: DataFormat| match data { + DataFormat::All(state) => { + if !state.is_air() { + for x in 0..16 { + for y in 0..16isize { + for z in 0..16 { + chunk.set_block_state( + x, + (y + chunk_y_offset - world.min_y) as usize, + z, + state, + ); + } + } + } + } + Ok(()) + } + DataFormat::Palette(index, state) => { + let y = (index >> 8 & 0b1111) as isize; + let z = index >> 4 & 0b1111; + let x = index & 0b1111; + chunk.set_block_state( + x, + (y + chunk_y_offset - world.min_y) as usize, + z, + state, + ); + Ok(()) + } + }, + )?; + } + Some(value) => { + nbt_section.insert("block_states", value); + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(nbt_section), + key: "block_states".to_string(), + })); + } + None => { + return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { + key: "block_states", + tag: Some(nbt_section), + })); + } + } + + match nbt_section.remove("biomes") { + Some(Value::Compound(tag)) => { + parse_identity_list_palette::( + tag, + 0, + 4 * 4 * 4, + |biome_identity: Ident| { + if let Some(biome) = world.biomes.get(&biome_identity) { + Ok(*biome) + } else { + Err(Error::DataFormatError(DataFormatError::UnknownType( + biome_identity, + ))) + } + }, + |data: DataFormat| { + match data { + DataFormat::All(biome) => { + for x in 0..4 { + for y in 0..4isize { + for z in 0..4 { + chunk.set_biome( + x, + (y + (chunk_y_offset / 4) - (world.min_y / 4)) + as usize, + z, + biome, + ); + } + } + } + } + DataFormat::Palette(index, biome) => { + let y = (index >> 4 & 0b11) as isize; + let z = index >> 2 & 0b11; + let x = index & 0b11; + + let final_y = y + (chunk_y_offset / 4) - (world.min_y / 4); + chunk.set_biome(x, final_y as usize, z, biome); + } + } + Ok(()) + }, + )?; + } + Some(value) => { + nbt_section.insert("biomes", value); + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + key: "biomes".to_string(), + tag: Some(nbt_section), + })); + } + None => { + return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { + key: "biomes", + tag: Some(nbt_section), + })); + } + } + } + Ok(chunk) + } else { + return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { + key: "sections", + tag: Some(nbt), + })); + } +} diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs index 76bb2f9af..d9916b320 100644 --- a/valence_anvil/src/error.rs +++ b/valence_anvil/src/error.rs @@ -1,8 +1,11 @@ use std::io; use thiserror::Error; +use valence::prelude::Compound; use valence::protocol::ident::{Ident, IdentError}; +use crate::chunk::ChunkStatus; + #[derive(Error, Debug)] pub enum Error { #[error(transparent)] @@ -17,10 +20,10 @@ pub enum Error { #[derive(Error, Debug)] pub enum NbtFormatError { - #[error("Missing key: {0}")] - MissingKey(String), - #[error("Invalid type: {0}")] - InvalidType(String), + #[error("Missing key: {key}")] + MissingKey { key: String, tag: Option }, + #[error("Invalid type: {key}")] + InvalidType { key: String, tag: Option }, } #[derive(Error, Debug)] @@ -29,12 +32,21 @@ pub enum DataFormatError { UnknownCompressionScheme(u8), #[error("Invalid chunk size: {0}")] InvalidChunkSize(usize), + #[error("Missing chunk parameter: {key}")] + MissingChunkNBT { + key: &'static str, + tag: Option, + }, #[error(transparent)] IdentityError(#[from] IdentError), #[error("Unknown identity: {0}")] UnknownType(Ident), #[error("Invalid chunk state: {0}")] InvalidChunkState(String), + #[error("Unexpected chunk state: {0}")] + UnexpectedChunkState(ChunkStatus), + #[error("Property load error: {name} {value}")] + PropertyLoadError { name: String, value: String }, #[error("Invalid chunk palette")] InvalidPalette, } diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index da66bb642..d35ec0bf3 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -9,7 +9,9 @@ use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; +use valence::dimension::Dimension; use valence::protocol::Ident; +use valence::vek::num_traits::FromPrimitive; use crate::error::Error; @@ -17,12 +19,15 @@ pub mod biome; pub mod compression; pub mod error; +mod chunk; mod palette; mod region; #[derive(Debug)] pub struct AnvilWorld { world_root: PathBuf, + min_y: isize, + height: usize, biomes: BTreeMap, BiomeId>, region_files: Mutex>>>, } @@ -44,14 +49,17 @@ impl AnvilWorld { /// ```ignore /// impl Config for Game { /// fn init(&self, server: &mut Server) { - /// server.worlds.insert( - /// DimensionId::default(), - /// AnvilWorld::new::(&self.world_dir, server.shared.biomes()), - /// ); + /// for (id, dimension) in server.shared.dimensions() { + /// server.worlds.insert( + /// id, + /// AnvilWorld::new::(&dimension, &self.world_dir, server.shared.biomes()), + /// ); + /// } /// } /// } /// ``` pub fn new>( + dimension: &Dimension, directory: impl Into, server_biomes: impl Iterator, ) -> Self { @@ -61,6 +69,10 @@ impl AnvilWorld { } Self { world_root: directory.into(), + min_y: isize::from_i32(dimension.min_y) + .expect("Dimension min_y could not be converted to isize from i32."), + height: usize::from_i32(dimension.height) + .expect("Dimension height could not be converted to usize from i32."), biomes, region_files: Mutex::new(BTreeMap::new()), } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs index 490eb552d..e3716f321 100644 --- a/valence_anvil/src/palette.rs +++ b/valence_anvil/src/palette.rs @@ -1,18 +1,190 @@ use std::ops::BitXor; -use crate::error::{DataFormatError, Error}; +use valence::nbt::{Compound, List, Value}; +use valence::prelude::*; + +use crate::error::{DataFormatError, Error, NbtFormatError}; pub enum DataFormat { All(T), Palette(usize, T), } -pub fn parse_palette) -> Result<(), Error>)>( +pub fn parse_palette_identities_with_properties< + T: Copy, + FT: FnMut(Ident) -> Result, + FP: FnMut(T, PropName, PropValue) -> Result, + F: FnMut(DataFormat) -> Result<(), Error>, +>( + palette_container: Compound, + min_bits: usize, + expected_len: usize, + mut loader: FT, + mut applicator: FP, + handler: F, +) -> Result<(), Error> { + parse_compound_palette( + palette_container, + min_bits, + expected_len, + |mut nbt| match (nbt.remove("Name"), nbt.remove("Properties")) { + (Some(Value::String(identity)), None) => loader(Ident::new(identity.to_string())?), + (Some(Value::String(identity)), Some(Value::Compound(properties))) => { + let mut object = loader(Ident::new(identity.to_string())?)?; + for (property_name_raw, property_value) in &properties { + if let Value::String(property_value) = property_value { + match ( + PropName::from_str(property_name_raw), + PropValue::from_str(property_value), + ) { + (Some(name), Some(value)) => { + object = applicator(object, name, value)?; + } + _ => { + return Err(Error::DataFormatError( + DataFormatError::PropertyLoadError { + name: property_name_raw.to_string(), + value: property_value.to_string(), + }, + )) + } + } + } else { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(properties), + key: "Name".to_string(), + })); + } + } + Ok(object) + } + (Some(_), Some(Value::Compound(_))) => { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: None, + key: "Name".to_string(), + })) + } + (None, Some(Value::Compound(_))) => { + return Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: None, + key: "Name".to_string(), + })) + } + (_, Some(_)) => { + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: None, + key: "Properties".to_string(), + })) + } + (_, None) => { + return Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: None, + key: "Properties".to_string(), + })) + } + }, + handler, + ) +} + +pub fn parse_compound_palette< + T: Copy, + FT: FnMut(Compound) -> Result, + F: FnMut(DataFormat) -> Result<(), Error>, +>( + mut palette_container: Compound, + min_bits: usize, + expected_len: usize, + mut loader: FT, + handler: F, +) -> Result<(), Error> { + match palette_container.remove("palette") { + Some(Value::List(List::Compound(nbt_palette_vec))) => { + let iter = nbt_palette_vec.into_iter(); + let mut keys = Vec::::with_capacity(iter.len()); + for tag in iter { + keys.push(loader(tag)?) + } + match palette_container.remove("data") { + Some(Value::LongArray(data)) => { + decode_palette(&keys, Some(data), min_bits, expected_len, handler) + } + Some(data) => { + palette_container.insert("data", data); + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(palette_container), + key: "data".to_string(), + })); + } + None => decode_palette(&keys, None, min_bits, expected_len, handler), + } + } + Some(value) => { + palette_container.insert("palette", value); + Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(palette_container), + key: "palette".to_string(), + })) + } + None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: Some(palette_container), + key: "palette".to_string(), + })), + } +} + +pub fn parse_identity_list_palette< + T: Copy, + FT: FnMut(Ident) -> Result, + F: FnMut(DataFormat) -> Result<(), Error>, +>( + mut palette_container: Compound, + min_bits: usize, + expected_len: usize, + mut loader: FT, + handler: F, +) -> Result<(), Error> { + match palette_container.remove("palette") { + Some(Value::List(List::String(nbt_palette_vec))) => { + let iter = nbt_palette_vec.into_iter(); + let mut keys = Vec::::with_capacity(iter.len()); + for tag in iter { + keys.push(loader(Ident::new(tag)?)?) + } + match palette_container.remove("data") { + Some(Value::LongArray(data)) => { + decode_palette(&keys, Some(data), min_bits, expected_len, handler) + } + Some(data) => { + palette_container.insert("data", data); + return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(palette_container), + key: "data".to_string(), + })); + } + None => decode_palette(&keys, None, min_bits, expected_len, handler), + } + } + Some(value) => { + palette_container.insert("palette", value); + Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: Some(palette_container), + key: "palette".to_string(), + })) + } + None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: Some(palette_container), + key: "palette".to_string(), + })), + } +} + +pub fn decode_palette) -> Result<(), Error>)>( source: &Vec, data: Option>, min_bits: usize, expected_len: usize, - fun: &mut F, + mut fun: F, ) -> Result<(), Error> { let palette_len = source.len(); if palette_len == 0 { diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index 22e9de154..abc8ce1e9 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -6,16 +6,12 @@ use byteorder::{BigEndian, ByteOrder}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; use tokio::sync::Mutex; -use valence::biome::BiomeId; -use valence::chunk::{Chunk, ChunkPos, UnloadedChunk}; -use valence::nbt::{Compound, List, Value}; -use valence::protocol::block::{BlockKind, BlockState, PropName, PropValue}; -use valence::protocol::Ident; +use valence::chunk::{ChunkPos, UnloadedChunk}; +use crate::chunk::parse_chunk_nbt; use crate::compression::CompressionScheme; -use crate::error::{DataFormatError, Error, NbtFormatError}; -use crate::palette::DataFormat; -use crate::{palette, AnvilWorld}; +use crate::error::{DataFormatError, Error}; +use crate::AnvilWorld; #[derive(Debug)] pub struct Region { @@ -111,9 +107,11 @@ impl Region { let chunk_data = self.read_chunk_bytes(pos).await?; if let Some(chunk_data) = chunk_data { - let mut nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - match Self::parse_chunk_nbt(&mut nbt, world) { - Err(Error::DataFormatError(DataFormatError::InvalidChunkState(..))) => { + let nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; + match parse_chunk_nbt(nbt, world) { + Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { .. })) + | Err(Error::DataFormatError(DataFormatError::UnexpectedChunkState(..))) => { + // The chunk is missing vital data and cannot be parsed. results.push((pos, None)); } Err(e) => return Err(e), @@ -128,233 +126,6 @@ impl Region { Ok(results.into_iter()) } - - //TODO: This function is very large and should be separated into dedicated - // functions at some point. - fn parse_chunk_nbt(nbt: &mut Compound, world: &AnvilWorld) -> Result { - fn take_assume(compound: &mut Compound, key: &'static str) -> Result - where - Option: From, - { - match compound.remove(key) { - None => Err(Error::NbtFormatError(NbtFormatError::MissingKey( - key.to_string(), - ))), - Some(value) => { - if let Some(value) = Option::::from(value) { - Ok(value) - } else { - Err(Error::NbtFormatError(NbtFormatError::InvalidType( - key.to_string(), - ))) - } - } - } - } - - fn take_assume_optional(compound: &mut Compound, key: &'static str) -> Option - where - Option: From, - { - match compound.remove(key) { - None => None, - Some(value) => Option::::from(value), - } - } - - let status: String = take_assume(nbt, "Status")?; - if status.as_str() != "full" { - return Err(Error::DataFormatError(DataFormatError::InvalidChunkState( - status, - ))); - } - - if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { - let mut y_max = 0i8; - let mut y_min = 0i8; - - for chunk_nbt in nbt_sections.iter() { - if let Some(Value::Byte(section_y)) = chunk_nbt.get("Y") { - y_max = y_max.max(*section_y); - y_min = y_min.min(*section_y); - } else { - return Err(Error::NbtFormatError(NbtFormatError::MissingKey( - "Y".to_string(), - ))); - } - } - - // `y_max` should always be equal or higher than `y_min`. Therefore, - // section_height is positive. - let section_height = ((y_max as isize - y_min as isize) as usize * 16) + 16; - let y_raise = isize::from(-y_min) * 16; - - // Parsing sections - let mut chunk = UnloadedChunk::new(section_height); - for mut nbt_section in nbt_sections.into_iter() { - let chunk_y_offset: isize = - isize::from(take_assume::(&mut nbt_section, "Y")?) * 16; - - // Block states - let mut nbt_block_states: Compound = take_assume(&mut nbt_section, "block_states")?; - let parsed_block_state_palette: Vec = - if let Some(Value::List(List::Compound(nbt_palette_vec))) = - nbt_block_states.remove("palette") - { - let mut palette_vec: Vec = - Vec::with_capacity(nbt_palette_vec.len()); - for mut nbt_palette in nbt_palette_vec { - let block_id = - Ident::new(take_assume::(&mut nbt_palette, "Name")?)?; - let block_kind = - if let Some(block_kind) = BlockKind::from_str(block_id.path()) { - block_kind - } else { - return Err(Error::DataFormatError( - DataFormatError::UnknownType(block_id), - )); - }; - let mut block_state = BlockState::from_kind(block_kind); - if let Some(Value::Compound(nbt_palette_properties)) = - nbt_palette.remove("Properties") - { - for (property_name_raw, property_value) in nbt_palette_properties { - if let Value::String(property_value) = property_value { - let property_name = PropName::from_str(&property_name_raw); - let property_value = PropValue::from_str(&property_value); - if let (Some(property_name), Some(property_value)) = - (property_name, property_value) - { - block_state = - block_state.set(property_name, property_value); - } else { - return Err(Error::NbtFormatError( - NbtFormatError::MissingKey(property_name_raw), - )); - } - } else { - return Err(Error::NbtFormatError( - NbtFormatError::InvalidType(property_name_raw), - )); - } - } - } - palette_vec.push(block_state); - } - palette_vec - } else { - return Err(Error::NbtFormatError(NbtFormatError::InvalidType( - "palette".to_string(), - ))); - }; - - // Block state palette - palette::parse_palette::( - &parsed_block_state_palette, - take_assume_optional(&mut nbt_block_states, "data"), - 4, - 16 * 16 * 16, - &mut |data| { - match data { - DataFormat::All(state) => { - if !state.is_air() { - for x in 0..16 { - for y in 0..16isize { - for z in 0..16 { - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - } - } - } - DataFormat::Palette(index, state) => { - let y = (index >> 8 & 0b1111) as isize; - let z = index >> 4 & 0b1111; - let x = index & 0b1111; - - chunk.set_block_state( - x, - (y + chunk_y_offset + y_raise) as usize, - z, - state, - ); - } - } - Ok(()) - }, - )?; - - // Biome palette - let mut nbt_biomes: Compound = take_assume(&mut nbt_section, "biomes")?; - let parsed_biome_palette: Vec = - if let Some(Value::List(List::String(biome_names))) = - nbt_biomes.remove("palette") - { - let mut biomes: Vec = Vec::with_capacity(biome_names.len()); - for biome in biome_names { - let biome_identity = Ident::new(biome)?; - if let Some(biome) = world.biomes.get(&biome_identity) { - biomes.push(*biome); - } else { - return Err(Error::DataFormatError(DataFormatError::UnknownType( - biome_identity, - ))); - } - } - biomes - } else { - return Err(Error::NbtFormatError(NbtFormatError::InvalidType( - "palette".to_string(), - ))); - }; - - palette::parse_palette::( - &parsed_biome_palette, - take_assume_optional(&mut nbt_biomes, "data"), - 0, - 4 * 4 * 4, - &mut |data| { - match data { - DataFormat::All(biome) => { - for x in 0..4 { - for y in 0..4isize { - for z in 0..4 { - chunk.set_biome( - x, - (y + (chunk_y_offset / 4) + (y_raise / 4)) as usize, - z, - biome, - ); - } - } - } - } - DataFormat::Palette(index, biome) => { - let y = (index >> 4 & 0b11) as isize; - let z = index >> 2 & 0b11; - let x = index & 0b11; - - let final_y = y + (chunk_y_offset / 4) + (y_raise / 4); - chunk.set_biome(x, final_y as usize, z, biome); - } - } - Ok(()) - }, - )?; - } - - Ok(chunk) - } else { - Err(Error::NbtFormatError(NbtFormatError::InvalidType( - "sections".to_string(), - ))) - } - } } #[derive(Copy, Clone, Debug)] diff --git a/valence_nbt/src/value.rs b/valence_nbt/src/value.rs index e6be1b68f..f70348265 100644 --- a/valence_nbt/src/value.rs +++ b/valence_nbt/src/value.rs @@ -234,123 +234,3 @@ impl From>> for List { List::LongArray(v) } } - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Byte(b) = value { - Some(b) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Short(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Int(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Long(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Float(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Double(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option> { - fn from(value: Value) -> Self { - if let Value::ByteArray(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::String(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::List(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option { - fn from(value: Value) -> Self { - if let Value::Compound(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option> { - fn from(value: Value) -> Self { - if let Value::IntArray(val) = value { - Some(val) - } else { - None - } - } -} - -impl From for Option> { - fn from(value: Value) -> Self { - if let Value::LongArray(val) = value { - Some(val) - } else { - None - } - } -} From cfe95b9c3587a58d1795adca9e01d2a01c5b56b4 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 11 Dec 2022 18:00:40 +0100 Subject: [PATCH 59/75] Code cleanup: Clippy lints --- valence_anvil/src/chunk.rs | 10 +++------- valence_anvil/src/palette.rs | 36 ++++++++++++++++-------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/valence_anvil/src/chunk.rs b/valence_anvil/src/chunk.rs index 71c6502fd..802608edf 100644 --- a/valence_anvil/src/chunk.rs +++ b/valence_anvil/src/chunk.rs @@ -68,11 +68,7 @@ impl ChunkStatus { } pub fn is_fully_generated(&self) -> bool { - if let ChunkStatus::Full = self { - true - } else { - false - } + matches!(self, ChunkStatus::Full) } pub fn raw_status(&self) -> &str { @@ -258,9 +254,9 @@ pub fn parse_chunk_nbt(mut nbt: Compound, world: &AnvilWorld) -> Result loader(Ident::new(identity.to_string())?), + (Some(Value::String(identity)), None) => loader(Ident::new(identity)?), (Some(Value::String(identity)), Some(Value::Compound(properties))) => { - let mut object = loader(Ident::new(identity.to_string())?)?; + let mut object = loader(Ident::new(identity)?)?; for (property_name_raw, property_value) in &properties { if let Value::String(property_value) = property_value { match ( @@ -59,29 +59,25 @@ pub fn parse_palette_identities_with_properties< Ok(object) } (Some(_), Some(Value::Compound(_))) => { - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + Err(Error::NbtFormatError(NbtFormatError::InvalidType { tag: None, key: "Name".to_string(), })) } (None, Some(Value::Compound(_))) => { - return Err(Error::NbtFormatError(NbtFormatError::MissingKey { + Err(Error::NbtFormatError(NbtFormatError::MissingKey { tag: None, key: "Name".to_string(), })) } - (_, Some(_)) => { - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: None, - key: "Properties".to_string(), - })) - } - (_, None) => { - return Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: None, - key: "Properties".to_string(), - })) - } + (_, Some(_)) => Err(Error::NbtFormatError(NbtFormatError::InvalidType { + tag: None, + key: "Properties".to_string(), + })), + (_, None) => Err(Error::NbtFormatError(NbtFormatError::MissingKey { + tag: None, + key: "Properties".to_string(), + })), }, handler, ) @@ -111,10 +107,10 @@ pub fn parse_compound_palette< } Some(data) => { palette_container.insert("data", data); - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + Err(Error::NbtFormatError(NbtFormatError::InvalidType { tag: Some(palette_container), key: "data".to_string(), - })); + })) } None => decode_palette(&keys, None, min_bits, expected_len, handler), } @@ -157,10 +153,10 @@ pub fn parse_identity_list_palette< } Some(data) => { palette_container.insert("data", data); - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { + Err(Error::NbtFormatError(NbtFormatError::InvalidType { tag: Some(palette_container), key: "data".to_string(), - })); + })) } None => decode_palette(&keys, None, min_bits, expected_len, handler), } From f54e951924ecd4d44b81b5c5c5b89bc0ae7b7eaa Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 11 Dec 2022 19:37:02 +0100 Subject: [PATCH 60/75] Rustup update + Clippy --- valence_anvil/benches/world_parsing.rs | 2 ++ valence_anvil/build/biome.rs | 6 +++--- valence_anvil/examples/java_region.rs | 2 +- valence_anvil/tests/parse_world.rs | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 4029aebeb..b8effba79 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -5,6 +5,7 @@ use valence::chunk::ChunkPos; use valence::config::Config; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; +use valence::dimension::Dimension; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); @@ -33,6 +34,7 @@ fn criterion_benchmark(c: &mut Criterion) { let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); let world = AnvilWorld::new::( + &Dimension::default(), world_directory, BiomeKind::ALL .iter() diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 993494f81..4510d0cdd 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -66,7 +66,7 @@ pub fn build() -> anyhow::Result { .into_iter() .map(|biome| RenamedBiome { id: biome.id, - rustified_name: ident(&biome.name.replace("minecraft:", "").to_pascal_case()), + rustified_name: ident(biome.name.replace("minecraft:", "").to_pascal_case()), name: biome.name, climate: biome.climate, color: biome.color, @@ -171,14 +171,14 @@ pub fn build() -> anyhow::Result { .map(|biome| { let rustified_name = &biome.rustified_name; let name = &biome.name; - let precipitation = ident(&biome.climate.precipitation.to_pascal_case()); + let precipitation = ident(biome.climate.precipitation.to_pascal_case()); let sky_color = &biome.color.sky; let water_fog = &biome.color.water_fog; let fog = &biome.color.fog; let water_color = &biome.color.water; let foliage_color = option_to_quote(&biome.color.foliage); let grass_color = option_to_quote(&biome.color.grass); - let grass_modifier = ident(&biome.color.grass_modifier.to_pascal_case()); + let grass_modifier = ident(biome.color.grass_modifier.to_pascal_case()); quote! { Self::#rustified_name => Ok(Biome{ name: Ident::from_str(#name)?, diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 122a0dcfe..ecfbe0bd2 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -93,7 +93,7 @@ impl Config for Game { for (id, dimension) in server.shared.dimensions() { server.worlds.insert( id, - AnvilWorld::new::(&dimension, &self.world_dir, server.shared.biomes()), + AnvilWorld::new::(dimension, &self.world_dir, server.shared.biomes()), ); } server.state = Some(server.player_lists.insert(()).0); diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs index 91719cd1a..55e89f6a2 100644 --- a/valence_anvil/tests/parse_world.rs +++ b/valence_anvil/tests/parse_world.rs @@ -4,6 +4,7 @@ use valence::chunk::ChunkPos; use valence::config::Config; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; +use valence::prelude::Dimension; #[path = "../tests/assets.rs"] pub mod assets; @@ -29,6 +30,7 @@ impl Config for TestConfig { pub fn parse_world() { let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); let world = AnvilWorld::new::( + &Dimension::default(), world_directory, BiomeKind::ALL .iter() From 5ce1a13dcef7bfe27aa59da3830ac2cba363c841 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 11 Dec 2022 20:01:29 +0100 Subject: [PATCH 61/75] Update to new valence API --- valence_anvil/examples/java_region.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index ecfbe0bd2..75cc0553f 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -100,9 +100,9 @@ impl Config for Game { } fn update(&self, server: &mut Server) { - let (world_id, world) = server.worlds.iter_mut().next().unwrap(); + let (world_id, world): (WorldId, &mut World<_>) = server.worlds.iter_mut().next().unwrap(); - server.clients.retain(|_, client| { + server.clients.retain(|_, client: &mut Client<_>| { if client.created_this_tick() { if self .player_count @@ -156,7 +156,7 @@ impl Config for Game { if let Some(id) = &server.state { server.player_lists.get_mut(id).remove(client.uuid()); } - server.entities.remove(client.state.id); + server.entities.delete(client.id); return false; } @@ -170,9 +170,8 @@ impl Config for Game { let dist = client.view_distance(); let p = client.position(); - let required_chunks = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); let mut new_chunks = Vec::new(); - for pos in required_chunks { + for pos in ChunkPos::at(p.x, p.z).in_view(dist) { if let Some(existing) = world.chunks.get_mut(pos) { existing.state = true; } else { @@ -195,14 +194,10 @@ impl Config for Game { true }); - // Remove chunks outside the view distance of players. - world.chunks.retain(|_, chunk| { - if chunk.state { - chunk.state = false; - true - } else { - false + for (_, chunk) in world.chunks.iter_mut(){ + if !chunk.state { + chunk.set_deleted(true) } - }); + } } } From 2a93ef753f864641b5d629ed9a23a80c0530720a Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 11 Dec 2022 20:04:06 +0100 Subject: [PATCH 62/75] Cargo fmt --- valence_anvil/benches/world_parsing.rs | 2 +- valence_anvil/examples/java_region.rs | 2 +- valence_anvil/tests/parse_world.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index b8effba79..91b50d1a7 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -3,9 +3,9 @@ use tokio::runtime::Builder; use valence::biome::BiomeId; use valence::chunk::ChunkPos; use valence::config::Config; +use valence::dimension::Dimension; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -use valence::dimension::Dimension; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 75cc0553f..181b2097a 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -194,7 +194,7 @@ impl Config for Game { true }); - for (_, chunk) in world.chunks.iter_mut(){ + for (_, chunk) in world.chunks.iter_mut() { if !chunk.state { chunk.set_deleted(true) } diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs index 55e89f6a2..c081cb8cb 100644 --- a/valence_anvil/tests/parse_world.rs +++ b/valence_anvil/tests/parse_world.rs @@ -2,9 +2,9 @@ use tokio::runtime::Builder; use valence::biome::BiomeId; use valence::chunk::ChunkPos; use valence::config::Config; +use valence::prelude::Dimension; use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -use valence::prelude::Dimension; #[path = "../tests/assets.rs"] pub mod assets; From f4faccfe597353decaab17dd5dec83218a704eef Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Thu, 15 Dec 2022 20:26:56 +0100 Subject: [PATCH 63/75] Reformat Biome parsing to match https://github.com/valence-rs/valence/blob/main/src/biome.rs#L59-L123 --- extracted/biomes.json | 12503 ++++++++-------- .../main/java/rs/valence/extractor/Main.java | 1 + .../valence/extractor/extractors/Biomes.java | 92 +- valence_anvil/build/biome.rs | 207 +- valence_anvil/build/main.rs | 8 +- 5 files changed, 6633 insertions(+), 6178 deletions(-) diff --git a/extracted/biomes.json b/extracted/biomes.json index e0571e5d8..2612854b1 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -2,6535 +2,6976 @@ { "name": "the_void", "id": 0, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "plains", "id": 1, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7907327, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "horse", - "min_group_size": 2, - "max_group_size": 6, - "weight": 5 - }, - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 3, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 7907327, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "sunflower_plains", "id": 2, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7907327, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "horse", - "min_group_size": 2, - "max_group_size": 6, - "weight": 5 - }, - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 3, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 7907327, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 5 + }, + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 3, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "snowy_plains", "id": 3, - "climate": { + "element": { "precipitation": "snow", "temperature": 0.0, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8364543, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.07, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 20 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "stray", - "min_group_size": 4, - "max_group_size": 4, - "weight": 80 - } - ], - "creature": [ - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 10 - }, - { - "name": "polar_bear", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8364543, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.07, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "ice_spikes", "id": 4, - "climate": { + "element": { "precipitation": "snow", "temperature": 0.0, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8364543, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.07, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 20 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "stray", - "min_group_size": 4, - "max_group_size": 4, - "weight": 80 - } - ], - "creature": [ - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 10 - }, - { - "name": "polar_bear", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8364543, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.07, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 20 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "stray", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 10 + }, + { + "name": "polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "desert", "id": 5, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 19 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "husk", - "min_group_size": 4, - "max_group_size": 4, - "weight": 80 - } - ], - "creature": [ - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 19 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "husk", + "min_group_size": 4, + "max_group_size": 4, + "weight": 80 + } + ], + "creature": [ + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "swamp", "id": 6, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "swamp", - "foliage": 6975545, - "fog": 12638463, - "sky": 7907327, - "water_fog": 2302743, - "water": 6388580 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "slime", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "frog", - "min_group_size": 2, - "max_group_size": 5, - "weight": 10 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 7907327, + "water_fog_color": 2302743, + "fog_color": 12638463, + "water_color": 6388580, + "foliage_color": 6975545, + "grass_color_modifier": "swamp", + "music": { + "replace_current_music": false, + "sound": "music.overworld.swamp", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "mangrove_swamp", "id": 7, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "swamp", - "foliage": 9285927, - "fog": 12638463, - "sky": 7907327, - "water_fog": 5077600, - "water": 3832426 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "slime", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - } - ], - "creature": [ - { - "name": "frog", - "min_group_size": 2, - "max_group_size": 5, - "weight": 10 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [ - { - "name": "tropical_fish", - "min_group_size": 8, - "max_group_size": 8, - "weight": 25 - } - ], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 7907327, + "water_fog_color": 5077600, + "fog_color": 12638463, + "water_color": 3832426, + "foliage_color": 9285927, + "grass_color_modifier": "swamp", + "music": { + "replace_current_music": false, + "sound": "music.overworld.swamp", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "slime", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [ + { + "name": "frog", + "min_group_size": 2, + "max_group_size": 5, + "weight": 10 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } } }, { "name": "forest", "id": 8, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.7, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7972607, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 7972607, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "flower_forest", "id": 9, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.7, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7972607, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 7972607, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "birch_forest", "id": 10, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.6, - "downfall": 0.6 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8037887, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.6, + "effects": { + "sky_color": 8037887, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "dark_forest", "id": 11, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.7, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "dark_forest", - "foliage": null, - "fog": 12638463, - "sky": 7972607, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 7972607, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "dark_forest", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "old_growth_birch_forest", "id": 12, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.6, - "downfall": 0.6 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8037887, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.6, + "effects": { + "sky_color": 8037887, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "old_growth_pine_taiga", "id": 13, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.3, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8168447, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 25 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "fox", - "min_group_size": 2, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 8168447, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.old_growth_taiga", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 25 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "old_growth_spruce_taiga", "id": 14, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.25, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233983, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "fox", - "min_group_size": 2, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 8233983, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.old_growth_taiga", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "taiga", "id": 15, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.25, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233983, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "fox", - "min_group_size": 2, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 8233983, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "snowy_taiga", "id": 16, - "climate": { + "element": { "precipitation": "snow", "temperature": -0.5, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8625919, - "water_fog": 329011, - "water": 4020182 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "fox", - "min_group_size": 2, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 8625919, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4020182, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "savanna", "id": 17, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "horse", - "min_group_size": 2, - "max_group_size": 6, - "weight": 1 - }, - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "savanna_plateau", "id": 18, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "horse", - "min_group_size": 2, - "max_group_size": 6, - "weight": 1 - }, - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - }, - { - "name": "llama", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + }, + { + "name": "llama", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "windswept_hills", "id": 19, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.2, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233727, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "llama", - "min_group_size": 4, - "max_group_size": 6, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 8233727, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "windswept_gravelly_hills", "id": 20, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.2, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233727, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "llama", - "min_group_size": 4, - "max_group_size": 6, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 8233727, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "windswept_forest", "id": 21, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.2, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233727, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "llama", - "min_group_size": 4, - "max_group_size": 6, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 8233727, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "llama", + "min_group_size": 4, + "max_group_size": 6, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "windswept_savanna", "id": 22, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "horse", - "min_group_size": 2, - "max_group_size": 6, - "weight": 1 - }, - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "horse", + "min_group_size": 2, + "max_group_size": 6, + "weight": 1 + }, + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "jungle", "id": 23, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.95, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7842047, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "ocelot", - "min_group_size": 1, - "max_group_size": 3, - "weight": 2 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "parrot", - "min_group_size": 1, - "max_group_size": 2, - "weight": 40 - }, - { - "name": "panda", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 7842047, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "ocelot", + "min_group_size": 1, + "max_group_size": 3, + "weight": 2 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "sparse_jungle", "id": 24, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.95, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7842047, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 7842047, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "bamboo_jungle", "id": 25, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.95, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7842047, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "ocelot", - "min_group_size": 1, - "max_group_size": 1, - "weight": 2 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "parrot", - "min_group_size": 1, - "max_group_size": 2, - "weight": 40 - }, - { - "name": "panda", - "min_group_size": 1, - "max_group_size": 2, - "weight": 80 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 7842047, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jungle_and_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "ocelot", + "min_group_size": 1, + "max_group_size": 1, + "weight": 2 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "parrot", + "min_group_size": 1, + "max_group_size": 2, + "weight": 40 + }, + { + "name": "panda", + "min_group_size": 1, + "max_group_size": 2, + "weight": 80 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "badlands", "id": 26, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": 9470285, - "grass_modifier": "none", - "foliage": 10387789, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "foliage_color": 10387789, + "grass_color": 9470285, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "eroded_badlands", "id": 27, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": 9470285, - "grass_modifier": "none", - "foliage": 10387789, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "foliage_color": 10387789, + "grass_color": 9470285, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "wooded_badlands", "id": 28, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": 9470285, - "grass_modifier": "none", - "foliage": 10387789, - "fog": 12638463, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "foliage_color": 10387789, + "grass_color": 9470285, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "meadow", "id": 29, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 937679 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "donkey", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 6, - "weight": 2 - }, - { - "name": "sheep", - "min_group_size": 2, - "max_group_size": 4, - "weight": 2 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 937679, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.meadow", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "donkey", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 6, + "weight": 2 + }, + { + "name": "sheep", + "min_group_size": 2, + "max_group_size": 4, + "weight": 2 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "grove", "id": 30, - "climate": { + "element": { "precipitation": "snow", "temperature": -0.2, - "downfall": 0.8 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8495359, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "sheep", - "min_group_size": 4, - "max_group_size": 4, - "weight": 12 - }, - { - "name": "pig", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "chicken", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "cow", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "wolf", - "min_group_size": 4, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "fox", - "min_group_size": 2, - "max_group_size": 4, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.8, + "effects": { + "sky_color": 8495359, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.grove", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "sheep", + "min_group_size": 4, + "max_group_size": 4, + "weight": 12 + }, + { + "name": "pig", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "chicken", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "cow", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "wolf", + "min_group_size": 4, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "fox", + "min_group_size": 2, + "max_group_size": 4, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "snowy_slopes", "id": 31, - "climate": { + "element": { "precipitation": "snow", "temperature": -0.3, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8560639, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "rabbit", - "min_group_size": 2, - "max_group_size": 3, - "weight": 4 - }, - { - "name": "goat", - "min_group_size": 1, - "max_group_size": 3, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 8560639, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.snowy_slopes", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "rabbit", + "min_group_size": 2, + "max_group_size": 3, + "weight": 4 + }, + { + "name": "goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "frozen_peaks", "id": 32, - "climate": { + "element": { "precipitation": "snow", "temperature": -0.7, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8756735, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "goat", - "min_group_size": 1, - "max_group_size": 3, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 8756735, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.frozen_peaks", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "jagged_peaks", "id": 33, - "climate": { + "element": { "precipitation": "snow", "temperature": -0.7, - "downfall": 0.9 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8756735, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "goat", - "min_group_size": 1, - "max_group_size": 3, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.9, + "effects": { + "sky_color": 8756735, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.jagged_peaks", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "goat", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "stony_peaks", "id": 34, - "climate": { + "element": { "precipitation": "rain", "temperature": 1.0, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7776511, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 7776511, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.stony_peaks", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "river", "id": 35, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 100 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 2 - } - ], - "water_ambient": [ - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 5 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 100 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } } }, { "name": "frozen_river", "id": 36, - "climate": { + "element": { "precipitation": "snow", "temperature": 0.0, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8364543, - "water_fog": 329011, - "water": 3750089 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 1 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 2 - } - ], - "water_ambient": [ - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 5 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8364543, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 3750089, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 1 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 5 + } + ], + "misc": [] + } } } }, { "name": "beach", "id": 37, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7907327, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "turtle", - "min_group_size": 2, - "max_group_size": 5, - "weight": 5 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 7907327, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "turtle", + "min_group_size": 2, + "max_group_size": 5, + "weight": 5 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "snowy_beach", "id": 38, - "climate": { + "element": { "precipitation": "snow", "temperature": 0.05, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8364543, - "water_fog": 329011, - "water": 4020182 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 8364543, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4020182, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "stony_shore", "id": 39, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.2, - "downfall": 0.3 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8233727, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.3, + "effects": { + "sky_color": 8233727, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "warm_ocean", "id": 40, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 270131, - "water": 4445678 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "dolphin", - "min_group_size": 1, - "max_group_size": 2, - "weight": 2 - } - ], - "water_ambient": [ - { - "name": "pufferfish", - "min_group_size": 1, - "max_group_size": 3, - "weight": 15 - }, - { - "name": "tropical_fish", - "min_group_size": 8, - "max_group_size": 8, - "weight": 25 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 270131, + "fog_color": 12638463, + "water_color": 4445678, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 15 + }, + { + "name": "tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } } }, { "name": "lukewarm_ocean", "id": 41, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 267827, - "water": 4566514 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 2, - "weight": 10 - }, - { - "name": "dolphin", - "min_group_size": 1, - "max_group_size": 2, - "weight": 2 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 15 - }, - { - "name": "pufferfish", - "min_group_size": 1, - "max_group_size": 3, - "weight": 5 - }, - { - "name": "tropical_fish", - "min_group_size": 8, - "max_group_size": 8, - "weight": 25 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 267827, + "fog_color": 12638463, + "water_color": 4566514, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 2, + "weight": 10 + }, + { + "name": "dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } } }, { "name": "deep_lukewarm_ocean", "id": 42, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 267827, - "water": 4566514 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 8 - }, - { - "name": "dolphin", - "min_group_size": 1, - "max_group_size": 2, - "weight": 2 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 8 - }, - { - "name": "pufferfish", - "min_group_size": 1, - "max_group_size": 3, - "weight": 5 - }, - { - "name": "tropical_fish", - "min_group_size": 8, - "max_group_size": 8, - "weight": 25 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 267827, + "fog_color": 12638463, + "water_color": 4566514, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 8 + }, + { + "name": "dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 2 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 8 + }, + { + "name": "pufferfish", + "min_group_size": 1, + "max_group_size": 3, + "weight": 5 + }, + { + "name": "tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } } }, { "name": "ocean", "id": 43, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 1 - }, - { - "name": "dolphin", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 10 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } } }, { "name": "deep_ocean", "id": 44, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 1 - }, - { - "name": "dolphin", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 10 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "dolphin", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 10 + } + ], + "misc": [] + } } } }, { "name": "cold_ocean", "id": 45, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4020182 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 3 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 15 - }, - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 15 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4020182, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } } }, { "name": "deep_cold_ocean", "id": 46, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4020182 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 3 - } - ], - "water_ambient": [ - { - "name": "cod", - "min_group_size": 3, - "max_group_size": 6, - "weight": 15 - }, - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 15 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4020182, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 3 + } + ], + "water_ambient": [ + { + "name": "cod", + "min_group_size": 3, + "max_group_size": 6, + "weight": 15 + }, + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } } }, { "name": "frozen_ocean", "id": 47, - "climate": { + "element": { "precipitation": "snow", "temperature": 0.0, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8364543, - "water_fog": 329011, - "water": 3750089 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "polar_bear", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 1 - } - ], - "water_ambient": [ - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 15 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8364543, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 3750089, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } } }, { "name": "deep_frozen_ocean", "id": 48, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 3750089 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [ - { - "name": "polar_bear", - "min_group_size": 1, - "max_group_size": 2, - "weight": 1 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [ - { - "name": "squid", - "min_group_size": 1, - "max_group_size": 4, - "weight": 1 - } - ], - "water_ambient": [ - { - "name": "salmon", - "min_group_size": 1, - "max_group_size": 5, - "weight": 15 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 3750089, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [ + { + "name": "polar_bear", + "min_group_size": 1, + "max_group_size": 2, + "weight": 1 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [ + { + "name": "squid", + "min_group_size": 1, + "max_group_size": 4, + "weight": 1 + } + ], + "water_ambient": [ + { + "name": "salmon", + "min_group_size": 1, + "max_group_size": 5, + "weight": 15 + } + ], + "misc": [] + } } } }, { "name": "mushroom_fields", "id": 49, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.9, - "downfall": 1.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7842047, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [], - "creature": [ - { - "name": "mooshroom", - "min_group_size": 4, - "max_group_size": 8, - "weight": 8 - } - ], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 1.0, + "effects": { + "sky_color": 7842047, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [], + "creature": [ + { + "name": "mooshroom", + "min_group_size": 4, + "max_group_size": 8, + "weight": 8 + } + ], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "dripstone_caves", "id": 50, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7907327, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "drowned", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 7907327, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.dripstone_caves", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "drowned", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "lush_caves", "id": 51, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 8103167, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "spider", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "zombie", - "min_group_size": 4, - "max_group_size": 4, - "weight": 95 - }, - { - "name": "zombie_villager", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - }, - { - "name": "skeleton", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "creeper", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "slime", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "enderman", - "min_group_size": 1, - "max_group_size": 4, - "weight": 10 - }, - { - "name": "witch", - "min_group_size": 1, - "max_group_size": 1, - "weight": 5 - } - ], - "creature": [], - "ambient": [ - { - "name": "bat", - "min_group_size": 8, - "max_group_size": 8, - "weight": 10 - } - ], - "axolotls": [ - { - "name": "axolotl", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "underground_water_creature": [ - { - "name": "glow_squid", - "min_group_size": 4, - "max_group_size": 6, - "weight": 10 - } - ], - "water_creature": [], - "water_ambient": [ - { - "name": "tropical_fish", - "min_group_size": 8, - "max_group_size": 8, - "weight": 25 - } - ], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 8103167, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.lush_caves", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "spider", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "zombie", + "min_group_size": 4, + "max_group_size": 4, + "weight": 95 + }, + { + "name": "zombie_villager", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + }, + { + "name": "skeleton", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "creeper", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "slime", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "enderman", + "min_group_size": 1, + "max_group_size": 4, + "weight": 10 + }, + { + "name": "witch", + "min_group_size": 1, + "max_group_size": 1, + "weight": 5 + } + ], + "creature": [], + "ambient": [ + { + "name": "bat", + "min_group_size": 8, + "max_group_size": 8, + "weight": 10 + } + ], + "axolotls": [ + { + "name": "axolotl", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "underground_water_creature": [ + { + "name": "glow_squid", + "min_group_size": 4, + "max_group_size": 6, + "weight": 10 + } + ], + "water_creature": [], + "water_ambient": [ + { + "name": "tropical_fish", + "min_group_size": 8, + "max_group_size": 8, + "weight": 25 + } + ], + "misc": [] + } } } }, { "name": "deep_dark", "id": 52, - "climate": { + "element": { "precipitation": "rain", "temperature": 0.8, - "downfall": 0.4 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 12638463, - "sky": 7907327, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.4, + "effects": { + "sky_color": 7907327, + "water_fog_color": 329011, + "fog_color": 12638463, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.overworld.deep_dark", + "max_delay": 24000, + "min_delay": 12000 + }, + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "nether_wastes", "id": 53, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 3344392, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "ghast", - "min_group_size": 4, - "max_group_size": 4, - "weight": 50 - }, - { - "name": "zombified_piglin", - "min_group_size": 4, - "max_group_size": 4, - "weight": 100 - }, - { - "name": "magma_cube", - "min_group_size": 4, - "max_group_size": 4, - "weight": 2 - }, - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 1 - }, - { - "name": "piglin", - "min_group_size": 4, - "max_group_size": 4, - "weight": 15 - } - ], - "creature": [ - { - "name": "strider", - "min_group_size": 1, - "max_group_size": 2, - "weight": 60 - } - ], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 3344392, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.nether.nether_wastes", + "max_delay": 24000, + "min_delay": 12000 + }, + "ambient_sound": "ambient.nether_wastes.loop", + "additions_sound": { + "sound": "ambient.nether_wastes.additions", + "tick_chance": 0.0111 + }, + "mood_sound": { + "sound": "ambient.nether_wastes.mood", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "zombified_piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 100 + }, + { + "name": "magma_cube", + "min_group_size": 4, + "max_group_size": 4, + "weight": 2 + }, + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "piglin", + "min_group_size": 4, + "max_group_size": 4, + "weight": 15 + } + ], + "creature": [ + { + "name": "strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "warped_forest", "id": 54, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 1705242, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 1 - } - ], - "creature": [ - { - "name": "strider", - "min_group_size": 1, - "max_group_size": 2, - "weight": 60 - } - ], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 1705242, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.nether.warped_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "ambient_sound": "ambient.warped_forest.loop", + "additions_sound": { + "sound": "ambient.warped_forest.additions", + "tick_chance": 0.0111 + }, + "mood_sound": { + "sound": "ambient.warped_forest.mood", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "crimson_forest", "id": 55, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 3343107, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "zombified_piglin", - "min_group_size": 2, - "max_group_size": 4, - "weight": 1 - }, - { - "name": "hoglin", - "min_group_size": 3, - "max_group_size": 4, - "weight": 9 - }, - { - "name": "piglin", - "min_group_size": 3, - "max_group_size": 4, - "weight": 5 - } - ], - "creature": [ - { - "name": "strider", - "min_group_size": 1, - "max_group_size": 2, - "weight": 60 - } - ], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 3343107, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.nether.crimson_forest", + "max_delay": 24000, + "min_delay": 12000 + }, + "ambient_sound": "ambient.crimson_forest.loop", + "additions_sound": { + "sound": "ambient.crimson_forest.additions", + "tick_chance": 0.0111 + }, + "mood_sound": { + "sound": "ambient.crimson_forest.mood", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "zombified_piglin", + "min_group_size": 2, + "max_group_size": 4, + "weight": 1 + }, + { + "name": "hoglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 9 + }, + { + "name": "piglin", + "min_group_size": 3, + "max_group_size": 4, + "weight": 5 + } + ], + "creature": [ + { + "name": "strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "soul_sand_valley", "id": 56, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 1787717, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "skeleton", - "min_group_size": 5, - "max_group_size": 5, - "weight": 20 - }, - { - "name": "ghast", - "min_group_size": 4, - "max_group_size": 4, - "weight": 50 - }, - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 1 - } - ], - "creature": [ - { - "name": "strider", - "min_group_size": 1, - "max_group_size": 2, - "weight": 60 - } - ], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 1787717, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.nether.soul_sand_valley", + "max_delay": 24000, + "min_delay": 12000 + }, + "ambient_sound": "ambient.soul_sand_valley.loop", + "additions_sound": { + "sound": "ambient.soul_sand_valley.additions", + "tick_chance": 0.0111 + }, + "mood_sound": { + "sound": "ambient.soul_sand_valley.mood", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "skeleton", + "min_group_size": 5, + "max_group_size": 5, + "weight": 20 + }, + { + "name": "ghast", + "min_group_size": 4, + "max_group_size": 4, + "weight": 50 + }, + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 1 + } + ], + "creature": [ + { + "name": "strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "basalt_deltas", "id": 57, - "climate": { + "element": { "precipitation": "none", "temperature": 2.0, - "downfall": 0.0 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 6840176, - "sky": 7254527, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "ghast", - "min_group_size": 1, - "max_group_size": 1, - "weight": 40 - }, - { - "name": "magma_cube", - "min_group_size": 2, - "max_group_size": 5, - "weight": 100 - } - ], - "creature": [ - { - "name": "strider", - "min_group_size": 1, - "max_group_size": 2, - "weight": 60 - } - ], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.0, + "effects": { + "sky_color": 7254527, + "water_fog_color": 329011, + "fog_color": 6840176, + "water_color": 4159204, + "grass_color_modifier": "none", + "music": { + "replace_current_music": false, + "sound": "music.nether.basalt_deltas", + "max_delay": 24000, + "min_delay": 12000 + }, + "ambient_sound": "ambient.basalt_deltas.loop", + "additions_sound": { + "sound": "ambient.basalt_deltas.additions", + "tick_chance": 0.0111 + }, + "mood_sound": { + "sound": "ambient.basalt_deltas.mood", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "ghast", + "min_group_size": 1, + "max_group_size": 1, + "weight": 40 + }, + { + "name": "magma_cube", + "min_group_size": 2, + "max_group_size": 5, + "weight": 100 + } + ], + "creature": [ + { + "name": "strider", + "min_group_size": 1, + "max_group_size": 2, + "weight": 60 + } + ], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "the_end", "id": 58, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 10518688, - "sky": 0, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 0, + "water_fog_color": 329011, + "fog_color": 10518688, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "end_highlands", "id": 59, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 10518688, - "sky": 0, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 0, + "water_fog_color": 329011, + "fog_color": 10518688, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "end_midlands", "id": 60, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 10518688, - "sky": 0, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 0, + "water_fog_color": 329011, + "fog_color": 10518688, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "small_end_islands", "id": 61, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 10518688, - "sky": 0, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 0, + "water_fog_color": 329011, + "fog_color": 10518688, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } }, { "name": "end_barrens", "id": 62, - "climate": { + "element": { "precipitation": "none", "temperature": 0.5, - "downfall": 0.5 - }, - "color": { - "grass": null, - "grass_modifier": "none", - "foliage": null, - "fog": 10518688, - "sky": 0, - "water_fog": 329011, - "water": 4159204 - }, - "spawn_settings": { - "probability": 0.1, - "groups": { - "monster": [ - { - "name": "enderman", - "min_group_size": 4, - "max_group_size": 4, - "weight": 10 - } - ], - "creature": [], - "ambient": [], - "axolotls": [], - "underground_water_creature": [], - "water_creature": [], - "water_ambient": [], - "misc": [] + "downfall": 0.5, + "effects": { + "sky_color": 0, + "water_fog_color": 329011, + "fog_color": 10518688, + "water_color": 4159204, + "grass_color_modifier": "none", + "mood_sound": { + "sound": "ambient.cave", + "tick_delay": 6000, + "offset": 2.0, + "block_search_extent": 8 + } + }, + "spawn_settings": { + "probability": 0.1, + "groups": { + "monster": [ + { + "name": "enderman", + "min_group_size": 4, + "max_group_size": 4, + "weight": 10 + } + ], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [], + "misc": [] + } } } } diff --git a/extractor/src/main/java/rs/valence/extractor/Main.java b/extractor/src/main/java/rs/valence/extractor/Main.java index 34fd53ba8..9d2fd8780 100644 --- a/extractor/src/main/java/rs/valence/extractor/Main.java +++ b/extractor/src/main/java/rs/valence/extractor/Main.java @@ -38,6 +38,7 @@ public void onInitialize() { LOGGER.info("Starting extractors..."); var extractors = new Extractor[]{ + new Biomes(), new Blocks(), new Enchants(), new Entities(), diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index c078e08e2..3d1a3d64e 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -1,40 +1,18 @@ package rs.valence.extractor.extractors; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import net.minecraft.entity.SpawnGroup; import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; import rs.valence.extractor.Main; -import java.util.Optional; - public class Biomes implements Main.Extractor { public Biomes() { } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private static JsonElement optional_to_json(Optional var) { - if (var.isEmpty()) { - return JsonNull.INSTANCE; - } else { - var value = var.get(); - if (value instanceof Boolean b) { - return new JsonPrimitive(b); - } else if (value instanceof Integer i) { - return new JsonPrimitive(i); - } else if (value instanceof Float f) { - return new JsonPrimitive(f); - } else if (value instanceof Long l) { - return new JsonPrimitive(l); - } else if (value instanceof Number n) { - return new JsonPrimitive(n); - } else { - throw new UnsupportedOperationException("Could not convert " + value + " to primitive (" + value.getClass().toString() + ")"); - } - } - } - @Override public String fileName() { return "biomes.json"; @@ -46,21 +24,49 @@ public JsonElement extract() { for (var biome : BuiltinRegistries.BIOME) { var biomeIdent = BuiltinRegistries.BIOME.getId(biome); + assert biomeIdent != null; - var climateJson = new JsonObject(); - climateJson.addProperty("precipitation", biome.getPrecipitation().getName()); - climateJson.addProperty("temperature", biome.getTemperature()); - climateJson.addProperty("downfall", biome.getDownfall()); + var biomeJson = new JsonObject(); + biomeJson.addProperty("precipitation", biome.getPrecipitation().getName()); + biomeJson.addProperty("temperature", biome.getTemperature()); + biomeJson.addProperty("downfall", biome.getDownfall()); - var colorJson = new JsonObject(); + var effectJson = new JsonObject(); var biomeEffects = biome.getEffects(); - colorJson.add("grass", optional_to_json(biomeEffects.getGrassColor())); - colorJson.addProperty("grass_modifier", biomeEffects.getGrassColorModifier().getName()); - colorJson.add("foliage", optional_to_json(biomeEffects.getFoliageColor())); - colorJson.addProperty("fog", biomeEffects.getFogColor()); - colorJson.addProperty("sky", biomeEffects.getSkyColor()); - colorJson.addProperty("water_fog", biomeEffects.getWaterFogColor()); - colorJson.addProperty("water", biomeEffects.getWaterColor()); + + effectJson.addProperty("sky_color", biomeEffects.getSkyColor()); + effectJson.addProperty("water_fog_color", biomeEffects.getWaterFogColor()); + effectJson.addProperty("fog_color", biomeEffects.getFogColor()); + effectJson.addProperty("water_color", biomeEffects.getWaterColor()); + biomeEffects.getFoliageColor().ifPresent(color -> effectJson.addProperty("foliage_color", color)); + biomeEffects.getGrassColor().ifPresent(color -> effectJson.addProperty("grass_color", color)); + effectJson.addProperty("grass_color_modifier", biomeEffects.getGrassColorModifier().getName()); + biomeEffects.getMusic().ifPresent(biome_music -> { + var music = new JsonObject(); + music.addProperty("replace_current_music", biome_music.shouldReplaceCurrentMusic()); + music.addProperty("sound", biome_music.getSound().getId().getPath()); + music.addProperty("max_delay", biome_music.getMaxDelay()); + music.addProperty("min_delay", biome_music.getMinDelay()); + effectJson.add("music", music); + }); + + biomeEffects.getLoopSound().ifPresent(soundEvent -> effectJson.addProperty("ambient_sound", soundEvent.getId().getPath())); + biomeEffects.getAdditionsSound().ifPresent(soundEvent -> { + var sound = new JsonObject(); + sound.addProperty("sound", soundEvent.getSound().getId().getPath()); + sound.addProperty("tick_chance", soundEvent.getChance()); + effectJson.add("additions_sound", sound); + }); + biomeEffects.getMoodSound().ifPresent(soundEvent -> { + var sound = new JsonObject(); + sound.addProperty("sound", soundEvent.getSound().getId().getPath()); + sound.addProperty("tick_delay", soundEvent.getCultivationTicks()); + sound.addProperty("offset", soundEvent.getExtraDistance()); + sound.addProperty("block_search_extent", soundEvent.getSpawnRange()); + + effectJson.add("mood_sound", sound); + }); + var spawnSettingsJson = new JsonObject(); var spawnSettings = biome.getSpawnSettings(); @@ -81,14 +87,14 @@ public JsonElement extract() { } spawnSettingsJson.add("groups", spawnGroupsJson); - var biomeJson = new JsonObject(); - biomeJson.addProperty("name", biomeIdent.getPath()); - biomeJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); - biomeJson.add("climate", climateJson); - biomeJson.add("color", colorJson); + biomeJson.add("effects", effectJson); biomeJson.add("spawn_settings", spawnSettingsJson); - biomesJson.add(biomeJson); + var entryJson = new JsonObject(); + entryJson.addProperty("name", biomeIdent.getPath()); + entryJson.addProperty("id", BuiltinRegistries.BIOME.getRawId(biome)); + entryJson.add("element", biomeJson); + biomesJson.add(entryJson); } return biomesJson; diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 4510d0cdd..75bc8c732 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -1,47 +1,42 @@ use std::collections::{BTreeMap, HashMap}; +use std::fmt; use heck::{ToPascalCase, ToSnakeCase}; -use proc_macro2::{Ident, TokenStream}; +use proc_macro2::{Ident as TokenIdent, TokenStream}; use quote::quote; -use serde::Deserialize; +use serde::de::Visitor; +use serde::{Deserialize, Deserializer}; use crate::ident; #[derive(Deserialize, Debug)] -struct ParsedBiome { - id: u16, - name: String, - climate: ParsedBiomeClimate, - color: ParsedBiomeColor, - spawn_settings: ParsedBiomeSpawnRates, -} - -#[derive(Debug)] -struct RenamedBiome { +struct ParsedElement { id: u16, - name: String, - rustified_name: Ident, - climate: ParsedBiomeClimate, - color: ParsedBiomeColor, - spawn_rates: ParsedBiomeSpawnRates, + #[serde(deserialize_with = "parse_ident")] + name: ParsedName, + element: ParsedBiome, } #[derive(Deserialize, Debug)] -struct ParsedBiomeClimate { - precipitation: String, +struct ParsedBiome { + #[serde(deserialize_with = "parse_ident")] + precipitation: ParsedName, temperature: f32, downfall: f32, + effects: ParsedBiomeEffects, + spawn_settings: ParsedBiomeSpawnRates, } #[derive(Deserialize, Debug)] -struct ParsedBiomeColor { - grass_modifier: String, - grass: Option, - foliage: Option, - fog: u32, - sky: u32, - water_fog: u32, - water: u32, +struct ParsedBiomeEffects { + sky_color: u32, + water_fog_color: u32, + fog_color: u32, + water_color: u32, + #[serde(deserialize_with = "parse_ident")] + grass_color_modifier: ParsedName, + grass_color: Option, + foliage_color: Option, } #[derive(Deserialize, Debug)] @@ -52,42 +47,49 @@ struct ParsedBiomeSpawnRates { #[derive(Deserialize, Debug)] struct ParsedSpawnRate { - name: String, + #[serde(deserialize_with = "parse_ident")] + name: ParsedName, min_group_size: u32, max_group_size: u32, weight: i32, } +#[derive(Debug)] +struct ParsedName { + token: TokenIdent, + raw: String, +} + +fn parse_ident<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + struct IdentVisitor; + impl<'de> Visitor<'de> for IdentVisitor { + type Value = ParsedName; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string containing a minecraft ID path") + } + fn visit_str(self, id: &str) -> Result { + Ok(ParsedName { + token: ident(id.to_pascal_case()), + raw: id.to_string(), + }) + } + } + deserializer.deserialize_str(IdentVisitor) +} + pub fn build() -> anyhow::Result { - let biomes: Vec = + let mut biomes: Vec = serde_json::from_str(include_str!("../../extracted/biomes.json"))?; - let mut biomes = biomes - .into_iter() - .map(|biome| RenamedBiome { - id: biome.id, - rustified_name: ident(biome.name.replace("minecraft:", "").to_pascal_case()), - name: biome.name, - climate: biome.climate, - color: biome.color, - spawn_rates: biome.spawn_settings, - }) - .collect::>(); - //Ensure biomes are sorted, even if the JSON changes later. biomes.sort_by(|one, two| one.id.cmp(&two.id)); - let mut precipitation_types = BTreeMap::<&str, Ident>::new(); - let mut grass_modifier_types = BTreeMap::<&str, Ident>::new(); - let mut class_spawn_fields = BTreeMap::<&str, Ident>::new(); - for biome in biomes.iter() { - precipitation_types - .entry(biome.climate.precipitation.as_str()) - .or_insert_with(|| ident(biome.climate.precipitation.to_pascal_case())); - grass_modifier_types - .entry(biome.color.grass_modifier.as_str()) - .or_insert_with(|| ident(biome.color.grass_modifier.to_pascal_case())); - for class in biome.spawn_rates.groups.keys() { + let mut class_spawn_fields = BTreeMap::<&str, TokenIdent>::new(); + for biome in biomes.iter().map(|b| &b.element) { + for class in biome.spawn_settings.groups.keys() { class_spawn_fields .entry(class) .or_insert_with(|| ident(class.to_snake_case())); @@ -104,10 +106,10 @@ pub fn build() -> anyhow::Result { let biome_kind_enum_declare = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; + let name = &biome.name.token; let id = biome.id as isize; quote! { - #rustified_name = #id, + #name = #id, } }) .collect::(); @@ -115,9 +117,9 @@ pub fn build() -> anyhow::Result { let biome_kind_enum_names = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; + let name = &biome.name.token; quote! { - #rustified_name + #name } }) .collect::>(); @@ -125,10 +127,10 @@ pub fn build() -> anyhow::Result { let biomekind_id_to_variant_lookup = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; + let name = &biome.name.token; let id = &biome.id; quote! { - #id => Some(Self::#rustified_name), + #id => Some(Self::#name), } }) .collect::(); @@ -136,10 +138,10 @@ pub fn build() -> anyhow::Result { let biomekind_name_lookup = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; - let name = &biome.name; + let name = &biome.name.token; + let raw = &biome.name.raw; quote! { - #name => Some(Self::#rustified_name), + #raw => Some(Self::#name), } }) .collect::(); @@ -147,10 +149,10 @@ pub fn build() -> anyhow::Result { let biomekind_temperatures_arms = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; - let temp = &biome.climate.temperature; + let name = &biome.name.token; + let temp = &biome.element.temperature; quote! { - Self::#rustified_name => #temp, + Self::#name => #temp, } }) .collect::(); @@ -158,10 +160,10 @@ pub fn build() -> anyhow::Result { let biomekind_downfall_arms = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; - let downfall = &biome.climate.downfall; + let name = &biome.name.token; + let downfall = &biome.element.downfall; quote! { - Self::#rustified_name => #downfall, + Self::#name => #downfall, } }) .collect::(); @@ -169,19 +171,19 @@ pub fn build() -> anyhow::Result { let biomekind_to_biome = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; - let name = &biome.name; - let precipitation = ident(biome.climate.precipitation.to_pascal_case()); - let sky_color = &biome.color.sky; - let water_fog = &biome.color.water_fog; - let fog = &biome.color.fog; - let water_color = &biome.color.water; - let foliage_color = option_to_quote(&biome.color.foliage); - let grass_color = option_to_quote(&biome.color.grass); - let grass_modifier = ident(biome.color.grass_modifier.to_pascal_case()); + let name = &biome.name.token; + let raw_name = &biome.name.raw; + let precipitation = &biome.element.precipitation.token; + let sky_color = &biome.element.effects.sky_color; + let water_fog = &biome.element.effects.water_fog_color; + let fog = &biome.element.effects.fog_color; + let water_color = &biome.element.effects.water_color; + let foliage_color = option_to_quote(&biome.element.effects.foliage_color); + let grass_color = option_to_quote(&biome.element.effects.grass_color); + let grass_modifier = &biome.element.effects.grass_color_modifier.token; quote! { - Self::#rustified_name => Ok(Biome{ - name: Ident::from_str(#name)?, + Self::#name => Ok(Biome{ + name: Ident::from_str(#raw_name)?, precipitation: BiomePrecipitation::#precipitation, sky_color: #sky_color, water_fog_color: #water_fog, @@ -203,31 +205,36 @@ pub fn build() -> anyhow::Result { let biomekind_spawn_settings_arms = biomes .iter() .map(|biome| { - let rustified_name = &biome.rustified_name; - let probability = biome.spawn_rates.probability; - - let fields = biome.spawn_rates.groups.iter().map(|(class, rates)| { - let rates = rates.iter().map(|spawn_rate| { - let name = &spawn_rate.name; - let min_group_size = &spawn_rate.min_group_size; - let max_group_size = &spawn_rate.max_group_size; - let weight = &spawn_rate.weight; - quote! { - SpawnProperty { - name: #name, - min_group_size: #min_group_size, - max_group_size: #max_group_size, - weight: #weight + let name = &biome.name.token; + let probability = biome.element.spawn_settings.probability; + + let fields = biome + .element + .spawn_settings + .groups + .iter() + .map(|(class, rates)| { + let rates = rates.iter().map(|spawn_rate| { + let name_raw = &spawn_rate.name.raw; + let min_group_size = &spawn_rate.min_group_size; + let max_group_size = &spawn_rate.max_group_size; + let weight = &spawn_rate.weight; + quote! { + SpawnProperty { + name: #name_raw, + min_group_size: #min_group_size, + max_group_size: #max_group_size, + weight: #weight + } } + }); + let class = ident(class); + quote! { + #class: &[#( #rates ),*] } }); - let class = ident(class); - quote! { - #class: &[#( #rates ),*] - } - }); quote! { - Self::#rustified_name => SpawnSettings { + Self::#name => SpawnSettings { probability: #probability, #( #fields ),* }, diff --git a/valence_anvil/build/main.rs b/valence_anvil/build/main.rs index d7200f067..e30a4068e 100644 --- a/valence_anvil/build/main.rs +++ b/valence_anvil/build/main.rs @@ -3,7 +3,7 @@ use std::process::Command; use std::{env, fs}; use anyhow::Context; -use proc_macro2::{Ident, Span}; +use proc_macro2::{Ident as TokenIdent, Span}; mod biome; @@ -27,12 +27,12 @@ pub fn main() -> anyhow::Result<()> { Ok(()) } -fn ident(s: impl AsRef) -> Ident { +fn ident(s: impl AsRef) -> TokenIdent { let s = s.as_ref().trim(); match s.as_bytes() { // TODO: check for the other rust keywords. - [b'0'..=b'9', ..] | b"type" => Ident::new(&format!("_{s}"), Span::call_site()), - _ => Ident::new(s, Span::call_site()), + [b'0'..=b'9', ..] | b"type" => TokenIdent::new(&format!("_{s}"), Span::call_site()), + _ => TokenIdent::new(s, Span::call_site()), } } From 055ec9aeeee0b8ff8370f5e019af6f8562403bb3 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 17 Dec 2022 15:47:36 +0100 Subject: [PATCH 64/75] Fix MacOS build requirement by removing borrow --- valence_anvil/build/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valence_anvil/build/main.rs b/valence_anvil/build/main.rs index e30a4068e..92c555f2d 100644 --- a/valence_anvil/build/main.rs +++ b/valence_anvil/build/main.rs @@ -17,7 +17,7 @@ pub fn main() -> anyhow::Result<()> { for (g, file_name) in generators { let path = Path::new(&out_dir).join(file_name); let code = g()?.to_string(); - fs::write(&path, &code)?; + fs::write(&path, code)?; // Format the output for debugging purposes. // Doesn't matter if rustfmt is unavailable. From 8dbbe64d37a7ad0ccb8071a049370f35ced9db0a Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sat, 17 Dec 2022 17:23:50 +0100 Subject: [PATCH 65/75] Clean up parser and add particle effect --- extracted/biomes.json | 16 ++ .../valence/extractor/extractors/Biomes.java | 26 +++ valence_anvil/build/biome.rs | 159 +++++++++++++++--- 3 files changed, 174 insertions(+), 27 deletions(-) diff --git a/extracted/biomes.json b/extracted/biomes.json index 2612854b1..cd5eb54c3 100644 --- a/extracted/biomes.json +++ b/extracted/biomes.json @@ -6502,6 +6502,10 @@ "precipitation": "none", "temperature": 2.0, "downfall": 0.0, + "particle": { + "kind": "warped_spore", + "probability": 0.01428 + }, "effects": { "sky_color": 7254527, "water_fog_color": 329011, @@ -6562,6 +6566,10 @@ "precipitation": "none", "temperature": 2.0, "downfall": 0.0, + "particle": { + "kind": "crimson_spore", + "probability": 0.025 + }, "effects": { "sky_color": 7254527, "water_fog_color": 329011, @@ -6634,6 +6642,10 @@ "precipitation": "none", "temperature": 2.0, "downfall": 0.0, + "particle": { + "kind": "ash", + "probability": 0.00625 + }, "effects": { "sky_color": 7254527, "water_fog_color": 329011, @@ -6706,6 +6718,10 @@ "precipitation": "none", "temperature": 2.0, "downfall": 0.0, + "particle": { + "kind": "white_ash", + "probability": 0.118093334 + }, "effects": { "sky_color": 7254527, "water_fog_color": 329011, diff --git a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java index 3d1a3d64e..fc4327707 100644 --- a/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java +++ b/extractor/src/main/java/rs/valence/extractor/extractors/Biomes.java @@ -4,11 +4,15 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.entity.SpawnGroup; +import net.minecraft.util.Identifier; import net.minecraft.util.collection.Weighted; import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.BiomeParticleConfig; import rs.valence.extractor.Main; +import java.lang.reflect.Field; + public class Biomes implements Main.Extractor { public Biomes() { } @@ -20,6 +24,16 @@ public String fileName() { @Override public JsonElement extract() { + // The biome particle probability field is private. + // We have to resort to reflection, unfortunately. + Field particleConfigProbabilityField; + try { + particleConfigProbabilityField = BiomeParticleConfig.class.getDeclaredField("probability"); + particleConfigProbabilityField.setAccessible(true); + } catch (Exception e) { + throw new RuntimeException(e); + } + var biomesJson = new JsonArray(); for (var biome : BuiltinRegistries.BIOME) { @@ -67,6 +81,18 @@ public JsonElement extract() { effectJson.add("mood_sound", sound); }); + biome.getParticleConfig().ifPresent(biomeParticleConfig -> { + try { + var particleConfig = new JsonObject(); + // We must first convert it into an identifier, because asString() returns a resource identifier as string. + Identifier id = new Identifier(biomeParticleConfig.getParticle().asString()); + particleConfig.addProperty("kind", id.getPath()); + particleConfig.addProperty("probability" ,particleConfigProbabilityField.getFloat(biomeParticleConfig)); + biomeJson.add("particle", particleConfig); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + }); var spawnSettingsJson = new JsonObject(); var spawnSettings = biome.getSpawnSettings(); diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index 75bc8c732..ef269ab10 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -3,7 +3,7 @@ use std::fmt; use heck::{ToPascalCase, ToSnakeCase}; use proc_macro2::{Ident as TokenIdent, TokenStream}; -use quote::quote; +use quote::{quote, ToTokens}; use serde::de::Visitor; use serde::{Deserialize, Deserializer}; @@ -12,18 +12,17 @@ use crate::ident; #[derive(Deserialize, Debug)] struct ParsedElement { id: u16, - #[serde(deserialize_with = "parse_ident")] name: ParsedName, element: ParsedBiome, } #[derive(Deserialize, Debug)] struct ParsedBiome { - #[serde(deserialize_with = "parse_ident")] precipitation: ParsedName, temperature: f32, downfall: f32, effects: ParsedBiomeEffects, + particle: Option, spawn_settings: ParsedBiomeSpawnRates, } @@ -33,10 +32,105 @@ struct ParsedBiomeEffects { water_fog_color: u32, fog_color: u32, water_color: u32, - #[serde(deserialize_with = "parse_ident")] grass_color_modifier: ParsedName, grass_color: Option, foliage_color: Option, + music: Option, + ambient_sound: Option, + additions_sound: Option, + mood_sound: Option, +} + +#[derive(Deserialize, Debug)] +struct ParsedMusic { + replace_current_music: bool, + sound: ParsedName, + max_delay: i32, + min_delay: i32, +} + +#[derive(Deserialize, Debug)] +struct ParsedAdditionsMusic { + sound: ParsedName, + tick_chance: f64, +} + +#[derive(Deserialize, Debug)] +struct ParsedMoodSound { + sound: ParsedName, + tick_delay: i32, + offset: f64, + block_search_extent: i32, +} + +#[derive(Deserialize, Debug)] +struct ParsedParticle { + kind: ParsedName, + probability: f32, +} + +impl ToTokens for ParsedMusic { + fn to_tokens(&self, tokens: &mut TokenStream) { + let replace_current_music = &self.replace_current_music; + let sound = &self.sound.raw; + let min_delay = &self.min_delay; + let max_delay = &self.max_delay; + quote! ( + BiomeMusic { + replace_current_music: #replace_current_music, + sound: Ident::from_str(#sound)?, + min_delay: #min_delay, + max_delay: #max_delay + } + ) + .to_tokens(tokens) + } +} + +impl ToTokens for ParsedAdditionsMusic { + fn to_tokens(&self, tokens: &mut TokenStream) { + let sound = &self.sound.raw; + let tick_chance = &self.tick_chance; + quote! ( + BiomeAdditionsSound { + sound: Ident::from_str(#sound)?, + tick_chance: #tick_chance, + } + ) + .to_tokens(tokens) + } +} + +impl ToTokens for ParsedMoodSound { + fn to_tokens(&self, tokens: &mut TokenStream) { + let sound = &self.sound.raw; + let block_search_extent = &self.block_search_extent; + let offset = &self.offset; + let tick_delay = &self.tick_delay; + quote! ( + BiomeMoodSound { + sound: Ident::from_str(#sound)?, + block_search_extent: #block_search_extent, + offset: #offset, + tick_delay: #tick_delay + } + ) + .to_tokens(tokens) + } +} + +impl ToTokens for ParsedParticle { + fn to_tokens(&self, tokens: &mut TokenStream) { + let kind = &self.kind.raw; + let probability = &self.probability; + quote! ( + BiomeParticle { + kind: Ident::from_str(#kind)?, + probability: #probability + } + ) + .to_tokens(tokens) + } } #[derive(Deserialize, Debug)] @@ -47,7 +141,6 @@ struct ParsedBiomeSpawnRates { #[derive(Deserialize, Debug)] struct ParsedSpawnRate { - #[serde(deserialize_with = "parse_ident")] name: ParsedName, min_group_size: u32, max_group_size: u32, @@ -60,24 +153,26 @@ struct ParsedName { raw: String, } -fn parse_ident<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - struct IdentVisitor; - impl<'de> Visitor<'de> for IdentVisitor { - type Value = ParsedName; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string containing a minecraft ID path") - } - fn visit_str(self, id: &str) -> Result { - Ok(ParsedName { - token: ident(id.to_pascal_case()), - raw: id.to_string(), - }) +impl<'de> Deserialize<'de> for ParsedName { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct IdentVisitor; + impl<'de> Visitor<'de> for IdentVisitor { + type Value = ParsedName; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string containing a minecraft ID path") + } + fn visit_str(self, id: &str) -> Result { + Ok(ParsedName { + token: ident(id.to_pascal_case()), + raw: id.to_string(), + }) + } } + deserializer.deserialize_str(IdentVisitor) } - deserializer.deserialize_str(IdentVisitor) } pub fn build() -> anyhow::Result { @@ -181,6 +276,16 @@ pub fn build() -> anyhow::Result { let foliage_color = option_to_quote(&biome.element.effects.foliage_color); let grass_color = option_to_quote(&biome.element.effects.grass_color); let grass_modifier = &biome.element.effects.grass_color_modifier.token; + let music = option_to_quote(&biome.element.effects.music); + let ambient_sound = option_to_quote({ + &biome.element.effects.ambient_sound.as_ref().map(|n| { + let raw = &n.raw; + quote!(Ident::from_str(#raw)?) + }) + }); + let additions_sound = option_to_quote(&biome.element.effects.additions_sound); + let mood_sound = option_to_quote(&biome.element.effects.mood_sound); + let particle = option_to_quote(&biome.element.particle); quote! { Self::#name => Ok(Biome{ name: Ident::from_str(#raw_name)?, @@ -192,11 +297,11 @@ pub fn build() -> anyhow::Result { foliage_color: #foliage_color, grass_color: #grass_color, grass_color_modifier: BiomeGrassColorModifier::#grass_modifier, - music: None, - ambient_sound: None, - additions_sound: None, - mood_sound: None, - particle: None, + music: #music, + ambient_sound: #ambient_sound, + additions_sound: #additions_sound, + mood_sound: #mood_sound, + particle: #particle, }), } }) @@ -245,7 +350,7 @@ pub fn build() -> anyhow::Result { let spawn_classes = class_spawn_fields.values(); Ok(quote! { - use valence::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation}; + use valence::biome::{Biome, BiomeMusic, BiomeAdditionsSound, BiomeMoodSound, BiomeParticle, BiomeGrassColorModifier, BiomePrecipitation}; use valence::protocol::ident::{Ident, IdentError}; use std::str::FromStr; From 9d71ab553805543faee792117a9b5e625821db89 Mon Sep 17 00:00:00 2001 From: Terminator Date: Sun, 18 Dec 2022 18:05:24 +0100 Subject: [PATCH 66/75] Remove async impl (#2) --- valence_anvil/Cargo.toml | 9 +- valence_anvil/benches/world_parsing.rs | 14 +-- valence_anvil/examples/java_region.rs | 4 +- valence_anvil/src/chunk.rs | 22 ++-- valence_anvil/src/compression.rs | 20 ++-- valence_anvil/src/lib.rs | 133 +++++++++++++------------ valence_anvil/src/region.rs | 61 +++++------- valence_anvil/tests/parse_world.rs | 13 +-- 8 files changed, 128 insertions(+), 148 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 2d08703dc..ef382f9e1 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -5,7 +5,7 @@ documentation = "https://docs.rs/valence_anvil/" repository = "https://github.com/valence_anvil/valence/tree/main/valence_anvil" readme = "README.md" license = "MIT" -keywords = ["anvil", "minecraft", "serialization"] +keywords = ["anvil", "minecraft", "deserialization"] version = "0.1.0" authors = ["Ryan Johnson ", "TerminatorNL "] build = "build/main.rs" @@ -14,10 +14,8 @@ edition = "2021" [dependencies] valence = { version = "0.1.0", path = ".." } rayon = "1.5.3" -async-compression = { version = "0.3.15", features = ["tokio", "gzip", "zlib"] } +flate2 = "1.0.25" byteorder = "1.4.3" -tokio = { version = "1.21.2", features = ["fs", "io-util"] } -futures = "0.3.24" thiserror = "1.0.37" num-traits = "0.2.15" @@ -25,8 +23,7 @@ num-traits = "0.2.15" tempfile = "3.3.0" zip = "0.5" fs_extra = "1.2.0" -zip-extensions = "0.6.1" -criterion = { version = "0.4.0", features = ["async", "async_tokio"] } +criterion = "0.4.0" [dev-dependencies.reqwest] version = "0.11.12" diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 91b50d1a7..10143d6e9 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -1,5 +1,4 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use tokio::runtime::Builder; use valence::biome::BiomeId; use valence::chunk::ChunkPos; use valence::config::Config; @@ -33,7 +32,7 @@ impl Config for BenchmarkConfig { fn criterion_benchmark(c: &mut Criterion) { let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); - let world = AnvilWorld::new::( + let mut world = AnvilWorld::new::( &Dimension::default(), world_directory, BiomeKind::ALL @@ -48,16 +47,11 @@ fn criterion_benchmark(c: &mut Criterion) { } } - let runtime = Builder::new_multi_thread() - .enable_all() - .build() - .expect("Creating runtime failed"); - c.bench_function("Load square 10x10", |b| { - b.to_async(&runtime).iter_with_setup( + b.iter_with_setup( || load_targets.clone().into_iter(), - |targets| async { - for (chunk_pos, chunk) in world.load_chunks(black_box(targets)).await.unwrap() { + |targets| { + for (chunk_pos, chunk) in world.load_chunks(black_box(targets)).unwrap() { assert!( chunk.is_some(), "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/java_region.rs index 181b2097a..913764cfe 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/java_region.rs @@ -179,9 +179,7 @@ impl Config for Game { } } - let future = world.state.load_chunks(new_chunks.into_iter()); - - let parsed_chunks = futures::executor::block_on(future).unwrap(); + let parsed_chunks = world.state.load_chunks(new_chunks.into_iter()).unwrap(); for (pos, chunk) in parsed_chunks { if let Some(chunk) = chunk { world.chunks.insert(pos, chunk, true); diff --git a/valence_anvil/src/chunk.rs b/valence_anvil/src/chunk.rs index 802608edf..6f4e2fdf6 100644 --- a/valence_anvil/src/chunk.rs +++ b/valence_anvil/src/chunk.rs @@ -8,7 +8,7 @@ use crate::error::{DataFormatError, Error, NbtFormatError}; use crate::palette::{ parse_identity_list_palette, parse_palette_identities_with_properties, DataFormat, }; -use crate::AnvilWorld; +use crate::AnvilWorldConfig; #[derive(Debug, Copy, Clone)] pub enum ChunkStatus { @@ -96,7 +96,10 @@ impl fmt::Display for ChunkStatus { } } -pub fn parse_chunk_nbt(mut nbt: Compound, world: &AnvilWorld) -> Result { +pub fn parse_chunk_nbt( + mut nbt: Compound, + world_config: &AnvilWorldConfig, +) -> Result { let status: ChunkStatus = ChunkStatus::from_nbt(&nbt)?; if !status.is_fully_generated() { return Err(Error::DataFormatError( @@ -106,7 +109,7 @@ pub fn parse_chunk_nbt(mut nbt: Compound, world: &AnvilWorld) -> Result Result Result Result| { - if let Some(biome) = world.biomes.get(&biome_identity) { + if let Some(biome) = world_config.biomes.get(&biome_identity) { Ok(*biome) } else { Err(Error::DataFormatError(DataFormatError::UnknownType( @@ -215,7 +219,8 @@ pub fn parse_chunk_nbt(mut nbt: Compound, world: &AnvilWorld) -> Result Result> 2 & 0b11; let x = index & 0b11; - let final_y = y + (chunk_y_offset / 4) - (world.min_y / 4); + let final_y = + y + (chunk_y_offset / 4) - (world_config.min_y / 4); chunk.set_biome(x, final_y as usize, z, biome); } } diff --git a/valence_anvil/src/compression.rs b/valence_anvil/src/compression.rs index 5393d4abe..2d34da9f8 100644 --- a/valence_anvil/src/compression.rs +++ b/valence_anvil/src/compression.rs @@ -1,6 +1,6 @@ -use async_compression::tokio::bufread::ZlibDecoder; -use async_compression::tokio::write::GzipDecoder; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; +use std::io::Read; + +use flate2::read::{GzDecoder, ZlibDecoder}; use crate::error::{DataFormatError, Error}; @@ -23,24 +23,24 @@ impl CompressionScheme { } } - pub(crate) async fn read_to_vec( + pub(crate) fn read_to_vec( self, source: &mut R, length: usize, ) -> Result, std::io::Error> { let mut raw_data = vec![0u8; length]; - source.read_exact(&mut raw_data).await?; + source.read_exact(&mut raw_data)?; match self { CompressionScheme::GZip => { - let mut decoder = GzipDecoder::new(Vec::::new()); - decoder.write_all(&raw_data).await?; - decoder.shutdown().await?; - Ok(decoder.into_inner()) + let mut decoder = GzDecoder::new(std::io::Cursor::new(raw_data)); + let mut vec = Vec::::new(); + decoder.read_to_end(&mut vec)?; + Ok(vec) } CompressionScheme::Zlib => { let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); let mut vec = Vec::::new(); - decoder.read_to_end(&mut vec).await?; + decoder.read_to_end(&mut vec)?; Ok(vec) } CompressionScheme::Raw => Ok(raw_data), diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index d35ec0bf3..ef876735d 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,11 +1,10 @@ use std::borrow::Borrow; use std::collections::BTreeMap; use std::fmt::Debug; +use std::fs::File; use std::path::PathBuf; use region::{ChunkTimestamp, Region, RegionPos}; -use tokio::fs::File; -use tokio::sync::{Mutex, MutexGuard}; use valence::biome::{Biome, BiomeId}; use valence::chunk::{ChunkPos, UnloadedChunk}; use valence::config::Config; @@ -26,10 +25,15 @@ mod region; #[derive(Debug)] pub struct AnvilWorld { world_root: PathBuf, - min_y: isize, - height: usize, - biomes: BTreeMap, BiomeId>, - region_files: Mutex>>>, + config: AnvilWorldConfig, + region_files: BTreeMap>>, +} + +#[derive(Debug)] +pub struct AnvilWorldConfig { + pub min_y: isize, + pub height: usize, + pub biomes: BTreeMap, BiomeId>, } impl AnvilWorld { @@ -69,12 +73,14 @@ impl AnvilWorld { } Self { world_root: directory.into(), - min_y: isize::from_i32(dimension.min_y) - .expect("Dimension min_y could not be converted to isize from i32."), - height: usize::from_i32(dimension.height) - .expect("Dimension height could not be converted to usize from i32."), - biomes, - region_files: Mutex::new(BTreeMap::new()), + config: AnvilWorldConfig { + min_y: isize::from_i32(dimension.min_y) + .expect("Dimension min_y could not be converted to isize from i32."), + height: usize::from_i32(dimension.height) + .expect("Dimension height could not be converted to usize from i32."), + biomes, + }, + region_files: BTreeMap::new(), } } @@ -109,63 +115,76 @@ impl AnvilWorld { /// } /// } /// ``` - pub async fn load_chunks>( - &self, + pub fn load_chunks>( + &mut self, positions: I, ) -> Result)>, Error> { - let mut map = BTreeMap::>::new(); - for pos in positions { - let region_pos = RegionPos::from(pos); - map.entry(region_pos) - .and_modify(|v| v.push(pos)) - .or_insert_with(|| vec![pos]); + let mut region_chunks = BTreeMap::>::new(); + for chunk_pos in positions { + let region_pos = RegionPos::from(chunk_pos); + region_chunks + .entry(region_pos) + .and_modify(|v| v.push(chunk_pos)) + .or_insert_with(|| vec![chunk_pos]); } - let mut result_vec = Vec::<(ChunkPos, Option)>::new(); - let mut lock = self.region_files.lock().await; - for (region_pos, chunk_pos_vec) in map.into_iter() { - if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { + for (region_pos, chunk_pos_vec) in region_chunks { + if let Some(region) = self.region_files.entry(region_pos).or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path)?, region_pos)?) + } else { + None + } + }) { // A region file exists, and it is loaded. - result_vec.extend(region.parse_chunks(self, chunk_pos_vec).await?); + result_vec.extend(region.parse_chunks(&self.config, chunk_pos_vec)?); } else { // No region file exists, there is no data to load here. result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); } } - Ok(result_vec.into_iter()) } - /// Get the last time the chunk was modified in seconds since epoch. - /// This operation will temporarily block operations on all region files - /// within `AnvilWorld`. - /// - /// # Arguments - /// - /// * `positions`: An iterator of chunk positions - /// - /// returns: An iterator with `ChunkPos` and the respective - /// `Option` as tuple. - pub async fn chunk_timestamps>( - &self, + // /// Get the last time the chunk was modified in seconds since epoch. + // /// This operation will temporarily block operations on all region files + // /// within `AnvilWorld`. + // /// + // /// # Arguments + // /// + // /// * `positions`: An iterator of chunk positions + // /// + // /// returns: An iterator with `ChunkPos` and the respective + // /// `Option` as tuple. + pub fn chunk_timestamps>( + &mut self, positions: I, ) -> Result)>, Error> { - let mut map = BTreeMap::>::new(); - for pos in positions { - let region_pos = RegionPos::from(pos); - map.entry(region_pos) - .and_modify(|v| v.push(pos)) - .or_insert_with(|| vec![pos]); + let mut region_chunks = BTreeMap::>::new(); + for chunk_pos in positions { + let region_pos = RegionPos::from(chunk_pos); + region_chunks + .entry(region_pos) + .and_modify(|v| v.push(chunk_pos)) + .or_insert_with(|| vec![chunk_pos]); } - let mut result_vec = Vec::<(ChunkPos, Option)>::new(); - let mut lock = self.region_files.lock().await; - for (region_pos, chunk_pos_vec) in map.into_iter() { - if let Some(region) = self.access_region_mut(&mut lock, region_pos).await? { + for (region_pos, chunk_pos_vec) in region_chunks { + if let Some(region) = self.region_files.entry(region_pos).or_insert({ + let path = region_pos.path(&self.world_root); + if path.exists() { + Some(Region::from_file(File::open(&path)?, region_pos)?) + } else { + None + } + }) { + // A region file exists, and it is loaded. for chunk_pos in chunk_pos_vec { result_vec.push((chunk_pos, region.chunk_timestamp(chunk_pos))); } } else { + // No region file exists, there is no data to load here. for chunk_pos in chunk_pos_vec { result_vec.push((chunk_pos, None)); } @@ -173,22 +192,4 @@ impl AnvilWorld { } Ok(result_vec.into_iter()) } - - async fn access_region_mut<'a>( - &self, - lock: &'a mut MutexGuard<'_, BTreeMap>>>, - region_pos: RegionPos, - ) -> Result>, Error> { - Ok(lock - .entry(region_pos) - .or_insert({ - let path = region_pos.path(&self.world_root); - if path.exists() { - Some(Region::from_file(File::open(&path).await?, region_pos).await?) - } else { - None - } - }) - .as_mut()) - } } diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs index abc8ce1e9..002bbd369 100644 --- a/valence_anvil/src/region.rs +++ b/valence_anvil/src/region.rs @@ -1,21 +1,19 @@ use std::fmt::{self, Debug, Formatter}; -use std::io::SeekFrom; +use std::fs::File; +use std::io::{Read, Seek, SeekFrom}; use std::path::{Path, PathBuf}; -use byteorder::{BigEndian, ByteOrder}; -use tokio::fs::File; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt}; -use tokio::sync::Mutex; +use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; use valence::chunk::{ChunkPos, UnloadedChunk}; use crate::chunk::parse_chunk_nbt; use crate::compression::CompressionScheme; use crate::error::{DataFormatError, Error}; -use crate::AnvilWorld; +use crate::AnvilWorldConfig; #[derive(Debug)] pub struct Region { - source: Mutex, + source: S, offset: u64, position: RegionPos, header: AnvilHeader, @@ -24,23 +22,21 @@ pub struct Region { impl Region { /// Convenience method, creates a Region object from the given file and /// position. - pub async fn from_file(source: File, position: RegionPos) -> Result { - Self::from_seek(Mutex::new(source), 0, position).await + pub fn from_file(source: File, position: RegionPos) -> Result { + Self::from_seek(source, 0, position) } } -impl Region { +impl Region { /// Creates a Region object using the incoming stream. The offset defines /// the position of the header start. - pub async fn from_seek( - source: Mutex, + pub fn from_seek( + mut source: S, offset: u64, position: RegionPos, ) -> Result { - let mut lock = source.lock().await; - lock.seek(SeekFrom::Start(offset)).await?; - let header = AnvilHeader::parse(&mut *lock).await?; - drop(lock); + source.seek(SeekFrom::Start(offset))?; + let header = AnvilHeader::parse(&mut source)?; Ok(Self { source, @@ -57,15 +53,13 @@ impl Region { .into_option() } - async fn read_chunk_bytes(&self, chunk_pos: ChunkPos) -> Result>, Error> { + fn read_chunk_bytes(&mut self, chunk_pos: ChunkPos) -> Result>, Error> { let seek_pos = self .header .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); - let mut lock = self.source.lock().await; - - lock.seek(SeekFrom::Start(seek_pos.offset() + self.offset)) - .await?; + self.source + .seek(SeekFrom::Start(seek_pos.offset() + self.offset))?; if seek_pos.len() == 0 { return Ok(None); @@ -73,7 +67,7 @@ impl Region { let compressed_chunk_size = { let mut buf = [0u8; 4]; - lock.read_exact(&mut buf).await?; + self.source.read_exact(&mut buf)?; BigEndian::read_u32(&buf) as usize }; @@ -83,16 +77,15 @@ impl Region { ))); } - let compression = CompressionScheme::from_raw(lock.read_u8().await?)?; - let uncompressed_buffer = compression - .read_to_vec(&mut *lock, compressed_chunk_size - 1) - .await?; + let compression = CompressionScheme::from_raw(self.source.read_u8()?)?; + let uncompressed_buffer = + compression.read_to_vec(&mut self.source, compressed_chunk_size - 1)?; Ok(Some(uncompressed_buffer)) } - pub(crate) async fn parse_chunks>( - &self, - world: &AnvilWorld, + pub(crate) fn parse_chunks>( + &mut self, + world_config: &AnvilWorldConfig, positions: I, ) -> Result)>, Error> { let mut results = Vec::<(ChunkPos, Option)>::new(); @@ -105,10 +98,10 @@ impl Region { self.position ); - let chunk_data = self.read_chunk_bytes(pos).await?; + let chunk_data = self.read_chunk_bytes(pos)?; if let Some(chunk_data) = chunk_data { let nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - match parse_chunk_nbt(nbt, world) { + match parse_chunk_nbt(nbt, world_config) { Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { .. })) | Err(Error::DataFormatError(DataFormatError::UnexpectedChunkState(..))) => { // The chunk is missing vital data and cannot be parsed. @@ -136,17 +129,17 @@ struct AnvilHeader { impl AnvilHeader { /// Parses the header bytes from the current position - async fn parse(source: &mut R) -> Result { + fn parse(source: &mut R) -> Result { let mut offsets = [ChunkSeekLocation::zero(); 1024]; for offset in &mut offsets { let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; + source.read_exact(&mut buf)?; offset.load(buf); } let mut timestamps = [ChunkTimestamp::zero(); 1024]; for timestamp in &mut timestamps { let mut buf = [0u8; 4]; - source.read_exact(&mut buf).await?; + source.read_exact(&mut buf)?; timestamp.load(buf); } Ok(Self { diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs index c081cb8cb..222675547 100644 --- a/valence_anvil/tests/parse_world.rs +++ b/valence_anvil/tests/parse_world.rs @@ -1,4 +1,3 @@ -use tokio::runtime::Builder; use valence::biome::BiomeId; use valence::chunk::ChunkPos; use valence::config::Config; @@ -29,7 +28,7 @@ impl Config for TestConfig { #[test] pub fn parse_world() { let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); - let world = AnvilWorld::new::( + let mut world = AnvilWorld::new::( &Dimension::default(), world_directory, BiomeKind::ALL @@ -43,15 +42,7 @@ pub fn parse_world() { } } - let runtime = Builder::new_current_thread() - .enable_all() - .build() - .expect("Creating runtime failed"); - - for (chunk_pos, chunk) in runtime - .block_on(world.load_chunks(load_targets.into_iter())) - .unwrap() - { + for (chunk_pos, chunk) in world.load_chunks(load_targets.into_iter()).unwrap() { assert!( chunk.is_some(), "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world generated?" From 1b5417582bd31612c1d29499e011c22e5e89e279 Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 18 Dec 2022 18:13:00 +0100 Subject: [PATCH 67/75] Update documentation (and examples) --- valence_anvil/src/lib.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index ef876735d..c8eb5b1ed 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -85,8 +85,6 @@ impl AnvilWorld { } /// Load chunks from the available region files within the world directory. - /// This operation will temporarily block operations on all region files - /// within `AnvilWorld`. /// /// # Arguments /// @@ -100,9 +98,16 @@ impl AnvilWorld { /// ```ignore /// use valence::prelude::*; /// - /// let to_load = chunks_in_view_distance(ChunkPos::at(p.x, p.z), dist); - /// let future = world.state.load_chunks(to_load); - /// let parsed_chunks = futures::executor::block_on(future).unwrap(); + /// let mut new_chunks = Vec::new(); + /// for pos in ChunkPos::at(p.x, p.z).in_view(dist) { + /// if let Some(existing) = world.chunks.get_mut(pos) { + /// existing.state = true; + /// } else { + /// new_chunks.push(pos); + /// } + /// } + /// + /// let parsed_chunks = world.state.load_chunks(new_chunks.into_iter()).unwrap(); /// for (pos, chunk) in parsed_chunks { /// if let Some(chunk) = chunk { /// // A chunk has successfully loaded from the region file. @@ -147,16 +152,14 @@ impl AnvilWorld { Ok(result_vec.into_iter()) } - // /// Get the last time the chunk was modified in seconds since epoch. - // /// This operation will temporarily block operations on all region files - // /// within `AnvilWorld`. - // /// - // /// # Arguments - // /// - // /// * `positions`: An iterator of chunk positions - // /// - // /// returns: An iterator with `ChunkPos` and the respective - // /// `Option` as tuple. + /// Get the last time the chunk was modified in seconds since epoch. + /// + /// # Arguments + /// + /// * `positions`: An iterator of chunk positions + /// + /// returns: An iterator with `ChunkPos` and the respective + /// `Option` as tuple. pub fn chunk_timestamps>( &mut self, positions: I, From d1f691b312f667b52777749931257481b6ced1ca Mon Sep 17 00:00:00 2001 From: TerminatorNL Date: Sun, 18 Dec 2022 21:34:25 +0100 Subject: [PATCH 68/75] Fix semantics --- valence_anvil/build/biome.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs index ef269ab10..e588e620a 100644 --- a/valence_anvil/build/biome.rs +++ b/valence_anvil/build/biome.rs @@ -162,12 +162,12 @@ impl<'de> Deserialize<'de> for ParsedName { impl<'de> Visitor<'de> for IdentVisitor { type Value = ParsedName; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string containing a minecraft ID path") + formatter.write_str("a string containing a minecraft identifier path") } - fn visit_str(self, id: &str) -> Result { + fn visit_str(self, identifier: &str) -> Result { Ok(ParsedName { - token: ident(id.to_pascal_case()), - raw: id.to_string(), + token: ident(identifier.to_pascal_case()), + raw: identifier.to_string(), }) } } From 909104c334635cbb1cd6df0e97ba9ee77f002a17 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 25 Dec 2022 04:30:21 -0800 Subject: [PATCH 69/75] Get basic block state loading working --- examples/terrain.rs | 4 +- src/chunk.rs | 229 ++++++------- valence_anvil/Cargo.toml | 16 +- .../{java_region.rs => valence_loading.rs} | 102 +++--- valence_anvil/src/biome.rs | 7 - valence_anvil/src/chunk.rs | 268 --------------- valence_anvil/src/compression.rs | 49 --- valence_anvil/src/error.rs | 58 ---- valence_anvil/src/lib.rs | 314 ++++++++---------- valence_anvil/src/palette.rs | 237 ------------- valence_anvil/src/region.rs | 250 -------------- valence_anvil/src/to_valence.rs | 177 ++++++++++ valence_anvil/tests/assets.rs | 2 +- 13 files changed, 504 insertions(+), 1209 deletions(-) rename valence_anvil/examples/{java_region.rs => valence_loading.rs} (69%) delete mode 100644 valence_anvil/src/biome.rs delete mode 100644 valence_anvil/src/chunk.rs delete mode 100644 valence_anvil/src/compression.rs delete mode 100644 valence_anvil/src/error.rs delete mode 100644 valence_anvil/src/palette.rs delete mode 100644 valence_anvil/src/region.rs create mode 100644 valence_anvil/src/to_valence.rs diff --git a/examples/terrain.rs b/examples/terrain.rs index b31c29141..195a53e3e 100644 --- a/examples/terrain.rs +++ b/examples/terrain.rs @@ -171,7 +171,7 @@ impl Config for Game { let mut in_terrain = false; let mut depth = 0; - for y in (0..chunk.height()).rev() { + for y in (0..chunk.section_count() * 16).rev() { let b = terrain_column( self, block_x, @@ -184,7 +184,7 @@ impl Config for Game { } // Add grass - for y in (0..chunk.height()).rev() { + for y in (0..chunk.section_count() * 16).rev() { if chunk.block_state(x, y, z).is_air() && chunk.block_state(x, y - 1, z) == BlockState::GRASS_BLOCK { diff --git a/src/chunk.rs b/src/chunk.rs index 319664624..10f77ba5f 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -204,7 +204,7 @@ impl Chunks { let y = pos.y.checked_sub(self.dimension_min_y)?.try_into().ok()?; - if y < chunk.height() { + if y < chunk.section_count() * 16 { Some(chunk.block_state( pos.x.rem_euclid(16) as usize, y, @@ -437,42 +437,46 @@ impl> IndexMut

for Chunks { /// Operations that can be performed on a chunk. [`LoadedChunk`] and /// [`UnloadedChunk`] implement this trait. pub trait Chunk { - /// Returns the height of this chunk in blocks. The result is always a - /// multiple of 16. - fn height(&self) -> usize; + /// Returns the number of sections in this chunk. To get the height of the + /// chunk in meters, multiply the result by 16. + fn section_count(&self) -> usize; /// Gets the block state at the provided offsets in the chunk. /// /// **Note**: The arguments to this function are offsets from the minimum - /// corner of the chunk in _chunk space_ rather than _world space_. You - /// might be looking for [`Chunks::block_state`] instead. + /// corner of the chunk in _chunk space_ rather than _world space_. /// /// # Panics /// - /// Panics if the offsets are outside the bounds of the chunk. + /// Panics if the offsets are outside the bounds of the chunk. `x` and `z` + /// must be less than 16 while `y` must be less than `section_count() * 16`. fn block_state(&self, x: usize, y: usize, z: usize) -> BlockState; /// Sets the block state at the provided offsets in the chunk. The previous /// block state at the position is returned. /// /// **Note**: The arguments to this function are offsets from the minimum - /// corner of the chunk in _chunk space_ rather than _world space_. You - /// might be looking for [`Chunks::set_block_state`] instead. + /// corner of the chunk in _chunk space_ rather than _world space_. /// /// # Panics /// - /// Panics if the offsets are outside the bounds of the chunk. + /// Panics if the offsets are outside the bounds of the chunk. `x` and `z` + /// must be less than 16 while `y` must be less than `section_count() * 16`. fn set_block_state(&mut self, x: usize, y: usize, z: usize, block: BlockState) -> BlockState; - /// Sets every block state in this chunk to the given block state. + /// Sets every block in a section to the given block state. /// - /// This is semantically equivalent to calling [`set_block_state`] on every - /// block in the chunk followed by a call to [`optimize`] at the end. - /// However, this function may be implemented more efficiently. + /// This is semantically equivalent to setting every block in the section + /// with [`set_block_state`]. However, this function may be implemented more + /// efficiently. + /// + /// # Panics + /// + /// Panics if `sect_y` is out of bounds. `sect_y` must be less than the + /// section count. /// /// [`set_block_state`]: Self::set_block_state - /// [`optimize`]: Self::optimize - fn fill_block_states(&mut self, block: BlockState); + fn fill_block_states(&mut self, sect_y: usize, block: BlockState); /// Gets the biome at the provided biome offsets in the chunk. /// @@ -481,7 +485,8 @@ pub trait Chunk { /// /// # Panics /// - /// Panics if the offsets are outside the bounds of the chunk. + /// Panics if the offsets are outside the bounds of the chunk. `x` and `z` + /// must be less than 4 while `y` must be less than `section_count() * 4`. fn biome(&self, x: usize, y: usize, z: usize) -> BiomeId; /// Sets the biome at the provided offsets in the chunk. The previous @@ -492,18 +497,23 @@ pub trait Chunk { /// /// # Panics /// - /// Panics if the offsets are outside the bounds of the chunk. + /// Panics if the offsets are outside the bounds of the chunk. `x` and `z` + /// must be less than 4 while `y` must be less than `section_count() * 4`. fn set_biome(&mut self, x: usize, y: usize, z: usize, biome: BiomeId) -> BiomeId; - /// Sets every biome in this chunk to the given biome. + /// Sets every biome in a section to the given block state. /// - /// This is semantically equivalent to calling [`set_biome`] on every - /// biome in the chunk followed by a call to [`optimize`] at the end. - /// However, this function may be implemented more efficiently. + /// This is semantically equivalent to setting every biome in the section + /// with [`set_biome`]. However, this function may be implemented more + /// efficiently. + /// + /// # Panics + /// + /// Panics if `sect_y` is out of bounds. `sect_y` must be less than the + /// section count. /// /// [`set_biome`]: Self::set_biome - /// [`optimize`]: Self::optimize - fn fill_biomes(&mut self, biome: BiomeId); + fn fill_biomes(&mut self, sect_y: usize, biome: BiomeId); /// Optimizes this chunk to use the minimum amount of memory possible. It /// should have no observable effect on the contents of the chunk. @@ -521,44 +531,30 @@ pub struct UnloadedChunk { impl UnloadedChunk { /// Constructs a new unloaded chunk containing only [`BlockState::AIR`] and - /// [`BiomeId::default()`] with the given height in blocks. - /// - /// # Panics - /// - /// Panics if the value of `height` does not meet the following criteria: - /// `height % 16 == 0 && height <= 4064`. - pub fn new(height: usize) -> Self { + /// [`BiomeId::default()`] with the given number of sections. A section is a + /// 16x16x16 meter volume. + pub fn new(section_count: usize) -> Self { let mut chunk = Self { sections: vec![] }; - - chunk.resize(height); + chunk.resize(section_count); chunk } - /// Changes the height of the chunk to `new_height`. This is a potentially - /// expensive operation that may involve copying. + /// Changes the section count of the chunk to `new_section_count`. This is a + /// potentially expensive operation that may involve copying. /// /// The chunk is extended and truncated from the top. New blocks are always /// [`BlockState::AIR`] and biomes are [`BiomeId::default()`]. - /// - /// # Panics - /// - /// The constraints on `new_height` are the same as [`UnloadedChunk::new`]. - pub fn resize(&mut self, new_height: usize) { - assert!( - new_height % 16 == 0 && new_height <= 4064, - "invalid chunk height of {new_height}" - ); - - let old_height = self.sections.len() * 16; + pub fn resize(&mut self, new_section_count: usize) { + let old_section_count = self.section_count(); - if new_height > old_height { - let additional = (new_height - old_height) / 16; - self.sections.reserve_exact(additional); + if new_section_count > old_section_count { self.sections - .resize_with(new_height / 16, ChunkSection::default); + .reserve_exact(new_section_count - old_section_count); + self.sections + .resize_with(new_section_count, ChunkSection::default); debug_assert_eq!(self.sections.capacity(), self.sections.len()); - } else if new_height < old_height { - self.sections.truncate(new_height / 16); + } else { + self.sections.truncate(new_section_count); } } } @@ -571,13 +567,13 @@ impl Default for UnloadedChunk { } impl Chunk for UnloadedChunk { - fn height(&self) -> usize { - self.sections.len() * 16 + fn section_count(&self) -> usize { + self.sections.len() } fn block_state(&self, x: usize, y: usize, z: usize) -> BlockState { assert!( - x < 16 && y < self.height() && z < 16, + x < 16 && y < self.section_count() * 16 && z < 16, "chunk block offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -588,7 +584,7 @@ impl Chunk for UnloadedChunk { fn set_block_state(&mut self, x: usize, y: usize, z: usize, block: BlockState) -> BlockState { assert!( - x < 16 && y < self.height() && z < 16, + x < 16 && y < self.section_count() * 16 && z < 16, "chunk block offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -605,23 +601,26 @@ impl Chunk for UnloadedChunk { old_block } - fn fill_block_states(&mut self, block: BlockState) { - for sect in self.sections.iter_mut() { - // TODO: adjust motion blocking here. - - if block.is_air() { - sect.non_air_count = 0; - } else { - sect.non_air_count = SECTION_BLOCK_COUNT as u16; - } + fn fill_block_states(&mut self, sect_y: usize, block: BlockState) { + let Some(sect) = self.sections.get_mut(sect_y) else { + panic!( + "section index {sect_y} out of bounds for chunk with {} sections", + self.section_count() + ) + }; - sect.block_states.fill(block); + if block.is_air() { + sect.non_air_count = 0; + } else { + sect.non_air_count = SECTION_BLOCK_COUNT as u16; } + + sect.block_states.fill(block); } fn biome(&self, x: usize, y: usize, z: usize) -> BiomeId { assert!( - x < 4 && y < self.height() / 4 && z < 4, + x < 4 && y < self.section_count() * 4 && z < 4, "chunk biome offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -630,7 +629,7 @@ impl Chunk for UnloadedChunk { fn set_biome(&mut self, x: usize, y: usize, z: usize, biome: BiomeId) -> BiomeId { assert!( - x < 4 && y < self.height() / 4 && z < 4, + x < 4 && y < self.section_count() * 4 && z < 4, "chunk biome offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -639,10 +638,15 @@ impl Chunk for UnloadedChunk { .set(x + z * 4 + y % 4 * 4 * 4, biome) } - fn fill_biomes(&mut self, biome: BiomeId) { - for sect in self.sections.iter_mut() { - sect.biomes.fill(biome); - } + fn fill_biomes(&mut self, sect_y: usize, biome: BiomeId) { + let Some(sect) = self.sections.get_mut(sect_y) else { + panic!( + "section index {sect_y} out of bounds for chunk with {} sections", + self.section_count() + ) + }; + + sect.biomes.fill(biome); } fn optimize(&mut self) { @@ -727,7 +731,7 @@ impl ChunkSection { impl LoadedChunk { fn new(mut chunk: UnloadedChunk, dimension_section_count: usize, state: C::ChunkState) -> Self { - chunk.resize(dimension_section_count * 16); + chunk.resize(dimension_section_count); Self { state, @@ -870,13 +874,13 @@ impl LoadedChunk { } impl Chunk for LoadedChunk { - fn height(&self) -> usize { - self.sections.len() * 16 + fn section_count(&self) -> usize { + self.sections.len() } fn block_state(&self, x: usize, y: usize, z: usize) -> BlockState { assert!( - x < 16 && y < self.height() && z < 16, + x < 16 && y < self.section_count() * 16 && z < 16, "chunk block offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -887,7 +891,7 @@ impl Chunk for LoadedChunk { fn set_block_state(&mut self, x: usize, y: usize, z: usize, block: BlockState) -> BlockState { assert!( - x < 16 && y < self.height() && z < 16, + x < 16 && y < self.section_count() * 16 && z < 16, "chunk block offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -909,37 +913,40 @@ impl Chunk for LoadedChunk { old_block } - fn fill_block_states(&mut self, block: BlockState) { - for sect in self.sections.iter_mut() { - // Mark the appropriate blocks as modified. - // No need to iterate through all the blocks if we know they're all the same. - if let PalettedContainer::Single(single) = §.block_states { - if block != *single { - sect.mark_all_blocks_as_modified(); - } - } else { - for i in 0..SECTION_BLOCK_COUNT { - if block != sect.block_states.get(i) { - sect.mark_block_as_modified(i); - } - } - } - - // TODO: adjust motion blocking here. + fn fill_block_states(&mut self, sect_y: usize, block: BlockState) { + let Some(sect) = self.sections.get_mut(sect_y) else { + panic!( + "section index {sect_y} out of bounds for chunk with {} sections", + self.section_count() + ) + }; - if block.is_air() { - sect.non_air_count = 0; - } else { - sect.non_air_count = SECTION_BLOCK_COUNT as u16; + // Mark the appropriate blocks as modified. + // No need to iterate through all the blocks if we know they're all the same. + if let PalettedContainer::Single(single) = §.block_states { + if block != *single { + sect.mark_all_blocks_as_modified(); } + } else { + for i in 0..SECTION_BLOCK_COUNT { + if block != sect.block_states.get(i) { + sect.mark_block_as_modified(i); + } + } + } - sect.block_states.fill(block); + if block.is_air() { + sect.non_air_count = 0; + } else { + sect.non_air_count = SECTION_BLOCK_COUNT as u16; } + + sect.block_states.fill(block); } fn biome(&self, x: usize, y: usize, z: usize) -> BiomeId { assert!( - x < 4 && y < self.height() / 4 && z < 4, + x < 4 && y < self.section_count() * 4 && z < 4, "chunk biome offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -948,7 +955,7 @@ impl Chunk for LoadedChunk { fn set_biome(&mut self, x: usize, y: usize, z: usize, biome: BiomeId) -> BiomeId { assert!( - x < 4 && y < self.height() / 4 && z < 4, + x < 4 && y < self.section_count() * 4 && z < 4, "chunk biome offsets of ({x}, {y}, {z}) are out of bounds" ); @@ -963,10 +970,15 @@ impl Chunk for LoadedChunk { old_biome } - fn fill_biomes(&mut self, biome: BiomeId) { - for sect in self.sections.iter_mut() { - sect.biomes.fill(biome); - } + fn fill_biomes(&mut self, sect_y: usize, biome: BiomeId) { + let Some(sect) = self.sections.get_mut(sect_y) else { + panic!( + "section index {sect_y} out of bounds for chunk with {} sections", + self.section_count() + ) + }; + + sect.biomes.fill(biome); // TODO: this is set to true unconditionally, but it doesn't have to be. self.any_biomes_modified = true; @@ -983,13 +995,6 @@ impl Chunk for LoadedChunk { } } -/* -fn is_motion_blocking(b: BlockState) -> bool { - // TODO: use is_solid || is_fluid ? - !b.is_air() -} -*/ - fn compact_u64s_len(vals_count: usize, bits_per_val: usize) -> usize { let vals_per_u64 = 64 / bits_per_val; num::Integer::div_ceil(&vals_count, &vals_per_u64) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index ef382f9e1..41e2d3ae6 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -12,18 +12,20 @@ build = "build/main.rs" edition = "2021" [dependencies] -valence = { version = "0.1.0", path = ".." } -rayon = "1.5.3" -flate2 = "1.0.25" byteorder = "1.4.3" +flate2 = "1.0.25" thiserror = "1.0.37" -num-traits = "0.2.15" +num = "0.4.0" # TODO: remove when div_ceil is stabilized. +valence = { version = "0.1.0", path = "..", optional = true } +valence_nbt = { version = "0.5.0", path = "../valence_nbt" } [dev-dependencies] -tempfile = "3.3.0" -zip = "0.5" -fs_extra = "1.2.0" criterion = "0.4.0" +fs_extra = "1.2.0" +tempfile = "3.3.0" +zip = "0.6.3" +valence = { version = "0.1.0", path = ".." } +valence_anvil = { version = "0.1.0", path = ".", features = ["valence"] } [dev-dependencies.reqwest] version = "0.11.12" diff --git a/valence_anvil/examples/java_region.rs b/valence_anvil/examples/valence_loading.rs similarity index 69% rename from valence_anvil/examples/java_region.rs rename to valence_anvil/examples/valence_loading.rs index 913764cfe..3390ff1f0 100644 --- a/valence_anvil/examples/java_region.rs +++ b/valence_anvil/examples/valence_loading.rs @@ -1,10 +1,12 @@ extern crate valence; + +use std::env; use std::net::SocketAddr; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::prelude::*; -use valence_anvil::biome::BiomeKind; +// use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; /// # IMPORTANT @@ -14,32 +16,27 @@ use valence_anvil::AnvilWorld; /// commonly see `advancements`, `DIM1`, `DIM-1` and most importantly `region` /// subdirectories. Only the `region` directory is accessed. pub fn main() -> ShutdownResult { - let args: Vec = std::env::args().collect(); - if let Some(world_folder) = args.get(1) { - let world_folder = PathBuf::from(world_folder); - if world_folder.exists() && world_folder.is_dir() { - if !world_folder.join("region").exists() { - ShutdownResult::Err( - "Could not find the `region` folder inside the world directory.".into(), - ) - } else { - // This actually starts and runs the server. - valence::start_server( - Game { - world_dir: world_folder, - player_count: AtomicUsize::new(0), - }, - None, - ) - } - } else { - ShutdownResult::Err( - "World directory argument is not valid: Must be a folder that exists.".into(), - ) - } - } else { - ShutdownResult::Err("Please add the world directory as program argument.".into()) + let Some(world_dir) = env::args().nth(1) else { + return Err("Please add the world directory as program argument.".into()) + }; + + let world_dir = PathBuf::from(world_dir); + + if !world_dir.exists() || !world_dir.is_dir() { + return Err("World argument must be a directory that exists".into()) + } + + if !world_dir.join("region").exists() { + return Err("Could not find the \"region\" directory in the given world directory".into()) } + + valence::start_server( + Game { + world_dir, + player_count: AtomicUsize::new(0), + }, + None, + ) } #[derive(Debug, Default)] @@ -66,9 +63,9 @@ impl Config for Game { type PlayerListState = (); type InventoryState = (); - fn biomes(&self) -> Vec { - BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() - } + // fn biomes(&self) -> Vec { + // BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() + // } async fn server_list_ping( &self, @@ -91,18 +88,15 @@ impl Config for Game { fn init(&self, server: &mut Server) { for (id, dimension) in server.shared.dimensions() { - server.worlds.insert( - id, - AnvilWorld::new::(dimension, &self.world_dir, server.shared.biomes()), - ); + server.worlds.insert(id, AnvilWorld::new(&self.world_dir)); } server.state = Some(server.player_lists.insert(()).0); } fn update(&self, server: &mut Server) { - let (world_id, world): (WorldId, &mut World<_>) = server.worlds.iter_mut().next().unwrap(); + let (world_id, world) = server.worlds.iter_mut().next().unwrap(); - server.clients.retain(|_, client: &mut Client<_>| { + server.clients.retain(|_, client| { if client.created_this_tick() { if self .player_count @@ -170,25 +164,39 @@ impl Config for Game { let dist = client.view_distance(); let p = client.position(); - let mut new_chunks = Vec::new(); for pos in ChunkPos::at(p.x, p.z).in_view(dist) { if let Some(existing) = world.chunks.get_mut(pos) { existing.state = true; } else { - new_chunks.push(pos); + match world.state.read_chunk(pos.x, pos.z) { + Ok(Some(anvil_chunk)) => { + let mut chunk = UnloadedChunk::new(24); + + if let Err(e) = valence_anvil::to_valence( + &anvil_chunk.data, + &mut chunk, + 0, + |_| todo!(), + ) { + eprintln!( + "failed to convert chunk at ({}, {}): {e}", + pos.x, pos.z + ); + } + + world.chunks.insert(pos, chunk, true); + } + Ok(None) => { + // No chunk at this position. + world.chunks.insert(pos, UnloadedChunk::default(), true); + } + Err(e) => { + eprintln!("failed to read chunk at ({}, {}): {e}", pos.x, pos.z) + } + } } } - let parsed_chunks = world.state.load_chunks(new_chunks.into_iter()).unwrap(); - for (pos, chunk) in parsed_chunks { - if let Some(chunk) = chunk { - world.chunks.insert(pos, chunk, true); - } else { - let mut blank_chunk = UnloadedChunk::new(16); - blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); - world.chunks.insert(pos, blank_chunk, true); - } - } true }); diff --git a/valence_anvil/src/biome.rs b/valence_anvil/src/biome.rs deleted file mode 100644 index 5d3d19536..000000000 --- a/valence_anvil/src/biome.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! This module contains data for the default Minecraft biomes. -//! -//! All biome variants are located in [`BiomeKind`]. You can use the -//! associated const functions of [`BiomeKind`] to access details about a -//! biome type. - -include!(concat!(env!("OUT_DIR"), "/biome.rs")); diff --git a/valence_anvil/src/chunk.rs b/valence_anvil/src/chunk.rs deleted file mode 100644 index 6f4e2fdf6..000000000 --- a/valence_anvil/src/chunk.rs +++ /dev/null @@ -1,268 +0,0 @@ -use std::fmt; - -use num_traits::FromPrimitive; -use valence::nbt::{List, Value}; -use valence::prelude::*; - -use crate::error::{DataFormatError, Error, NbtFormatError}; -use crate::palette::{ - parse_identity_list_palette, parse_palette_identities_with_properties, DataFormat, -}; -use crate::AnvilWorldConfig; - -#[derive(Debug, Copy, Clone)] -pub enum ChunkStatus { - Empty, - StructureStarts, - StructureReferences, - Biomes, - Noise, - Surface, - Carvers, - LiquidCarvers, - Features, - Light, - Spawn, - Heightmaps, - Full, -} - -impl ChunkStatus { - /// Retrieves the "Status" field from the NBT compound and parses it to - /// `Self` - /// - /// # Arguments - /// - /// * `nbt`: The chunk NBT compound - /// - /// returns: the status or `Self::Unknown` if no valid status was found. - pub fn from_nbt(nbt: &Compound) -> Result { - match nbt.get("Status") { - None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: None, - key: "Status".to_string(), - })), - Some(Value::String(x)) => match x.as_str() { - "full" => Ok(Self::Full), - "empty" => Ok(Self::Empty), - "structure_starts" => Ok(Self::StructureStarts), - "structure_references" => Ok(Self::StructureReferences), - "biomes" => Ok(Self::Biomes), - "noise" => Ok(Self::Noise), - "surface" => Ok(Self::Surface), - "carvers" => Ok(Self::Carvers), - "liquid_carvers" => Ok(Self::LiquidCarvers), - "features" => Ok(Self::Features), - "light" => Ok(Self::Light), - "spawn" => Ok(Self::Spawn), - "heightmaps" => Ok(Self::Heightmaps), - raw => Err(Error::DataFormatError(DataFormatError::InvalidChunkState( - raw.to_string(), - ))), - }, - Some(_) => Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: None, - key: "Status".to_string(), - })), - } - } - - pub fn is_fully_generated(&self) -> bool { - matches!(self, ChunkStatus::Full) - } - - pub fn raw_status(&self) -> &str { - match self { - Self::Full => "full", - Self::Empty => "empty", - Self::StructureStarts => "structure_starts", - Self::StructureReferences => "structure_references", - Self::Biomes => "biomes", - Self::Noise => "noise", - Self::Surface => "surface", - Self::Carvers => "carvers", - Self::LiquidCarvers => "liquid_carvers", - Self::Features => "features", - Self::Light => "light", - Self::Spawn => "spawn", - Self::Heightmaps => "heightmaps", - } - } -} - -impl fmt::Display for ChunkStatus { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.raw_status()) - } -} - -pub fn parse_chunk_nbt( - mut nbt: Compound, - world_config: &AnvilWorldConfig, -) -> Result { - let status: ChunkStatus = ChunkStatus::from_nbt(&nbt)?; - if !status.is_fully_generated() { - return Err(Error::DataFormatError( - DataFormatError::UnexpectedChunkState(status), - )); - } - - if let Some(Value::List(List::Compound(nbt_sections))) = nbt.remove("sections") { - // Parsing sections - let mut chunk = UnloadedChunk::new(world_config.height); - for mut nbt_section in nbt_sections.into_iter() { - let chunk_y_offset: isize = if let Some(Value::Byte(y)) = nbt_section.get("Y") { - match isize::from_i8(*y) { - None => { - return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { - tag: Some(nbt_section), - key: "Y", - })); - } - Some(height) => height * 16, - } - } else { - return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { - tag: Some(nbt_section), - key: "Y", - })); - }; - - // Block states - match nbt_section.remove("block_states") { - Some(Value::Compound(tag)) => { - parse_palette_identities_with_properties::( - tag, - 4, - 16 * 16 * 16, - |identity: Ident| { - if let Some(block_kind) = BlockKind::from_str(identity.path()) { - Ok(BlockState::from_kind(block_kind)) - } else { - Err(Error::DataFormatError(DataFormatError::UnknownType( - identity, - ))) - } - }, - |state: BlockState, property: PropName, value: PropValue| { - Ok(state.set(property, value)) - }, - |data: DataFormat| match data { - DataFormat::All(state) => { - if !state.is_air() { - for x in 0..16 { - for y in 0..16isize { - for z in 0..16 { - chunk.set_block_state( - x, - (y + chunk_y_offset - world_config.min_y) - as usize, - z, - state, - ); - } - } - } - } - Ok(()) - } - DataFormat::Palette(index, state) => { - let y = (index >> 8 & 0b1111) as isize; - let z = index >> 4 & 0b1111; - let x = index & 0b1111; - chunk.set_block_state( - x, - (y + chunk_y_offset - world_config.min_y) as usize, - z, - state, - ); - Ok(()) - } - }, - )?; - } - Some(value) => { - nbt_section.insert("block_states", value); - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(nbt_section), - key: "block_states".to_string(), - })); - } - None => { - return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { - key: "block_states", - tag: Some(nbt_section), - })); - } - } - - match nbt_section.remove("biomes") { - Some(Value::Compound(tag)) => { - parse_identity_list_palette::( - tag, - 0, - 4 * 4 * 4, - |biome_identity: Ident| { - if let Some(biome) = world_config.biomes.get(&biome_identity) { - Ok(*biome) - } else { - Err(Error::DataFormatError(DataFormatError::UnknownType( - biome_identity, - ))) - } - }, - |data: DataFormat| { - match data { - DataFormat::All(biome) => { - for x in 0..4 { - for y in 0..4isize { - for z in 0..4 { - chunk.set_biome( - x, - (y + (chunk_y_offset / 4) - - (world_config.min_y / 4)) - as usize, - z, - biome, - ); - } - } - } - } - DataFormat::Palette(index, biome) => { - let y = (index >> 4 & 0b11) as isize; - let z = index >> 2 & 0b11; - let x = index & 0b11; - - let final_y = - y + (chunk_y_offset / 4) - (world_config.min_y / 4); - chunk.set_biome(x, final_y as usize, z, biome); - } - } - Ok(()) - }, - )?; - } - Some(value) => { - nbt_section.insert("biomes", value); - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { - key: "biomes".to_string(), - tag: Some(nbt_section), - })); - } - None => { - return Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { - key: "biomes", - tag: Some(nbt_section), - })); - } - } - } - Ok(chunk) - } else { - Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { - key: "sections", - tag: Some(nbt), - })) - } -} diff --git a/valence_anvil/src/compression.rs b/valence_anvil/src/compression.rs deleted file mode 100644 index 2d34da9f8..000000000 --- a/valence_anvil/src/compression.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::io::Read; - -use flate2::read::{GzDecoder, ZlibDecoder}; - -use crate::error::{DataFormatError, Error}; - -#[derive(Debug, Copy, Clone)] -pub enum CompressionScheme { - GZip = 1, - Zlib = 2, - Raw = 3, -} - -impl CompressionScheme { - pub(crate) fn from_raw(mode: u8) -> Result { - match mode { - 1 => Ok(Self::GZip), - 2 => Ok(Self::Zlib), - 3 => Ok(Self::Raw), - scheme => Err(Error::DataFormatError( - DataFormatError::UnknownCompressionScheme(scheme), - )), - } - } - - pub(crate) fn read_to_vec( - self, - source: &mut R, - length: usize, - ) -> Result, std::io::Error> { - let mut raw_data = vec![0u8; length]; - source.read_exact(&mut raw_data)?; - match self { - CompressionScheme::GZip => { - let mut decoder = GzDecoder::new(std::io::Cursor::new(raw_data)); - let mut vec = Vec::::new(); - decoder.read_to_end(&mut vec)?; - Ok(vec) - } - CompressionScheme::Zlib => { - let mut decoder = ZlibDecoder::new(std::io::Cursor::new(raw_data)); - let mut vec = Vec::::new(); - decoder.read_to_end(&mut vec)?; - Ok(vec) - } - CompressionScheme::Raw => Ok(raw_data), - } - } -} diff --git a/valence_anvil/src/error.rs b/valence_anvil/src/error.rs deleted file mode 100644 index d9916b320..000000000 --- a/valence_anvil/src/error.rs +++ /dev/null @@ -1,58 +0,0 @@ -use std::io; - -use thiserror::Error; -use valence::prelude::Compound; -use valence::protocol::ident::{Ident, IdentError}; - -use crate::chunk::ChunkStatus; - -#[derive(Error, Debug)] -pub enum Error { - #[error(transparent)] - Io(#[from] io::Error), - #[error(transparent)] - DataFormatError(#[from] DataFormatError), - #[error(transparent)] - NbtParseError(#[from] valence::nbt::Error), - #[error(transparent)] - NbtFormatError(#[from] NbtFormatError), -} - -#[derive(Error, Debug)] -pub enum NbtFormatError { - #[error("Missing key: {key}")] - MissingKey { key: String, tag: Option }, - #[error("Invalid type: {key}")] - InvalidType { key: String, tag: Option }, -} - -#[derive(Error, Debug)] -pub enum DataFormatError { - #[error("Unknown compression scheme: {0}")] - UnknownCompressionScheme(u8), - #[error("Invalid chunk size: {0}")] - InvalidChunkSize(usize), - #[error("Missing chunk parameter: {key}")] - MissingChunkNBT { - key: &'static str, - tag: Option, - }, - #[error(transparent)] - IdentityError(#[from] IdentError), - #[error("Unknown identity: {0}")] - UnknownType(Ident), - #[error("Invalid chunk state: {0}")] - InvalidChunkState(String), - #[error("Unexpected chunk state: {0}")] - UnexpectedChunkState(ChunkStatus), - #[error("Property load error: {name} {value}")] - PropertyLoadError { name: String, value: String }, - #[error("Invalid chunk palette")] - InvalidPalette, -} - -impl From> for Error { - fn from(err: IdentError) -> Self { - Self::DataFormatError(DataFormatError::IdentityError(err)) - } -} diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index c8eb5b1ed..55d904330 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -1,198 +1,170 @@ -use std::borrow::Borrow; +use std::collections::btree_map::Entry; use std::collections::BTreeMap; -use std::fmt::Debug; use std::fs::File; +use std::io; +use std::io::{ErrorKind, Read, Seek, SeekFrom}; use std::path::PathBuf; -use region::{ChunkTimestamp, Region, RegionPos}; -use valence::biome::{Biome, BiomeId}; -use valence::chunk::{ChunkPos, UnloadedChunk}; -use valence::config::Config; -use valence::dimension::Dimension; -use valence::protocol::Ident; -use valence::vek::num_traits::FromPrimitive; +use byteorder::{BigEndian, ReadBytesExt}; +use flate2::bufread::{GzDecoder, ZlibDecoder}; +use thiserror::Error; +#[cfg(feature = "valence")] +pub use to_valence::*; +use valence_nbt::Compound; -use crate::error::Error; - -pub mod biome; -pub mod compression; -pub mod error; - -mod chunk; -mod palette; -mod region; +#[cfg(feature = "valence")] +mod to_valence; #[derive(Debug)] pub struct AnvilWorld { - world_root: PathBuf, - config: AnvilWorldConfig, - region_files: BTreeMap>>, + /// Path to the "region" subdirectory in the world root. + region_root: PathBuf, + /// Maps region (x, z) positions to region files. + regions: BTreeMap<(i32, i32), Region>, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct AnvilChunk { + /// This chunk's NBT data. + pub data: Compound, + /// The time this chunk was last modified measured in seconds since the + /// epoch. + pub timestamp: u32, +} + +#[derive(Debug, Error)] +#[non_exhaustive] +pub enum ReadChunkError { + #[error(transparent)] + Io(#[from] io::Error), + #[error(transparent)] + Nbt(#[from] valence_nbt::Error), + #[error("invalid chunk sector offset")] + BadSectorOffset, + #[error("invalid chunk size")] + BadChunkSize, + #[error("unknown compression scheme number of {0}")] + UnknownCompressionScheme(u8), + #[error("not all chunk NBT data was read")] + IncompleteNbtRead, } #[derive(Debug)] -pub struct AnvilWorldConfig { - pub min_y: isize, - pub height: usize, - pub biomes: BTreeMap, BiomeId>, +struct Region { + file: File, + /// The first 8 KiB in the file. The header in the file and the in-memory + /// header must be kept in sync when writes occur. + header: [u8; SECTOR_SIZE * 2], } +const SECTOR_SIZE: usize = 4096; + impl AnvilWorld { - /// Creates an `AnvilWorld` instance. - /// - /// # Arguments - /// - /// * `directory`: A path to the world folder. Inside this folder you should - /// see the `region` directory. - /// * `server`: The shared server. This is used to initialize which biomes - /// to use. - /// - /// returns: AnvilWorld - /// - /// # Examples - /// - /// ```ignore - /// impl Config for Game { - /// fn init(&self, server: &mut Server) { - /// for (id, dimension) in server.shared.dimensions() { - /// server.worlds.insert( - /// id, - /// AnvilWorld::new::(&dimension, &self.world_dir, server.shared.biomes()), - /// ); - /// } - /// } - /// } - /// ``` - pub fn new>( - dimension: &Dimension, - directory: impl Into, - server_biomes: impl Iterator, - ) -> Self { - let mut biomes = BTreeMap::new(); - for (id, biome) in server_biomes { - biomes.insert(biome.borrow().name.clone(), id); - } + pub fn new(world_root: impl Into) -> Self { + let mut region_root = world_root.into(); + region_root.push("region"); + Self { - world_root: directory.into(), - config: AnvilWorldConfig { - min_y: isize::from_i32(dimension.min_y) - .expect("Dimension min_y could not be converted to isize from i32."), - height: usize::from_i32(dimension.height) - .expect("Dimension height could not be converted to usize from i32."), - biomes, - }, - region_files: BTreeMap::new(), + region_root, + regions: BTreeMap::new(), } } - /// Load chunks from the available region files within the world directory. - /// - /// # Arguments - /// - /// * `positions`: Any iterator of `valence::chunk_pos::ChunkPos` - /// - /// returns: An iterator of the requested chunk positions and their - /// associated chunks - /// - /// # Examples - /// - /// ```ignore - /// use valence::prelude::*; - /// - /// let mut new_chunks = Vec::new(); - /// for pos in ChunkPos::at(p.x, p.z).in_view(dist) { - /// if let Some(existing) = world.chunks.get_mut(pos) { - /// existing.state = true; - /// } else { - /// new_chunks.push(pos); - /// } - /// } - /// - /// let parsed_chunks = world.state.load_chunks(new_chunks.into_iter()).unwrap(); - /// for (pos, chunk) in parsed_chunks { - /// if let Some(chunk) = chunk { - /// // A chunk has successfully loaded from the region file. - /// world.chunks.insert(pos, chunk, true); - /// } else { - /// // There is no information on this chunk in the region file. - /// let mut blank_chunk = UnloadedChunk::new(16); - /// blank_chunk.set_block_state(0, 0, 0, BlockState::from_kind(BlockKind::Lava)); - /// world.chunks.insert(pos, blank_chunk, true); - /// } - /// } - /// ``` - pub fn load_chunks>( + pub fn read_chunk( &mut self, - positions: I, - ) -> Result)>, Error> { - let mut region_chunks = BTreeMap::>::new(); - for chunk_pos in positions { - let region_pos = RegionPos::from(chunk_pos); - region_chunks - .entry(region_pos) - .and_modify(|v| v.push(chunk_pos)) - .or_insert_with(|| vec![chunk_pos]); - } - let mut result_vec = Vec::<(ChunkPos, Option)>::new(); - for (region_pos, chunk_pos_vec) in region_chunks { - if let Some(region) = self.region_files.entry(region_pos).or_insert({ - let path = region_pos.path(&self.world_root); - if path.exists() { - Some(Region::from_file(File::open(&path)?, region_pos)?) - } else { - None - } - }) { - // A region file exists, and it is loaded. - result_vec.extend(region.parse_chunks(&self.config, chunk_pos_vec)?); - } else { - // No region file exists, there is no data to load here. - result_vec.extend(chunk_pos_vec.into_iter().map(|pos| (pos, None))); + chunk_x: i32, + chunk_z: i32, + ) -> Result, ReadChunkError> { + let region_x = chunk_x.div_euclid(32); + let region_z = chunk_z.div_euclid(32); + + let region = match self.regions.entry((region_x, region_z)) { + Entry::Vacant(ve) => { + // Load the region file if it exists. Otherwise, the chunk is considered absent. + + let path = self + .region_root + .join(format!("r.{region_x}.{region_z}.mca")); + + let mut file = match File::options().read(true).write(true).open(path) { + Ok(file) => file, + Err(e) if e.kind() == ErrorKind::NotFound => return Ok(None), + Err(e) => return Err(e.into()), + }; + + let mut header = [0; SECTOR_SIZE * 2]; + + file.read_exact(&mut header)?; + + ve.insert(Region { file, header }) } + Entry::Occupied(oe) => oe.into_mut(), + }; + + let chunk_idx = (chunk_x.rem_euclid(32) + chunk_z.rem_euclid(32) * 32) as usize; + + let location_bytes = (®ion.header[chunk_idx * 4..]).read_u32::()?; + let timestamp = (®ion.header[chunk_idx * 4 + SECTOR_SIZE..]).read_u32::()?; + + if location_bytes == 0 { + // No chunk exists at this position. + return Ok(None); } - Ok(result_vec.into_iter()) - } - /// Get the last time the chunk was modified in seconds since epoch. - /// - /// # Arguments - /// - /// * `positions`: An iterator of chunk positions - /// - /// returns: An iterator with `ChunkPos` and the respective - /// `Option` as tuple. - pub fn chunk_timestamps>( - &mut self, - positions: I, - ) -> Result)>, Error> { - let mut region_chunks = BTreeMap::>::new(); - for chunk_pos in positions { - let region_pos = RegionPos::from(chunk_pos); - region_chunks - .entry(region_pos) - .and_modify(|v| v.push(chunk_pos)) - .or_insert_with(|| vec![chunk_pos]); + let sector_offset = (location_bytes >> 8) as u64; + let sector_count = (location_bytes & 0xff) as usize; + + if sector_offset < 2 { + // If the sector offset was <2, then the chunk data would be inside the region + // header. That doesn't make any sense. + return Err(ReadChunkError::BadSectorOffset); + } + + // Seek to the beginning of the chunk's data. + region + .file + .seek(SeekFrom::Start(sector_offset * SECTOR_SIZE as u64))?; + + let exact_chunk_size = region.file.read_u32::()? as usize; + + if exact_chunk_size > sector_count * SECTOR_SIZE { + // Sector size of this chunk must always be >= the exact size. + return Err(ReadChunkError::BadChunkSize); } - let mut result_vec = Vec::<(ChunkPos, Option)>::new(); - for (region_pos, chunk_pos_vec) in region_chunks { - if let Some(region) = self.region_files.entry(region_pos).or_insert({ - let path = region_pos.path(&self.world_root); - if path.exists() { - Some(Region::from_file(File::open(&path)?, region_pos)?) - } else { - None - } - }) { - // A region file exists, and it is loaded. - for chunk_pos in chunk_pos_vec { - result_vec.push((chunk_pos, region.chunk_timestamp(chunk_pos))); - } - } else { - // No region file exists, there is no data to load here. - for chunk_pos in chunk_pos_vec { - result_vec.push((chunk_pos, None)); - } + + let mut data_buf = vec![0; exact_chunk_size].into_boxed_slice(); + region.file.read_exact(&mut data_buf)?; + + let mut r = data_buf.as_ref(); + + let mut decompress_buf = vec![]; + + // What compression does the chunk use? + let mut nbt_slice = match r.read_u8()? { + // GZip + 1 => { + let mut z = GzDecoder::new(r); + z.read_to_end(&mut decompress_buf)?; + decompress_buf.as_slice() } + // Zlib + 2 => { + let mut z = ZlibDecoder::new(r); + z.read_to_end(&mut decompress_buf)?; + decompress_buf.as_slice() + } + // Uncompressed + 3 => r, + // Unknown + b => return Err(ReadChunkError::UnknownCompressionScheme(b)), + }; + + let (data, _) = valence_nbt::from_binary_slice(&mut nbt_slice)?; + + if !nbt_slice.is_empty() { + return Err(ReadChunkError::IncompleteNbtRead); } - Ok(result_vec.into_iter()) + + Ok(Some(AnvilChunk { data, timestamp })) } } diff --git a/valence_anvil/src/palette.rs b/valence_anvil/src/palette.rs deleted file mode 100644 index 5192d8b33..000000000 --- a/valence_anvil/src/palette.rs +++ /dev/null @@ -1,237 +0,0 @@ -use std::ops::BitXor; - -use valence::nbt::{Compound, List, Value}; -use valence::prelude::*; - -use crate::error::{DataFormatError, Error, NbtFormatError}; - -pub enum DataFormat { - All(T), - Palette(usize, T), -} - -pub fn parse_palette_identities_with_properties< - T: Copy, - FT: FnMut(Ident) -> Result, - FP: FnMut(T, PropName, PropValue) -> Result, - F: FnMut(DataFormat) -> Result<(), Error>, ->( - palette_container: Compound, - min_bits: usize, - expected_len: usize, - mut loader: FT, - mut applicator: FP, - handler: F, -) -> Result<(), Error> { - parse_compound_palette( - palette_container, - min_bits, - expected_len, - |mut nbt| match (nbt.remove("Name"), nbt.remove("Properties")) { - (Some(Value::String(identity)), None) => loader(Ident::new(identity)?), - (Some(Value::String(identity)), Some(Value::Compound(properties))) => { - let mut object = loader(Ident::new(identity)?)?; - for (property_name_raw, property_value) in &properties { - if let Value::String(property_value) = property_value { - match ( - PropName::from_str(property_name_raw), - PropValue::from_str(property_value), - ) { - (Some(name), Some(value)) => { - object = applicator(object, name, value)?; - } - _ => { - return Err(Error::DataFormatError( - DataFormatError::PropertyLoadError { - name: property_name_raw.to_string(), - value: property_value.to_string(), - }, - )) - } - } - } else { - return Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(properties), - key: "Name".to_string(), - })); - } - } - Ok(object) - } - (Some(_), Some(Value::Compound(_))) => { - Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: None, - key: "Name".to_string(), - })) - } - (None, Some(Value::Compound(_))) => { - Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: None, - key: "Name".to_string(), - })) - } - (_, Some(_)) => Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: None, - key: "Properties".to_string(), - })), - (_, None) => Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: None, - key: "Properties".to_string(), - })), - }, - handler, - ) -} - -pub fn parse_compound_palette< - T: Copy, - FT: FnMut(Compound) -> Result, - F: FnMut(DataFormat) -> Result<(), Error>, ->( - mut palette_container: Compound, - min_bits: usize, - expected_len: usize, - mut loader: FT, - handler: F, -) -> Result<(), Error> { - match palette_container.remove("palette") { - Some(Value::List(List::Compound(nbt_palette_vec))) => { - let iter = nbt_palette_vec.into_iter(); - let mut keys = Vec::::with_capacity(iter.len()); - for tag in iter { - keys.push(loader(tag)?) - } - match palette_container.remove("data") { - Some(Value::LongArray(data)) => { - decode_palette(&keys, Some(data), min_bits, expected_len, handler) - } - Some(data) => { - palette_container.insert("data", data); - Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(palette_container), - key: "data".to_string(), - })) - } - None => decode_palette(&keys, None, min_bits, expected_len, handler), - } - } - Some(value) => { - palette_container.insert("palette", value); - Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(palette_container), - key: "palette".to_string(), - })) - } - None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: Some(palette_container), - key: "palette".to_string(), - })), - } -} - -pub fn parse_identity_list_palette< - T: Copy, - FT: FnMut(Ident) -> Result, - F: FnMut(DataFormat) -> Result<(), Error>, ->( - mut palette_container: Compound, - min_bits: usize, - expected_len: usize, - mut loader: FT, - handler: F, -) -> Result<(), Error> { - match palette_container.remove("palette") { - Some(Value::List(List::String(nbt_palette_vec))) => { - let iter = nbt_palette_vec.into_iter(); - let mut keys = Vec::::with_capacity(iter.len()); - for tag in iter { - keys.push(loader(Ident::new(tag)?)?) - } - match palette_container.remove("data") { - Some(Value::LongArray(data)) => { - decode_palette(&keys, Some(data), min_bits, expected_len, handler) - } - Some(data) => { - palette_container.insert("data", data); - Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(palette_container), - key: "data".to_string(), - })) - } - None => decode_palette(&keys, None, min_bits, expected_len, handler), - } - } - Some(value) => { - palette_container.insert("palette", value); - Err(Error::NbtFormatError(NbtFormatError::InvalidType { - tag: Some(palette_container), - key: "palette".to_string(), - })) - } - None => Err(Error::NbtFormatError(NbtFormatError::MissingKey { - tag: Some(palette_container), - key: "palette".to_string(), - })), - } -} - -pub fn decode_palette) -> Result<(), Error>)>( - source: &Vec, - data: Option>, - min_bits: usize, - expected_len: usize, - mut fun: F, -) -> Result<(), Error> { - let palette_len = source.len(); - if palette_len == 0 { - return Err(crate::error::Error::DataFormatError( - DataFormatError::InvalidPalette, - )); - } - if let Some(data) = data { - if palette_len < 2 || data.is_empty() { - fun(DataFormat::All(source[0]))?; - Ok(()) - } else { - let choice_len = palette_len - 1; //Corrects for the absence of a non-choice: null is not an option. - let bits_per_index = usize::max( - (usize::BITS - choice_len.leading_zeros()) as usize, - min_bits, - ); - let entries_per_integer = i64::BITS as usize / bits_per_index; - - let mut entry_mask = (u64::MAX << bits_per_index).bitxor(u64::MAX); - let mut mask_fields: Vec<(u64, usize)> = vec![(0u64, 0usize); entries_per_integer]; - for (i, mask_field) in mask_fields.iter_mut().enumerate() { - *mask_field = (entry_mask, (i * bits_per_index)); - entry_mask <<= bits_per_index; - } - - let mut index: usize = 0; - for integer in data { - let integer = integer as u64; - for (mask, rev_shift) in &mask_fields { - let palette_index_unshifted = (integer & mask) as usize; - let palette_index_shifted = palette_index_unshifted >> rev_shift; - - if palette_index_shifted > choice_len { - return Err(crate::error::Error::DataFormatError( - DataFormatError::InvalidPalette, - )); - } else { - fun(DataFormat::Palette(index, source[palette_index_shifted]))?; - index += 1; - // Prevents interpreting the rest of the long as data. - if index == expected_len { - return Ok(()); - } - } - } - } - Ok(()) - } - } else { - fun(DataFormat::All(source[0]))?; - Ok(()) - } -} diff --git a/valence_anvil/src/region.rs b/valence_anvil/src/region.rs deleted file mode 100644 index 002bbd369..000000000 --- a/valence_anvil/src/region.rs +++ /dev/null @@ -1,250 +0,0 @@ -use std::fmt::{self, Debug, Formatter}; -use std::fs::File; -use std::io::{Read, Seek, SeekFrom}; -use std::path::{Path, PathBuf}; - -use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; -use valence::chunk::{ChunkPos, UnloadedChunk}; - -use crate::chunk::parse_chunk_nbt; -use crate::compression::CompressionScheme; -use crate::error::{DataFormatError, Error}; -use crate::AnvilWorldConfig; - -#[derive(Debug)] -pub struct Region { - source: S, - offset: u64, - position: RegionPos, - header: AnvilHeader, -} - -impl Region { - /// Convenience method, creates a Region object from the given file and - /// position. - pub fn from_file(source: File, position: RegionPos) -> Result { - Self::from_seek(source, 0, position) - } -} - -impl Region { - /// Creates a Region object using the incoming stream. The offset defines - /// the position of the header start. - pub fn from_seek( - mut source: S, - offset: u64, - position: RegionPos, - ) -> Result { - source.seek(SeekFrom::Start(offset))?; - let header = AnvilHeader::parse(&mut source)?; - - Ok(Self { - source, - offset, - position, - header, - }) - } - - /// Get the last time the chunk was modified in seconds since epoch. - pub fn chunk_timestamp(&self, chunk_pos: ChunkPos) -> Option { - self.header - .timestamp((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize) - .into_option() - } - - fn read_chunk_bytes(&mut self, chunk_pos: ChunkPos) -> Result>, Error> { - let seek_pos = self - .header - .offset((chunk_pos.x & 31) as usize, (chunk_pos.z & 31) as usize); - - self.source - .seek(SeekFrom::Start(seek_pos.offset() + self.offset))?; - - if seek_pos.len() == 0 { - return Ok(None); - } - - let compressed_chunk_size = { - let mut buf = [0u8; 4]; - self.source.read_exact(&mut buf)?; - BigEndian::read_u32(&buf) as usize - }; - - if compressed_chunk_size == 0 { - return Err(Error::DataFormatError(DataFormatError::InvalidChunkSize( - compressed_chunk_size, - ))); - } - - let compression = CompressionScheme::from_raw(self.source.read_u8()?)?; - let uncompressed_buffer = - compression.read_to_vec(&mut self.source, compressed_chunk_size - 1)?; - Ok(Some(uncompressed_buffer)) - } - - pub(crate) fn parse_chunks>( - &mut self, - world_config: &AnvilWorldConfig, - positions: I, - ) -> Result)>, Error> { - let mut results = Vec::<(ChunkPos, Option)>::new(); - - for pos in positions.into_iter() { - assert!( - self.position.contains(pos), - "Chunk position {:?} was not found in region {:?}", - pos, - self.position - ); - - let chunk_data = self.read_chunk_bytes(pos)?; - if let Some(chunk_data) = chunk_data { - let nbt = valence::nbt::from_binary_slice(&mut chunk_data.as_slice())?.0; - match parse_chunk_nbt(nbt, world_config) { - Err(Error::DataFormatError(DataFormatError::MissingChunkNBT { .. })) - | Err(Error::DataFormatError(DataFormatError::UnexpectedChunkState(..))) => { - // The chunk is missing vital data and cannot be parsed. - results.push((pos, None)); - } - Err(e) => return Err(e), - Ok(parsed_chunk) => { - results.push((pos, Some(parsed_chunk))); - } - } - } else { - results.push((pos, None)); - } - } - - Ok(results.into_iter()) - } -} - -#[derive(Copy, Clone, Debug)] -struct AnvilHeader { - offsets: [ChunkSeekLocation; 1024], - timestamps: [ChunkTimestamp; 1024], -} - -impl AnvilHeader { - /// Parses the header bytes from the current position - fn parse(source: &mut R) -> Result { - let mut offsets = [ChunkSeekLocation::zero(); 1024]; - for offset in &mut offsets { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf)?; - offset.load(buf); - } - let mut timestamps = [ChunkTimestamp::zero(); 1024]; - for timestamp in &mut timestamps { - let mut buf = [0u8; 4]; - source.read_exact(&mut buf)?; - timestamp.load(buf); - } - Ok(Self { - offsets, - timestamps, - }) - } - - #[inline(always)] - fn offset(&self, x: usize, z: usize) -> &ChunkSeekLocation { - &self.offsets[(x & 0b11111) + ((z & 0b11111) * 32)] - } - - #[inline(always)] - fn timestamp(&self, x: usize, z: usize) -> &ChunkTimestamp { - &self.timestamps[(x & 0b11111) + ((z & 0b11111) * 32)] - } -} - -/// The location of the chunk inside the region file. -#[derive(Copy, Clone, Debug)] -struct ChunkSeekLocation { - offset_sectors: u32, - len_sectors: u8, -} - -impl ChunkSeekLocation { - const fn zero() -> Self { - Self { - offset_sectors: 0, - len_sectors: 0, - } - } - - const fn offset(&self) -> u64 { - self.offset_sectors as u64 * 1024 * 4 - } - - const fn len(&self) -> usize { - self.len_sectors as usize * 1024 * 4 - } - - fn load(&mut self, chunk: [u8; 4]) { - self.offset_sectors = BigEndian::read_u24(&chunk[..3]); - self.len_sectors = chunk[3]; - } -} - -/// The timestamp when the chunk was last modified in seconds since epoch. -#[derive(Copy, Clone)] -pub struct ChunkTimestamp(u32); - -impl Debug for ChunkTimestamp { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "{}s", self.0) - } -} - -impl ChunkTimestamp { - const fn zero() -> Self { - Self(0) - } - - fn load(&mut self, chunk: [u8; 4]) { - self.0 = BigEndian::read_u32(&chunk) - } - - fn into_option(self) -> Option { - if self.0 == 0 { - None - } else { - Some(self) - } - } - - #[inline(always)] - pub fn seconds_since_epoch(self) -> u32 { - self.0 - } -} - -#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] -pub struct RegionPos { - x: i32, - z: i32, -} - -impl From for RegionPos { - fn from(pos: ChunkPos) -> Self { - Self { - x: pos.x >> 5, - z: pos.z >> 5, - } - } -} - -impl RegionPos { - pub fn path(self, world_root: impl AsRef) -> PathBuf { - world_root - .as_ref() - .join("region") - .join(format!("r.{}.{}.mca", self.x, self.z)) - } - - pub fn contains(self, chunk_pos: ChunkPos) -> bool { - Self::from(chunk_pos) == self - } -} diff --git a/valence_anvil/src/to_valence.rs b/valence_anvil/src/to_valence.rs new file mode 100644 index 000000000..4a4cb1bc5 --- /dev/null +++ b/valence_anvil/src/to_valence.rs @@ -0,0 +1,177 @@ +use num::integer::div_ceil; +use thiserror::Error; +use valence::biome::BiomeId; +use valence::chunk::{Chunk, UnloadedChunk}; +use valence::protocol::block::{BlockKind, PropName, PropValue}; +use valence::protocol::Ident; +use valence_nbt::{Compound, List, Value}; + +#[derive(Debug, Error)] +#[non_exhaustive] +pub enum ToValenceError<'a> { + #[error("missing chunk sections")] + MissingSections, + #[error("missing chunk section Y")] + MissingSectionY, + #[error("missing block states")] + MissingBlockStates, + #[error("missing block palette")] + MissingBlockPalette, + #[error("missing block name in palette")] + MissingBlockName, + #[error("unknown block name of \"{0}\"")] + UnknownBlockName(&'a str), + #[error("unknown property name of \"{0}\"")] + UnknownPropName(&'a str), + #[error("property value of block is not a string")] + BadPropValueType, + #[error("unknown property value of \"{0}\"")] + UnknownPropValue(&'a str), + #[error("missing packed block state data in section")] + MissingBlockStateData, + #[error("unexpected number of longs in block state blob")] + BadBlockStateLongCount, + #[error("invalid block palette index")] + InvalidBlockPaletteIndex, +} + +/// Reads an Anvil chunk in NBT form and writes its data to a Valence [`Chunk`]. +/// +/// - `nbt`: The Anvil chunk to read from. This is usually the value returned by +/// [`read_chunk`]. +/// - `chunk`: The Valence chunk to write to. +/// - `sect_offset`: +/// +/// [`read_chunk`]: crate::AnvilWorld::read_chunk +pub fn to_valence<'a, C, F>( + nbt: &'a Compound, + chunk: &mut C, + sect_offset: i32, + mut map_biomes: F, +) -> Result<(), ToValenceError<'a>> +where + C: Chunk, + F: FnMut(Ident<&str>) -> BiomeId, +{ + let Some(Value::List(List::Compound(sections))) = nbt.get("sections") else { + return Err(ToValenceError::MissingSections) + }; + + // Maps palette indices to the corresponding block state in the palette. + let mut converted_block_palette = vec![]; + + for section in sections { + let Some(Value::Byte(sect_y)) = section.get("Y") else { + return Err(ToValenceError::MissingSectionY) + }; + + let adjusted_sect_y = *sect_y as i32 + sect_offset; + + if adjusted_sect_y < 0 || adjusted_sect_y as usize >= chunk.section_count() { + // Section is out of bounds. Skip it. + continue; + } + + let Some(Value::Compound(block_states)) = section.get("block_states") else { + return Err(ToValenceError::MissingBlockStates) + }; + + let Some(Value::List(List::Compound(palette))) = block_states.get("palette") else { + return Err(ToValenceError::MissingBlockPalette) + }; + + converted_block_palette.clear(); + + for block in palette { + let Some(Value::String(name)) = block.get("Name") else { + return Err(ToValenceError::MissingBlockName) + }; + + let Some(block_kind) = BlockKind::from_str(ident_path(name)) else { + return Err(ToValenceError::UnknownBlockName(name.as_str())) + }; + + let mut state = block_kind.to_state(); + + if let Some(Value::Compound(properties)) = block.get("Properties") { + for (key, value) in properties { + let Value::String(value) = value else { + return Err(ToValenceError::BadPropValueType) + }; + + let Some(prop_name) = PropName::from_str(key) else { + return Err(ToValenceError::UnknownPropName(key)) + }; + + let Some(prop_value) = PropValue::from_str(value) else { + return Err(ToValenceError::UnknownPropValue(value)) + }; + + state = state.set(prop_name, prop_value); + } + } + + converted_block_palette.push(state); + } + + if converted_block_palette.len() == 1 { + chunk.fill_block_states(adjusted_sect_y as usize, converted_block_palette[0]); + } else if converted_block_palette.len() > 1 { + let Some(Value::LongArray(data)) = block_states.get("data") else { + return Err(ToValenceError::MissingBlockStateData) + }; + + let bits_per_idx = bit_width(converted_block_palette.len() - 1).max(4); + let idxs_per_long = 64 / bits_per_idx; + let long_count = div_ceil(BLOCKS_PER_SECTION, idxs_per_long); + let mask = 2_u64.pow(bits_per_idx as u32) - 1; + + if long_count != data.len() { + return Err(ToValenceError::BadBlockStateLongCount) + }; + + let mut i = 0; + + for &long in data.iter() { + let u64 = long as u64; + + for j in 0..idxs_per_long { + if i >= BLOCKS_PER_SECTION { + break; + } + + let idx = (u64 >> (bits_per_idx * j)) & mask; + + let Some(block) = converted_block_palette.get(idx as usize).cloned() else { + return Err(ToValenceError::InvalidBlockPaletteIndex) + }; + + let x = i % 16; + let z = i / 16 % 16; + let y = i / (16 * 16); + + chunk.set_block_state(x, adjusted_sect_y as usize * 16 + y, z, block); + + i += 1; + } + } + } + } + + Ok(()) +} + +const BLOCKS_PER_SECTION: usize = 4096; + +/// Gets the path part of a resource identifier. +fn ident_path(ident: &str) -> &str { + match ident.rsplit_once(':') { + Some((_, after)) => after, + None => ident, + } +} + +/// Returns the minimum number of bits needed to represent the integer `n`. +const fn bit_width(n: usize) -> usize { + (usize::BITS - n.leading_zeros()) as _ +} diff --git a/valence_anvil/tests/assets.rs b/valence_anvil/tests/assets.rs index c4fb1d6c1..0f4290d16 100644 --- a/valence_anvil/tests/assets.rs +++ b/valence_anvil/tests/assets.rs @@ -9,7 +9,7 @@ use reqwest::IntoUrl; /// Describes where to find the asset if it already has been downloaded and from /// which URL the asset can be downloaded. More asset types can be added on /// demand by modifying this enum. -pub enum WebAsset, URL: IntoUrl> { +pub enum WebAsset { ZippedDirectory { destination_path: DestinationPath, remove_top_level_dir: bool, From f685d589084abc34e2ef3d6cec48228f1f297706 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 25 Dec 2022 06:14:43 -0800 Subject: [PATCH 70/75] Add biomes --- valence_anvil/benches/world_parsing.rs | 55 ++++------- valence_anvil/examples/valence_loading.rs | 6 +- valence_anvil/src/to_valence.rs | 113 +++++++++++++++++----- 3 files changed, 113 insertions(+), 61 deletions(-) diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 10143d6e9..97db90b28 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -1,9 +1,5 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use valence::biome::BiomeId; -use valence::chunk::ChunkPos; -use valence::config::Config; -use valence::dimension::Dimension; -use valence_anvil::biome::BiomeKind; +use valence::chunk::{ChunkPos, UnloadedChunk}; use valence_anvil::AnvilWorld; criterion_group!(benches, criterion_benchmark); @@ -18,27 +14,10 @@ const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = asse "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", ); -struct BenchmarkConfig; -impl Config for BenchmarkConfig { - type ServerState = (); - type ClientState = (); - type EntityState = (); - type WorldState = (); - type ChunkState = (); - type PlayerListState = (); - type InventoryState = (); -} - fn criterion_benchmark(c: &mut Criterion) { - let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); + let world_dir = BENCHMARK_WORLD_ASSET.load_blocking_panic(); - let mut world = AnvilWorld::new::( - &Dimension::default(), - world_directory, - BiomeKind::ALL - .iter() - .map(|b| (BiomeId::default(), b.biome().unwrap())), - ); + let mut world = AnvilWorld::new(world_dir); let mut load_targets = Vec::new(); for x in -5..5 { @@ -48,18 +27,24 @@ fn criterion_benchmark(c: &mut Criterion) { } c.bench_function("Load square 10x10", |b| { - b.iter_with_setup( - || load_targets.clone().into_iter(), - |targets| { - for (chunk_pos, chunk) in world.load_chunks(black_box(targets)).unwrap() { - assert!( - chunk.is_some(), - "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world \ - generated?" - ); + b.iter(|| { + let world = black_box(&mut world); + + for z in -5..5 { + for x in -5..5 { + let nbt = world + .read_chunk(x, z) + .expect("failed to read chunk") + .expect("missing chunk at position") + .data; + + let mut chunk = UnloadedChunk::new(24); + + valence_anvil::to_valence(&nbt, &mut chunk, 4, |_| Default::default()).unwrap(); + black_box(chunk); } - }, - ); + } + }); }); } diff --git a/valence_anvil/examples/valence_loading.rs b/valence_anvil/examples/valence_loading.rs index 3390ff1f0..e31789943 100644 --- a/valence_anvil/examples/valence_loading.rs +++ b/valence_anvil/examples/valence_loading.rs @@ -123,7 +123,7 @@ impl Config for Game { client.respawn(world_id); client.set_flat(true); client.set_game_mode(GameMode::Spectator); - client.teleport([0.0, 200.0, 0.0], 0.0, 0.0); + client.teleport([0.0, 125.0, 0.0], 0.0, 0.0); client.set_player_list(server.state.clone()); if let Some(id) = &server.state { @@ -175,8 +175,8 @@ impl Config for Game { if let Err(e) = valence_anvil::to_valence( &anvil_chunk.data, &mut chunk, - 0, - |_| todo!(), + 4, + |_| BiomeId::default(), ) { eprintln!( "failed to convert chunk at ({}, {}): {e}", diff --git a/valence_anvil/src/to_valence.rs b/valence_anvil/src/to_valence.rs index 4a4cb1bc5..d1c9c4dd2 100644 --- a/valence_anvil/src/to_valence.rs +++ b/valence_anvil/src/to_valence.rs @@ -1,14 +1,13 @@ use num::integer::div_ceil; use thiserror::Error; use valence::biome::BiomeId; -use valence::chunk::{Chunk, UnloadedChunk}; +use valence::chunk::Chunk; use valence::protocol::block::{BlockKind, PropName, PropValue}; -use valence::protocol::Ident; use valence_nbt::{Compound, List, Value}; -#[derive(Debug, Error)] +#[derive(Clone, Debug, Error)] #[non_exhaustive] -pub enum ToValenceError<'a> { +pub enum ToValenceError { #[error("missing chunk sections")] MissingSections, #[error("missing chunk section Y")] @@ -20,19 +19,31 @@ pub enum ToValenceError<'a> { #[error("missing block name in palette")] MissingBlockName, #[error("unknown block name of \"{0}\"")] - UnknownBlockName(&'a str), + UnknownBlockName(String), #[error("unknown property name of \"{0}\"")] - UnknownPropName(&'a str), + UnknownPropName(String), #[error("property value of block is not a string")] BadPropValueType, #[error("unknown property value of \"{0}\"")] - UnknownPropValue(&'a str), + UnknownPropValue(String), #[error("missing packed block state data in section")] MissingBlockStateData, - #[error("unexpected number of longs in block state blob")] - BadBlockStateLongCount, + #[error("unexpected number of longs in block state data")] + BadBlockLongCount, #[error("invalid block palette index")] - InvalidBlockPaletteIndex, + BadBlockPaletteIndex, + #[error("missing biomes")] + MissingBiomes, + #[error("missing biome palette")] + MissingBiomePalette, + #[error("missing biome name")] + MissingBiomeName, + #[error("missing packed biome data in section")] + MissingBiomeData, + #[error("unexpected number of longs in biome data")] + BadBiomeLongCount, + #[error("invalid biome palette index")] + BadBiomePaletteIndex, } /// Reads an Anvil chunk in NBT form and writes its data to a Valence [`Chunk`]. @@ -43,22 +54,22 @@ pub enum ToValenceError<'a> { /// - `sect_offset`: /// /// [`read_chunk`]: crate::AnvilWorld::read_chunk -pub fn to_valence<'a, C, F>( - nbt: &'a Compound, +pub fn to_valence( + nbt: &Compound, chunk: &mut C, sect_offset: i32, - mut map_biomes: F, -) -> Result<(), ToValenceError<'a>> + mut map_biome: F, +) -> Result<(), ToValenceError> where C: Chunk, - F: FnMut(Ident<&str>) -> BiomeId, + F: FnMut(&str) -> BiomeId, { let Some(Value::List(List::Compound(sections))) = nbt.get("sections") else { return Err(ToValenceError::MissingSections) }; - // Maps palette indices to the corresponding block state in the palette. let mut converted_block_palette = vec![]; + let mut converted_biome_palette = vec![]; for section in sections { let Some(Value::Byte(sect_y)) = section.get("Y") else { @@ -88,7 +99,7 @@ where }; let Some(block_kind) = BlockKind::from_str(ident_path(name)) else { - return Err(ToValenceError::UnknownBlockName(name.as_str())) + return Err(ToValenceError::UnknownBlockName(name.into())) }; let mut state = block_kind.to_state(); @@ -100,11 +111,11 @@ where }; let Some(prop_name) = PropName::from_str(key) else { - return Err(ToValenceError::UnknownPropName(key)) + return Err(ToValenceError::UnknownPropName(key.into())) }; let Some(prop_value) = PropValue::from_str(value) else { - return Err(ToValenceError::UnknownPropValue(value)) + return Err(ToValenceError::UnknownPropValue(value.into())) }; state = state.set(prop_name, prop_value); @@ -127,11 +138,10 @@ where let mask = 2_u64.pow(bits_per_idx as u32) - 1; if long_count != data.len() { - return Err(ToValenceError::BadBlockStateLongCount) + return Err(ToValenceError::BadBlockLongCount); }; let mut i = 0; - for &long in data.iter() { let u64 = long as u64; @@ -143,7 +153,7 @@ where let idx = (u64 >> (bits_per_idx * j)) & mask; let Some(block) = converted_block_palette.get(idx as usize).cloned() else { - return Err(ToValenceError::InvalidBlockPaletteIndex) + return Err(ToValenceError::BadBlockPaletteIndex) }; let x = i % 16; @@ -156,12 +166,69 @@ where } } } + + let Some(Value::Compound(biomes)) = section.get("biomes") else { + return Err(ToValenceError::MissingBiomes) + }; + + let Some(Value::List(List::String(palette))) = biomes.get("palette") else { + return Err(ToValenceError::MissingBiomePalette) + }; + + converted_biome_palette.clear(); + + for biome_name in palette { + converted_biome_palette.push(map_biome(biome_name)); + } + + if converted_biome_palette.len() == 1 { + chunk.fill_biomes(adjusted_sect_y as usize, converted_biome_palette[0]); + } else if converted_biome_palette.len() > 1 { + let Some(Value::LongArray(data)) = biomes.get("data") else { + return Err(ToValenceError::MissingBiomeData) + }; + + let bits_per_idx = bit_width(converted_biome_palette.len() - 1); + let idxs_per_long = 64 / bits_per_idx; + let long_count = div_ceil(BIOMES_PER_SECTION, idxs_per_long); + let mask = 2_u64.pow(bits_per_idx as u32) - 1; + + if long_count != data.len() { + return Err(ToValenceError::BadBiomeLongCount); + }; + + let mut i = 0; + for &long in data.iter() { + let u64 = long as u64; + + for j in 0..idxs_per_long { + if i >= BIOMES_PER_SECTION { + break; + } + + let idx = (u64 >> (bits_per_idx * j)) & mask; + + let Some(biome) = converted_biome_palette.get(idx as usize).cloned() else { + return Err(ToValenceError::BadBiomePaletteIndex) + }; + + let x = i % 4; + let z = i / 4 % 4; + let y = i / (4 * 4); + + chunk.set_biome(x, adjusted_sect_y as usize * 4 + y, z, biome); + + i += 1; + } + } + } } Ok(()) } -const BLOCKS_PER_SECTION: usize = 4096; +const BLOCKS_PER_SECTION: usize = 16 * 16 * 16; +const BIOMES_PER_SECTION: usize = 4 * 4 * 4; /// Gets the path part of a resource identifier. fn ident_path(ident: &str) -> &str { From ee46b3f85f6305c06e58cfeb5e68ea5afac961a6 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 26 Dec 2022 02:42:31 -0800 Subject: [PATCH 71/75] Clean up asset loading, remove biome generator --- valence_anvil/Cargo.toml | 4 +- valence_anvil/benches/world_parsing.rs | 123 +++++- valence_anvil/build/biome.rs | 431 ---------------------- valence_anvil/build/main.rs | 38 -- valence_anvil/examples/valence_loading.rs | 44 +-- valence_anvil/src/to_valence.rs | 12 + valence_anvil/tests/assets.rs | 178 --------- valence_anvil/tests/parse_world.rs | 51 --- 8 files changed, 137 insertions(+), 744 deletions(-) delete mode 100644 valence_anvil/build/biome.rs delete mode 100644 valence_anvil/build/main.rs delete mode 100644 valence_anvil/tests/assets.rs delete mode 100644 valence_anvil/tests/parse_world.rs diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 41e2d3ae6..3c10f7c34 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -8,7 +8,6 @@ license = "MIT" keywords = ["anvil", "minecraft", "deserialization"] version = "0.1.0" authors = ["Ryan Johnson ", "TerminatorNL "] -build = "build/main.rs" edition = "2021" [dependencies] @@ -20,12 +19,13 @@ valence = { version = "0.1.0", path = "..", optional = true } valence_nbt = { version = "0.5.0", path = "../valence_nbt" } [dev-dependencies] +anyhow = "1.0.68" criterion = "0.4.0" fs_extra = "1.2.0" tempfile = "3.3.0" -zip = "0.6.3" valence = { version = "0.1.0", path = ".." } valence_anvil = { version = "0.1.0", path = ".", features = ["valence"] } +zip = "0.6.3" [dev-dependencies.reqwest] version = "0.11.12" diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 97db90b28..094cb813e 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -1,31 +1,26 @@ +use std::fs::create_dir_all; +use std::path::{Path, PathBuf}; + +use anyhow::{ensure, Context}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use valence::chunk::{ChunkPos, UnloadedChunk}; +use fs_extra::dir::CopyOptions; +use reqwest::IntoUrl; +use valence::chunk::UnloadedChunk; use valence_anvil::AnvilWorld; +use zip::ZipArchive; criterion_group!(benches, criterion_benchmark); criterion_main!(benches); -#[path = "../tests/assets.rs"] -pub mod assets; - -const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( - "1.19.2 benchmark world", - true, - "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", -); - fn criterion_benchmark(c: &mut Criterion) { - let world_dir = BENCHMARK_WORLD_ASSET.load_blocking_panic(); + let world_dir = get_world_asset( + "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", + "1.19.2 benchmark world", + true + ).expect("failed to get world asset"); let mut world = AnvilWorld::new(world_dir); - let mut load_targets = Vec::new(); - for x in -5..5 { - for z in -5..5 { - load_targets.push(ChunkPos::new(x, z)); - } - } - c.bench_function("Load square 10x10", |b| { b.iter(|| { let world = black_box(&mut world); @@ -48,3 +43,95 @@ fn criterion_benchmark(c: &mut Criterion) { }); }); } + +/// Loads the asset. If the asset is already present on the system due to a +/// prior run, the cached asset is used instead. If the asset is not +/// cached yet, this function downloads the asset using the current thread. +/// This will block until the download is complete. +/// +/// returns: `PathBuf` The reference to the asset on the file system +fn get_world_asset( + url: impl IntoUrl, + dest_path: impl AsRef, + remove_top_level_dir: bool, +) -> anyhow::Result { + let url = url.into_url()?; + let dest_path = dest_path.as_ref(); + + let asset_cache_dir = Path::new(".asset_cache"); + + create_dir_all(&asset_cache_dir).context("unable to create `.asset_cache` directory")?; + + let final_path = asset_cache_dir.join(dest_path); + + if final_path.exists() { + return Ok(final_path); + } + + let mut response = reqwest::blocking::get(url.clone())?; + + let cache_download_directory = asset_cache_dir.join("downloads"); + + create_dir_all(&cache_download_directory) + .context("unable to create `.asset_cache/downloads` directory")?; + + let mut downloaded_zip_file = + tempfile::tempfile_in(&cache_download_directory).context("Could not create temp file")?; + + println!("Downloading {dest_path:?} from {url}"); + + response + .copy_to(&mut downloaded_zip_file) + .context("could not write web contents to the temporary file")?; + + let mut zip_archive = ZipArchive::new(downloaded_zip_file) + .context("unable to create zip archive from downloaded content")?; + + if !remove_top_level_dir { + zip_archive + .extract(&final_path) + .context("unable to unzip downloaded contents")?; + + return Ok(final_path); + } + + let temp_dir = tempfile::tempdir_in(&cache_download_directory) + .context("unable to create temporary directory in `.asset_cache`")?; + + zip_archive + .extract(&temp_dir) + .context("unable to unzip downloaded contents")?; + + let mut entries = temp_dir.path().read_dir()?.into_iter(); + + let top_level_dir = entries + .next() + .context("the downloaded zip file was empty")??; + + ensure!( + entries.next().is_none(), + "found more than one entry in the top level directory of the Zip file" + ); + + ensure!( + top_level_dir.path().is_dir(), + "the only content in the zip archive is a file" + ); + + create_dir_all(&final_path).context("could not create a directory inside the asset cache")?; + + let dir_entries = top_level_dir + .path() + .read_dir()? + .collect::, _>>()?; + + let items_to_move: Vec<_> = dir_entries.into_iter().map(|d| d.path()).collect(); + + fs_extra::move_items(&items_to_move, &final_path, &CopyOptions::new())?; + + // We keep the temporary directory around until we're done moving files out + // of it. + drop(temp_dir); + + Ok(final_path) +} diff --git a/valence_anvil/build/biome.rs b/valence_anvil/build/biome.rs deleted file mode 100644 index e588e620a..000000000 --- a/valence_anvil/build/biome.rs +++ /dev/null @@ -1,431 +0,0 @@ -use std::collections::{BTreeMap, HashMap}; -use std::fmt; - -use heck::{ToPascalCase, ToSnakeCase}; -use proc_macro2::{Ident as TokenIdent, TokenStream}; -use quote::{quote, ToTokens}; -use serde::de::Visitor; -use serde::{Deserialize, Deserializer}; - -use crate::ident; - -#[derive(Deserialize, Debug)] -struct ParsedElement { - id: u16, - name: ParsedName, - element: ParsedBiome, -} - -#[derive(Deserialize, Debug)] -struct ParsedBiome { - precipitation: ParsedName, - temperature: f32, - downfall: f32, - effects: ParsedBiomeEffects, - particle: Option, - spawn_settings: ParsedBiomeSpawnRates, -} - -#[derive(Deserialize, Debug)] -struct ParsedBiomeEffects { - sky_color: u32, - water_fog_color: u32, - fog_color: u32, - water_color: u32, - grass_color_modifier: ParsedName, - grass_color: Option, - foliage_color: Option, - music: Option, - ambient_sound: Option, - additions_sound: Option, - mood_sound: Option, -} - -#[derive(Deserialize, Debug)] -struct ParsedMusic { - replace_current_music: bool, - sound: ParsedName, - max_delay: i32, - min_delay: i32, -} - -#[derive(Deserialize, Debug)] -struct ParsedAdditionsMusic { - sound: ParsedName, - tick_chance: f64, -} - -#[derive(Deserialize, Debug)] -struct ParsedMoodSound { - sound: ParsedName, - tick_delay: i32, - offset: f64, - block_search_extent: i32, -} - -#[derive(Deserialize, Debug)] -struct ParsedParticle { - kind: ParsedName, - probability: f32, -} - -impl ToTokens for ParsedMusic { - fn to_tokens(&self, tokens: &mut TokenStream) { - let replace_current_music = &self.replace_current_music; - let sound = &self.sound.raw; - let min_delay = &self.min_delay; - let max_delay = &self.max_delay; - quote! ( - BiomeMusic { - replace_current_music: #replace_current_music, - sound: Ident::from_str(#sound)?, - min_delay: #min_delay, - max_delay: #max_delay - } - ) - .to_tokens(tokens) - } -} - -impl ToTokens for ParsedAdditionsMusic { - fn to_tokens(&self, tokens: &mut TokenStream) { - let sound = &self.sound.raw; - let tick_chance = &self.tick_chance; - quote! ( - BiomeAdditionsSound { - sound: Ident::from_str(#sound)?, - tick_chance: #tick_chance, - } - ) - .to_tokens(tokens) - } -} - -impl ToTokens for ParsedMoodSound { - fn to_tokens(&self, tokens: &mut TokenStream) { - let sound = &self.sound.raw; - let block_search_extent = &self.block_search_extent; - let offset = &self.offset; - let tick_delay = &self.tick_delay; - quote! ( - BiomeMoodSound { - sound: Ident::from_str(#sound)?, - block_search_extent: #block_search_extent, - offset: #offset, - tick_delay: #tick_delay - } - ) - .to_tokens(tokens) - } -} - -impl ToTokens for ParsedParticle { - fn to_tokens(&self, tokens: &mut TokenStream) { - let kind = &self.kind.raw; - let probability = &self.probability; - quote! ( - BiomeParticle { - kind: Ident::from_str(#kind)?, - probability: #probability - } - ) - .to_tokens(tokens) - } -} - -#[derive(Deserialize, Debug)] -struct ParsedBiomeSpawnRates { - probability: f32, - groups: HashMap>, -} - -#[derive(Deserialize, Debug)] -struct ParsedSpawnRate { - name: ParsedName, - min_group_size: u32, - max_group_size: u32, - weight: i32, -} - -#[derive(Debug)] -struct ParsedName { - token: TokenIdent, - raw: String, -} - -impl<'de> Deserialize<'de> for ParsedName { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct IdentVisitor; - impl<'de> Visitor<'de> for IdentVisitor { - type Value = ParsedName; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string containing a minecraft identifier path") - } - fn visit_str(self, identifier: &str) -> Result { - Ok(ParsedName { - token: ident(identifier.to_pascal_case()), - raw: identifier.to_string(), - }) - } - } - deserializer.deserialize_str(IdentVisitor) - } -} - -pub fn build() -> anyhow::Result { - let mut biomes: Vec = - serde_json::from_str(include_str!("../../extracted/biomes.json"))?; - - //Ensure biomes are sorted, even if the JSON changes later. - biomes.sort_by(|one, two| one.id.cmp(&two.id)); - - let mut class_spawn_fields = BTreeMap::<&str, TokenIdent>::new(); - for biome in biomes.iter().map(|b| &b.element) { - for class in biome.spawn_settings.groups.keys() { - class_spawn_fields - .entry(class) - .or_insert_with(|| ident(class.to_snake_case())); - } - } - - fn option_to_quote(input: &Option) -> TokenStream { - match input { - Some(value) => quote!(Some(#value)), - None => quote!(None), - } - } - - let biome_kind_enum_declare = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let id = biome.id as isize; - quote! { - #name = #id, - } - }) - .collect::(); - - let biome_kind_enum_names = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - quote! { - #name - } - }) - .collect::>(); - - let biomekind_id_to_variant_lookup = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let id = &biome.id; - quote! { - #id => Some(Self::#name), - } - }) - .collect::(); - - let biomekind_name_lookup = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let raw = &biome.name.raw; - quote! { - #raw => Some(Self::#name), - } - }) - .collect::(); - - let biomekind_temperatures_arms = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let temp = &biome.element.temperature; - quote! { - Self::#name => #temp, - } - }) - .collect::(); - - let biomekind_downfall_arms = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let downfall = &biome.element.downfall; - quote! { - Self::#name => #downfall, - } - }) - .collect::(); - - let biomekind_to_biome = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let raw_name = &biome.name.raw; - let precipitation = &biome.element.precipitation.token; - let sky_color = &biome.element.effects.sky_color; - let water_fog = &biome.element.effects.water_fog_color; - let fog = &biome.element.effects.fog_color; - let water_color = &biome.element.effects.water_color; - let foliage_color = option_to_quote(&biome.element.effects.foliage_color); - let grass_color = option_to_quote(&biome.element.effects.grass_color); - let grass_modifier = &biome.element.effects.grass_color_modifier.token; - let music = option_to_quote(&biome.element.effects.music); - let ambient_sound = option_to_quote({ - &biome.element.effects.ambient_sound.as_ref().map(|n| { - let raw = &n.raw; - quote!(Ident::from_str(#raw)?) - }) - }); - let additions_sound = option_to_quote(&biome.element.effects.additions_sound); - let mood_sound = option_to_quote(&biome.element.effects.mood_sound); - let particle = option_to_quote(&biome.element.particle); - quote! { - Self::#name => Ok(Biome{ - name: Ident::from_str(#raw_name)?, - precipitation: BiomePrecipitation::#precipitation, - sky_color: #sky_color, - water_fog_color: #water_fog, - fog_color: #fog, - water_color: #water_color, - foliage_color: #foliage_color, - grass_color: #grass_color, - grass_color_modifier: BiomeGrassColorModifier::#grass_modifier, - music: #music, - ambient_sound: #ambient_sound, - additions_sound: #additions_sound, - mood_sound: #mood_sound, - particle: #particle, - }), - } - }) - .collect::(); - - let biomekind_spawn_settings_arms = biomes - .iter() - .map(|biome| { - let name = &biome.name.token; - let probability = biome.element.spawn_settings.probability; - - let fields = biome - .element - .spawn_settings - .groups - .iter() - .map(|(class, rates)| { - let rates = rates.iter().map(|spawn_rate| { - let name_raw = &spawn_rate.name.raw; - let min_group_size = &spawn_rate.min_group_size; - let max_group_size = &spawn_rate.max_group_size; - let weight = &spawn_rate.weight; - quote! { - SpawnProperty { - name: #name_raw, - min_group_size: #min_group_size, - max_group_size: #max_group_size, - weight: #weight - } - } - }); - let class = ident(class); - quote! { - #class: &[#( #rates ),*] - } - }); - quote! { - Self::#name => SpawnSettings { - probability: #probability, - #( #fields ),* - }, - } - }) - .collect::(); - - let spawn_classes = class_spawn_fields.values(); - - Ok(quote! { - use valence::biome::{Biome, BiomeMusic, BiomeAdditionsSound, BiomeMoodSound, BiomeParticle, BiomeGrassColorModifier, BiomePrecipitation}; - use valence::protocol::ident::{Ident, IdentError}; - use std::str::FromStr; - - #[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] - pub struct SpawnProperty { - pub name: &'static str, - pub min_group_size: u32, - pub max_group_size: u32, - pub weight: i32 - } - - #[derive(Debug, Clone, PartialEq, PartialOrd)] - pub struct SpawnSettings { - pub probability: f32, - #( pub #spawn_classes: &'static [SpawnProperty] ),* - } - - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum BiomeKind { - #biome_kind_enum_declare - } - - impl BiomeKind { - /// All imported vanilla biomes (All variants of `BiomeKind`) - pub const ALL: &'static [Self] = &[#(Self::#biome_kind_enum_names),*]; - - /// Constructs an `BiomeKind` from a raw biome ID. - /// - /// If the given ID is invalid, `None` is returned. - pub const fn from_raw(id: u16) -> Option { - match id { - #biomekind_id_to_variant_lookup - _ => None - } - } - - /// Returns the raw biome ID. - pub const fn to_raw(self) -> u16 { - self as u16 - } - - pub fn from_ident>(ident: &Ident) -> Option { - if ident.namespace() != "minecraft" { - return None; - } - match ident.path() { - #biomekind_name_lookup - _ => None - } - } - - pub fn biome(self) -> Result> { - match self { - #biomekind_to_biome - } - } - - /// Gets the biome spawn rates - pub const fn spawn_rates(self) -> SpawnSettings { - match self { - #biomekind_spawn_settings_arms - } - } - - pub const fn temperature(self) -> f32 { - match self { - #biomekind_temperatures_arms - } - } - - pub const fn downfall(self) -> f32 { - match self { - #biomekind_downfall_arms - } - } - } - }) -} diff --git a/valence_anvil/build/main.rs b/valence_anvil/build/main.rs deleted file mode 100644 index 92c555f2d..000000000 --- a/valence_anvil/build/main.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::path::Path; -use std::process::Command; -use std::{env, fs}; - -use anyhow::Context; -use proc_macro2::{Ident as TokenIdent, Span}; - -mod biome; - -pub fn main() -> anyhow::Result<()> { - println!("cargo:rerun-if-changed=extracted/"); - - let generators = [(biome::build, "biome.rs")]; - - let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?; - - for (g, file_name) in generators { - let path = Path::new(&out_dir).join(file_name); - let code = g()?.to_string(); - fs::write(&path, code)?; - - // Format the output for debugging purposes. - // Doesn't matter if rustfmt is unavailable. - let _ = Command::new("rustfmt").arg(path).output(); - } - - Ok(()) -} - -fn ident(s: impl AsRef) -> TokenIdent { - let s = s.as_ref().trim(); - - match s.as_bytes() { - // TODO: check for the other rust keywords. - [b'0'..=b'9', ..] | b"type" => TokenIdent::new(&format!("_{s}"), Span::call_site()), - _ => TokenIdent::new(s, Span::call_site()), - } -} diff --git a/valence_anvil/examples/valence_loading.rs b/valence_anvil/examples/valence_loading.rs index e31789943..d0edeec91 100644 --- a/valence_anvil/examples/valence_loading.rs +++ b/valence_anvil/examples/valence_loading.rs @@ -1,3 +1,10 @@ +//! # IMPORTANT +//! +//! Run this example with one argument containing the path of the the following +//! to the world directory you wish to load. Inside this directory you can +//! commonly see `advancements`, `DIM1`, `DIM-1` and most importantly `region` +//! subdirectories. Only the `region` directory is accessed. + extern crate valence; use std::env; @@ -6,28 +13,21 @@ use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; use valence::prelude::*; -// use valence_anvil::biome::BiomeKind; use valence_anvil::AnvilWorld; -/// # IMPORTANT -/// -/// Run this example with one argument containing the path of the the following -/// to the world directory you wish to load. Inside this directory you can -/// commonly see `advancements`, `DIM1`, `DIM-1` and most importantly `region` -/// subdirectories. Only the `region` directory is accessed. pub fn main() -> ShutdownResult { let Some(world_dir) = env::args().nth(1) else { - return Err("Please add the world directory as program argument.".into()) + return Err("please add the world directory as program argument.".into()) }; let world_dir = PathBuf::from(world_dir); if !world_dir.exists() || !world_dir.is_dir() { - return Err("World argument must be a directory that exists".into()) + return Err("world argument must be a directory that exists".into()); } if !world_dir.join("region").exists() { - return Err("Could not find the \"region\" directory in the given world directory".into()) + return Err("could not find the \"region\" directory in the given world directory".into()); } valence::start_server( @@ -63,10 +63,6 @@ impl Config for Game { type PlayerListState = (); type InventoryState = (); - // fn biomes(&self) -> Vec { - // BiomeKind::ALL.iter().map(|b| b.biome().unwrap()).collect() - // } - async fn server_list_ping( &self, _server: &SharedServer, @@ -87,7 +83,7 @@ impl Config for Game { } fn init(&self, server: &mut Server) { - for (id, dimension) in server.shared.dimensions() { + for (id, _) in server.shared.dimensions() { server.worlds.insert(id, AnvilWorld::new(&self.world_dir)); } server.state = Some(server.player_lists.insert(()).0); @@ -172,16 +168,12 @@ impl Config for Game { Ok(Some(anvil_chunk)) => { let mut chunk = UnloadedChunk::new(24); - if let Err(e) = valence_anvil::to_valence( - &anvil_chunk.data, - &mut chunk, - 4, - |_| BiomeId::default(), - ) { - eprintln!( - "failed to convert chunk at ({}, {}): {e}", - pos.x, pos.z - ); + if let Err(e) = + valence_anvil::to_valence(&anvil_chunk.data, &mut chunk, 4, |_| { + BiomeId::default() + }) + { + eprintln!("Failed to convert chunk at ({}, {}): {e}", pos.x, pos.z); } world.chunks.insert(pos, chunk, true); @@ -191,7 +183,7 @@ impl Config for Game { world.chunks.insert(pos, UnloadedChunk::default(), true); } Err(e) => { - eprintln!("failed to read chunk at ({}, {}): {e}", pos.x, pos.z) + eprintln!("Failed to read chunk at ({}, {}): {e}", pos.x, pos.z) } } } diff --git a/valence_anvil/src/to_valence.rs b/valence_anvil/src/to_valence.rs index d1c9c4dd2..459cd309e 100644 --- a/valence_anvil/src/to_valence.rs +++ b/valence_anvil/src/to_valence.rs @@ -16,6 +16,8 @@ pub enum ToValenceError { MissingBlockStates, #[error("missing block palette")] MissingBlockPalette, + #[error("invalid block palette length")] + BadBlockPaletteLen, #[error("missing block name in palette")] MissingBlockName, #[error("unknown block name of \"{0}\"")] @@ -36,6 +38,8 @@ pub enum ToValenceError { MissingBiomes, #[error("missing biome palette")] MissingBiomePalette, + #[error("invalid biome palette length")] + BadBiomePaletteLen, #[error("missing biome name")] MissingBiomeName, #[error("missing packed biome data in section")] @@ -91,6 +95,10 @@ where return Err(ToValenceError::MissingBlockPalette) }; + if !(1..BLOCKS_PER_SECTION).contains(&palette.len()) { + return Err(ToValenceError::BadBlockPaletteLen); + } + converted_block_palette.clear(); for block in palette { @@ -175,6 +183,10 @@ where return Err(ToValenceError::MissingBiomePalette) }; + if !(1..BIOMES_PER_SECTION).contains(&palette.len()) { + return Err(ToValenceError::BadBiomePaletteLen); + } + converted_biome_palette.clear(); for biome_name in palette { diff --git a/valence_anvil/tests/assets.rs b/valence_anvil/tests/assets.rs deleted file mode 100644 index 0f4290d16..000000000 --- a/valence_anvil/tests/assets.rs +++ /dev/null @@ -1,178 +0,0 @@ -use std::fs::{create_dir_all, DirEntry}; -use std::io; -use std::path::{Path, PathBuf}; -use std::str::FromStr; - -use fs_extra::dir::CopyOptions; -use reqwest::IntoUrl; - -/// Describes where to find the asset if it already has been downloaded and from -/// which URL the asset can be downloaded. More asset types can be added on -/// demand by modifying this enum. -pub enum WebAsset { - ZippedDirectory { - destination_path: DestinationPath, - remove_top_level_dir: bool, - url: URL, - }, -} - -impl, URL: IntoUrl + Clone> WebAsset { - /// Creates a ZippedDirectory asset type. - /// - /// # Arguments - /// - /// * `destination_path`: A unique path for this asset. If the path is - /// relative, it will be placed under the `.asset_cache` directory. - /// Relative paths are recommended. - /// * `remove_top_level_dir`: Some zip files wrap all their contents in an - /// additional folder. Setting this value to `true` will remove that - /// redundant directory. If the Zip file contains multiple - /// files/directories in the root, this will cause a panic. - /// * `url`: The URL from which to download the Zip file. - /// - /// returns: `WebAsset` The created asset. - /// - /// # Examples - /// - /// ``` - /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( - /// "BenchmarkWorld", - /// true, - /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", - /// ); - /// ``` - pub const fn zipped_directory( - destination_path: DestinationPath, - remove_top_level_dir: bool, - url: URL, - ) -> Self { - Self::ZippedDirectory { - destination_path, - remove_top_level_dir, - url, - } - } - - fn url(&self) -> URL { - match self { - WebAsset::ZippedDirectory { url, .. } => url.clone(), - } - } - - fn destination_path(&self) -> &DestinationPath { - match self { - WebAsset::ZippedDirectory { - destination_path: directory_name, - .. - } => directory_name, - } - } - - /// Loads the asset. If the asset is already present on the system due to a - /// prior run, the cached asset is used instead. If the asset is not - /// cached yet, this function downloads the asset using the current thread. - /// This will block until the download is complete. - /// - /// returns: `PathBuf` The reference to the asset on the file system - /// - /// # Examples - /// - /// ``` - /// const BENCHMARK_WORLD_ASSET: benchtools::WebAsset<&'static str, &'static str> = benchtools::WebAsset::zipped_directory( - /// "BenchmarkWorld", - /// true, - /// "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", - /// ); - /// let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); - /// ``` - pub fn load_blocking_panic(&self) -> PathBuf { - let asset_cache_dir = PathBuf::from_str(".asset_cache").unwrap(); - create_dir_all(&asset_cache_dir).expect("Unable to create `.asset_cache` directory"); - let final_path = asset_cache_dir.join(self.destination_path()); - if final_path.exists() { - return final_path; - } - - let mut request = reqwest::blocking::get(self.url()) - .expect("File download request failed") - .error_for_status() - .unwrap(); - - let cache_download_directory = asset_cache_dir.join("downloads"); - create_dir_all(&cache_download_directory) - .expect("Unable to create `.asset_cache/downloads` directory"); - - let mut downloaded_zip_file = tempfile::tempfile_in(&cache_download_directory) - .expect("Could not create the temporary file"); - - println!( - "Downloading {:?} from {}", - self.destination_path().as_ref(), - self.url().as_str() - ); - request - .copy_to(&mut downloaded_zip_file) - .expect("Could not write web contents to the temporary file"); - - match self { - WebAsset::ZippedDirectory { - remove_top_level_dir: remove_single_top_level_dir, - .. - } => { - let mut zip_archive = zip::ZipArchive::new(downloaded_zip_file) - .expect("unable to create zip archive from downloaded content"); - if *remove_single_top_level_dir { - let temporary_directory = tempfile::tempdir_in(&cache_download_directory) - .expect("Unable to create temporary directory in `.asset_cache`"); - zip_archive - .extract(&temporary_directory) - .expect("Unable to unzip downloaded contents"); - let mut entries: Vec> = temporary_directory - .path() - .read_dir() - .expect("Could not read the contents of the temporary directory") - .into_iter() - .collect(); - if let Some(top_level_directory) = entries.pop() { - assert_eq!( - entries.len(), - 0, - "Found more than one entry in the top level directory of the Zip file." - ); - let top_level_directory = top_level_directory.unwrap(); - let top_level_directory = top_level_directory.path(); - assert!( - top_level_directory.is_dir(), - "The only content in the Zip is a file!" - ); - create_dir_all(&final_path) - .expect("Could not create a directory inside the asset cache"); - fs_extra::move_items( - top_level_directory - .read_dir() - .unwrap() - .map(|v| v.unwrap().path()) - .collect::>() - .as_slice(), - &final_path, - &CopyOptions::new(), - ) - .unwrap(); - // We keep the temporary directory around until we're done moving files out - // of it. - drop(temporary_directory); - final_path - } else { - panic!("The downloaded zip file was empty"); - } - } else { - zip_archive - .extract(&final_path) - .expect("Unable to unzip downloaded contents"); - final_path - } - } - } - } -} diff --git a/valence_anvil/tests/parse_world.rs b/valence_anvil/tests/parse_world.rs deleted file mode 100644 index 222675547..000000000 --- a/valence_anvil/tests/parse_world.rs +++ /dev/null @@ -1,51 +0,0 @@ -use valence::biome::BiomeId; -use valence::chunk::ChunkPos; -use valence::config::Config; -use valence::prelude::Dimension; -use valence_anvil::biome::BiomeKind; -use valence_anvil::AnvilWorld; - -#[path = "../tests/assets.rs"] -pub mod assets; - -const BENCHMARK_WORLD_ASSET: assets::WebAsset<&'static str, &'static str> = assets::WebAsset::zipped_directory( - "1.19.2 benchmark world", - true, - "https://github.com/valence-rs/valence-test-data/archive/refs/heads/asset/sp_world_1.19.2.zip", -); - -struct TestConfig; -impl Config for TestConfig { - type ServerState = (); - type ClientState = (); - type EntityState = (); - type WorldState = (); - type ChunkState = (); - type PlayerListState = (); - type InventoryState = (); -} - -#[test] -pub fn parse_world() { - let world_directory = BENCHMARK_WORLD_ASSET.load_blocking_panic(); - let mut world = AnvilWorld::new::( - &Dimension::default(), - world_directory, - BiomeKind::ALL - .iter() - .map(|b| (BiomeId::default(), b.biome().unwrap())), - ); - let mut load_targets = Vec::new(); - for x in -5..5 { - for z in -5..5 { - load_targets.push(ChunkPos::new(x, z)); - } - } - - for (chunk_pos, chunk) in world.load_chunks(load_targets.into_iter()).unwrap() { - assert!( - chunk.is_some(), - "Chunk at {chunk_pos:?} returned 'None'. Is this section of the world generated?" - ); - } -} From 7728e466a83ce240107afd532022325514f783c8 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 26 Dec 2022 02:50:31 -0800 Subject: [PATCH 72/75] Fix chunk test --- src/chunk.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/chunk.rs b/src/chunk.rs index 10f77ba5f..7afbaed41 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -1085,8 +1085,14 @@ mod tests { check_invariants(&loaded.sections); check_invariants(&unloaded.sections); - loaded.fill_block_states(rand_block_state(&mut rng)); - unloaded.fill_block_states(rand_block_state(&mut rng)); + loaded.fill_block_states( + rng.gen_range(0..loaded.section_count()), + rand_block_state(&mut rng), + ); + unloaded.fill_block_states( + rng.gen_range(0..loaded.section_count()), + rand_block_state(&mut rng), + ); check_invariants(&loaded.sections); check_invariants(&unloaded.sections); From f5ece9f2e249876aaadbae13e14267a6b65df736 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 26 Dec 2022 03:27:56 -0800 Subject: [PATCH 73/75] Clean up docs and Cargo.toml --- valence_anvil/Cargo.toml | 12 +----------- valence_anvil/src/lib.rs | 5 +++-- valence_anvil/src/to_valence.rs | 31 +++++++++++++++++++++++++------ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/valence_anvil/Cargo.toml b/valence_anvil/Cargo.toml index 3c10f7c34..a50e855ca 100644 --- a/valence_anvil/Cargo.toml +++ b/valence_anvil/Cargo.toml @@ -14,7 +14,7 @@ edition = "2021" byteorder = "1.4.3" flate2 = "1.0.25" thiserror = "1.0.37" -num = "0.4.0" # TODO: remove when div_ceil is stabilized. +num-integer = "0.1.45" # TODO: remove when div_ceil is stabilized. valence = { version = "0.1.0", path = "..", optional = true } valence_nbt = { version = "0.5.0", path = "../valence_nbt" } @@ -36,13 +36,3 @@ features = ["rustls-tls", "blocking", "stream"] [[bench]] name = "world_parsing" harness = false - -[build-dependencies] -anyhow = "1.0.65" -heck = "0.4.0" -proc-macro2 = "1.0.43" -quote = "1.0.21" -serde = { version = "1.0.145", features = ["derive"] } -serde_json = "1.0.85" -rayon = "1.5.3" -num = "0.4.0" diff --git a/valence_anvil/src/lib.rs b/valence_anvil/src/lib.rs index 55d904330..96a2b8da7 100644 --- a/valence_anvil/src/lib.rs +++ b/valence_anvil/src/lib.rs @@ -52,8 +52,7 @@ pub enum ReadChunkError { #[derive(Debug)] struct Region { file: File, - /// The first 8 KiB in the file. The header in the file and the in-memory - /// header must be kept in sync when writes occur. + /// The first 8 KiB in the file. header: [u8; SECTOR_SIZE * 2], } @@ -70,6 +69,8 @@ impl AnvilWorld { } } + /// Reads a chunk from the file system with the given chunk coordinates. If + /// no chunk exists at the position, then `None` is returned. pub fn read_chunk( &mut self, chunk_x: i32, diff --git a/valence_anvil/src/to_valence.rs b/valence_anvil/src/to_valence.rs index 459cd309e..0537cb27f 100644 --- a/valence_anvil/src/to_valence.rs +++ b/valence_anvil/src/to_valence.rs @@ -1,8 +1,9 @@ -use num::integer::div_ceil; +use num_integer::div_ceil; use thiserror::Error; use valence::biome::BiomeId; use valence::chunk::Chunk; use valence::protocol::block::{BlockKind, PropName, PropValue}; +use valence::protocol::Ident; use valence_nbt::{Compound, List, Value}; #[derive(Clone, Debug, Error)] @@ -40,6 +41,8 @@ pub enum ToValenceError { MissingBiomePalette, #[error("invalid biome palette length")] BadBiomePaletteLen, + #[error("biome name is not a valid resource identifier")] + BadBiomeName, #[error("missing biome name")] MissingBiomeName, #[error("missing packed biome data in section")] @@ -51,11 +54,19 @@ pub enum ToValenceError { } /// Reads an Anvil chunk in NBT form and writes its data to a Valence [`Chunk`]. +/// An error is returned if the NBT data does not match the expected structure +/// for an Anvil chunk. +/// +/// # Arguments /// /// - `nbt`: The Anvil chunk to read from. This is usually the value returned by /// [`read_chunk`]. /// - `chunk`: The Valence chunk to write to. -/// - `sect_offset`: +/// - `sect_offset`: A constant to add to all sector Y positions in `nbt`. After +/// applying the offset, only the sectors in the range +/// `0..chunk.sector_count()` are written. +/// - `map_biome`: A function to map biome resource identifiers in the NBT data +/// to Valence [`BiomeId`]s. /// /// [`read_chunk`]: crate::AnvilWorld::read_chunk pub fn to_valence( @@ -66,7 +77,7 @@ pub fn to_valence( ) -> Result<(), ToValenceError> where C: Chunk, - F: FnMut(&str) -> BiomeId, + F: FnMut(Ident<&str>) -> BiomeId, { let Some(Value::List(List::Compound(sections))) = nbt.get("sections") else { return Err(ToValenceError::MissingSections) @@ -135,7 +146,9 @@ where if converted_block_palette.len() == 1 { chunk.fill_block_states(adjusted_sect_y as usize, converted_block_palette[0]); - } else if converted_block_palette.len() > 1 { + } else { + debug_assert!(converted_block_palette.len() > 1); + let Some(Value::LongArray(data)) = block_states.get("data") else { return Err(ToValenceError::MissingBlockStateData) }; @@ -190,12 +203,18 @@ where converted_biome_palette.clear(); for biome_name in palette { - converted_biome_palette.push(map_biome(biome_name)); + let Ok(ident) = Ident::new(biome_name.as_str()) else { + return Err(ToValenceError::BadBiomeName) + }; + + converted_biome_palette.push(map_biome(ident)); } if converted_biome_palette.len() == 1 { chunk.fill_biomes(adjusted_sect_y as usize, converted_biome_palette[0]); - } else if converted_biome_palette.len() > 1 { + } else { + debug_assert!(converted_biome_palette.len() > 1); + let Some(Value::LongArray(data)) = biomes.get("data") else { return Err(ToValenceError::MissingBiomeData) }; From 7db13e7439cb7c6ddd1f9e7697b759ce17bd21b1 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 26 Dec 2022 06:15:48 -0800 Subject: [PATCH 74/75] Fix docs --- src/chunk.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/chunk.rs b/src/chunk.rs index 7afbaed41..81712be02 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -110,7 +110,8 @@ impl Chunks { } /// Returns the height of all loaded chunks in the world. This returns the - /// same value as [`Chunk::height`] for all loaded chunks. + /// same value as [`Chunk::section_count`] multiplied by 16 for all loaded + /// chunks. pub fn height(&self) -> usize { self.dimension_height as usize } From d21be976f672a13759ef10f64ab1018b0a78542a Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 26 Dec 2022 06:27:17 -0800 Subject: [PATCH 75/75] Fix lints --- valence_anvil/benches/world_parsing.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/valence_anvil/benches/world_parsing.rs b/valence_anvil/benches/world_parsing.rs index 094cb813e..b586d05a6 100644 --- a/valence_anvil/benches/world_parsing.rs +++ b/valence_anvil/benches/world_parsing.rs @@ -60,7 +60,7 @@ fn get_world_asset( let asset_cache_dir = Path::new(".asset_cache"); - create_dir_all(&asset_cache_dir).context("unable to create `.asset_cache` directory")?; + create_dir_all(asset_cache_dir).context("unable to create `.asset_cache` directory")?; let final_path = asset_cache_dir.join(dest_path); @@ -102,7 +102,7 @@ fn get_world_asset( .extract(&temp_dir) .context("unable to unzip downloaded contents")?; - let mut entries = temp_dir.path().read_dir()?.into_iter(); + let mut entries = temp_dir.path().read_dir()?; let top_level_dir = entries .next()