Skip to content

Commit

Permalink
Generate biome mappings - resolves #119
Browse files Browse the repository at this point in the history
Mappings are generated for both identifiers (e.g. minecraft:plains) and protocol IDs.

Note that the biomes are generated from the 1.14 registries.json file, which contains
two biomes that don't exist in 1.13.2. The mappings generator skips these biomes.
  • Loading branch information
caelunshun committed Sep 8, 2019
1 parent 26ffbab commit 6e75819
Show file tree
Hide file tree
Showing 8 changed files with 551 additions and 5 deletions.
5 changes: 3 additions & 2 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ coverage:
patch:
default:
threshold: 1.5
target: 25
target: 0

ignore:
- "blocks/src/blocks.rs"
- "generator"
- "items/src/item.rs"
- "item_block/src/mappings.rs"
- "core/src/biomes.rs"
- "generator"
- "codegen" # No way to run codecov on procedural macros, unfortunately
390 changes: 390 additions & 0 deletions core/src/biomes.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern crate strum_macros;

extern crate nalgebra_glm as glm;

mod biomes;
pub mod bytebuf;
pub mod entitymeta;
pub mod inventory;
Expand All @@ -28,6 +29,7 @@ mod save;
#[macro_use]
pub mod world;

pub use biomes::Biome;
pub use entitymeta::EntityMetadata;
pub use feather_items as item;
pub use inventory::{ItemStack, Slot};
Expand Down
4 changes: 2 additions & 2 deletions core/src/network/packet/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::inventory::ItemStack;
use crate::network::packet::PacketStage::Play;
use crate::prelude::*;
use crate::world::chunk::Chunk;
use crate::{ClientboundAnimation, Hand};
use crate::{Biome, ClientboundAnimation, Hand};
use bytes::{Buf, BufMut};
use hashbrown::HashMap;
use num_traits::{FromPrimitive, ToPrimitive};
Expand Down Expand Up @@ -1347,7 +1347,7 @@ impl Packet for ChunkData {
// Just plains for now - TODO proper biome support
temp_buf.reserve(256 * 4);
for _ in 0..256 {
temp_buf.write_i32_be(1); // 1 = plains
temp_buf.write_i32_be(Biome::Plains.protocol_id());
}

buf.write_var_int(temp_buf.len() as i32);
Expand Down
3 changes: 3 additions & 0 deletions generator/biomes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

cargo run --release --bin feather-generator -- biomes -i data/registries.json -o ../core/src/biomes.rs
126 changes: 126 additions & 0 deletions generator/src/biome.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//! Generation of biome mappings from 1.14 registry report.

use failure::Error;
use heck::CamelCase;
use indexmap::IndexMap;
use proc_macro2::{Ident, Span};
use serde_json::Value;
use std::fs::File;
use std::io::{Read, Write};
use std::process::Command;

#[derive(Deserialize, Clone)]
pub struct BiomeReport {
#[serde(flatten)]
biomes: IndexMap<String, Biome>,
}

#[derive(Deserialize, Clone)]
pub struct Biome {
protocol_id: i32,
}

fn load_report(path: &str) -> Result<BiomeReport, Error> {
let mut file = File::open(path)?;

let json: Value = {
let mut string = String::new();
file.read_to_string(&mut string)?;
serde_json::from_str(&string)?
};

// Hack to get around the format of the registries.json
// file.
let biome_report: BiomeReport = {
let top = &json["minecraft:biome"];
let entries = &top["entries"];

let as_string = serde_json::to_string(entries)?;
serde_json::from_str(&as_string)?
};

Ok(biome_report)
}

pub fn generate_rust(input: &str, output: &str) -> Result<(), Error> {
let report = load_report(input)?;

let mut enum_variants = vec![];
let mut to_protocol_id_match_arms = vec![];
let mut from_protocol_id_match_arms = vec![];
let mut to_identifier_match_arms = vec![];
let mut from_identifier_match_arms = vec![];

// These biomes don't exist in 1.13.2, only in 1.14.
let exclude = ["minecraft:bamboo_jungle", "minecraft:bamboo_jungle_hills"];

for (name, biome) in report.biomes {
if exclude.iter().any(|e| e == &name) {
continue;
}
let protocol_id = biome.protocol_id;

let ident = Ident::new(&name[10..].to_camel_case(), Span::call_site());

enum_variants.push(quote! {
#ident,
});

to_protocol_id_match_arms.push(quote! {
Biome::#ident => #protocol_id,
});

from_protocol_id_match_arms.push(quote! {
#protocol_id => Some(Biome::#ident),
});

to_identifier_match_arms.push(quote! {
Biome::#ident => #name,
});

from_identifier_match_arms.push(quote! {
#name => Some(Biome::#ident),
});
}

let code = quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumCount)]
pub enum Biome {
#(#enum_variants)*
}

impl Biome {
pub fn protocol_id(self) -> i32 {
match self {
#(#to_protocol_id_match_arms)*
}
}

pub fn from_protocol_id(protocol_id: i32) -> Option<Self> {
match protocol_id {
#(#from_protocol_id_match_arms)*
_ => None,
}
}

pub fn identifier(self) -> &'static str {
match self {
#(#to_identifier_match_arms)*
}
}

pub fn from_identifier(identifier: &str) -> Option<Self> {
match identifier {
#(#from_identifier_match_arms)*
_ => None,
}
}
}
};
let mut file = File::create(output)?;
file.write_all(code.to_string().as_bytes())?;

Command::new("rustfmt").arg(output).output()?;

Ok(())
}
18 changes: 17 additions & 1 deletion generator/src/cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,20 @@ subcommands:
short: o
help: "Rust output file"
required: true
takes_value: true
takes_value: true

- biomes:
about: "Generates biome mappings"
args:
- input:
long: input
short: i
required: true
takes_value: true
help: "1.14 registries.json report"
- output:
long: output
short: o
required: true
takes_value: true
help: "Output file to write code to"
8 changes: 8 additions & 0 deletions generator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ extern crate log;
#[macro_use]
extern crate quote;

mod biome;
mod block_data;
mod item;
mod item_to_block;
Expand Down Expand Up @@ -99,6 +100,13 @@ fn run() -> Result<(), Error> {
args.value_of("output").unwrap(),
)?;
}
Some("biomes") => {
let args = matches.subcommand_matches("biomes").unwrap();
biome::generate_rust(
args.value_of("input").unwrap(),
args.value_of("output").unwrap(),
)?;
}
Some(s) => {
error!("Invalid subcommand {}", s);
return Ok(());
Expand Down

0 comments on commit 6e75819

Please sign in to comment.