use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use serde::Deserialize; use crate::random::RandomImpl; #[derive(Clone, Copy, PartialEq, Debug)] pub struct LootTable { pub r#type: LootTableType, pub random_sequence: Option<&'static str>, pub pools: Option<&'static [LootPool]>, } #[derive(Clone, PartialEq, Debug)] pub struct LootPool { pub entries: &'static [LootPoolEntry], pub rolls: LootNumberProviderTypes, pub bonus_rolls: f32, pub conditions: Option<&'static [LootCondition]>, pub functions: Option<&'static [LootFunction]>, } #[derive(Clone, PartialEq, Debug)] pub struct ItemEntry { pub name: &'static str, } #[derive(Clone, PartialEq, Debug)] pub struct AlternativeEntry { pub children: &'static [LootPoolEntry], } #[derive(Clone, PartialEq, Debug)] pub enum LootPoolEntryTypes { Empty, Item(ItemEntry), LootTable, Dynamic, Tag, Alternatives(AlternativeEntry), Sequence, Group, } #[derive(Clone, PartialEq, Debug)] pub enum LootCondition { Inverted, AnyOf, AllOf, RandomChance, RandomChanceWithEnchantedBonus, EntityProperties, KilledByPlayer, EntityScores, BlockStateProperty { block: &'static str, properties: &'static [(&'static str, &'static str)], }, MatchTool, TableBonus, SurvivesExplosion, DamageSourceProperties, LocationCheck, WeatherCheck, Reference, TimeCheck, ValueCheck, EnchantmentActiveCheck, } #[derive(Clone, PartialEq, Debug)] pub struct LootFunction { pub content: LootFunctionTypes, pub conditions: Option<&'static [LootCondition]>, } #[derive(Clone, PartialEq, Debug)] pub enum LootFunctionTypes { SetCount { count: LootFunctionNumberProvider, add: bool, }, EnchantedCountIncrease, FurnaceSmelt, SetPotion, SetOminousBottleAmplifier, LimitCount { min: Option, max: Option, }, ApplyBonus { enchantment: &'static str, formula: &'static str, parameters: Option, }, CopyComponents { source: &'static str, include: &'static [&'static str], }, CopyState { block: &'static str, properties: &'static [&'static str], }, ExplosionDecay, } #[derive(Clone, PartialEq, Debug)] pub enum LootFunctionNumberProvider { Constant { value: f32 }, Uniform { min: f32, max: f32 }, Binomial { n: f32, p: f32 }, } #[derive(Clone, PartialEq, Debug)] pub enum LootFunctionBonusParameter { Multiplier { bonus_multiplier: i32 }, Probability { extra: i32, probability: f32 }, } #[derive(Clone, PartialEq, Debug)] pub struct LootPoolEntry { pub content: LootPoolEntryTypes, pub conditions: Option<&'static [LootCondition]>, pub functions: Option<&'static [LootFunction]>, } #[derive(Clone, Copy, PartialEq, Debug)] pub enum LootTableType { Empty, Entity, Block, Chest, } #[derive(Deserialize, PartialEq, Clone, Copy, Debug)] #[serde(tag = "type")] pub enum LootNumberProviderTypesProvider { #[serde(rename = "minecraft:uniform")] Uniform(UniformLootNumberProvider), } impl ToTokens for LootNumberProviderTypesProvider { fn to_tokens(&self, tokens: &mut TokenStream) { match self { LootNumberProviderTypesProvider::Uniform(uniform) => { tokens.extend(quote! { LootNumberProviderTypesProvider::Uniform(#uniform) }); } } } } #[derive(Deserialize, PartialEq, Clone, Copy, Debug)] pub struct UniformLootNumberProvider { pub min: f32, pub max: f32, } impl ToTokens for UniformLootNumberProvider { fn to_tokens(&self, tokens: &mut TokenStream) { let min_inclusive = self.min; let max_inclusive = self.max; tokens.extend(quote! { UniformLootNumberProvider { min: #min_inclusive, max: #max_inclusive } }); } } impl UniformLootNumberProvider { pub fn get(&self, random: &mut impl RandomImpl) -> f32 { random.next_f32() * (self.max - self.min) + self.min } } #[derive(Deserialize, PartialEq, Clone, Copy, Debug)] #[serde(untagged)] pub enum LootNumberProviderTypes { Object(LootNumberProviderTypesProvider), Constant(f32), } impl ToTokens for LootNumberProviderTypes { fn to_tokens(&self, tokens: &mut TokenStream) { match self { LootNumberProviderTypes::Object(provider) => { tokens.extend(quote! { LootNumberProviderTypes::Object(#provider) }); } LootNumberProviderTypes::Constant(i) => tokens.extend(quote! { LootNumberProviderTypes::Constant(#i) }), } } } impl LootNumberProviderTypes { pub fn get(&self, random: &mut impl RandomImpl) -> f32 { match self { LootNumberProviderTypes::Object(int_provider) => match int_provider { LootNumberProviderTypesProvider::Uniform(uniform) => uniform.get(random), }, LootNumberProviderTypes::Constant(i) => *i, } } }