Pumpkin/pumpkin-util/src/loot_table.rs
2026-01-15 16:51:37 +01:00

208 lines
5.1 KiB
Rust

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<f32>,
max: Option<f32>,
},
ApplyBonus {
enchantment: &'static str,
formula: &'static str,
parameters: Option<LootFunctionBonusParameter>,
},
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,
}
}
}