This commit is contained in:
parent
161b90ed28
commit
878116ceff
@ -131,6 +131,90 @@ impl ToTokens for AlternativeEntryStruct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
pub struct SequenceEntryStruct {
|
||||||
|
/// Child entries evaluated in order until the first condition failure.
|
||||||
|
children: Vec<LootPoolEntryStruct>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for SequenceEntryStruct {
|
||||||
|
/// Emits a `SequenceEntry { … }` struct literal token stream for code generation.
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let children = self.children.iter().map(ToTokens::to_token_stream);
|
||||||
|
|
||||||
|
tokens.extend(quote! {
|
||||||
|
SequenceEntry {
|
||||||
|
children: &[#(#children),*],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialized group loot entry that evaluates all children regardless of individual success.
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
pub struct GroupEntryStruct {
|
||||||
|
/// Child entries all evaluated unconditionally.
|
||||||
|
children: Vec<LootPoolEntryStruct>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for GroupEntryStruct {
|
||||||
|
/// Emits a `GroupEntry { … }` struct literal token stream for code generation.
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let children = self.children.iter().map(ToTokens::to_token_stream);
|
||||||
|
|
||||||
|
tokens.extend(quote! {
|
||||||
|
GroupEntry {
|
||||||
|
children: &[#(#children),*],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialized dynamic loot entry holding the dynamic drop's namespaced key.
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
pub struct DynamicEntryStruct {
|
||||||
|
/// Namespaced key identifying the dynamic drop type (e.g., `"minecraft:contents"`).
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for DynamicEntryStruct {
|
||||||
|
/// Emits a `DynamicEntry { … }` struct literal token stream for code generation.
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let name = LitStr::new(&self.name, Span::call_site());
|
||||||
|
|
||||||
|
tokens.extend(quote! {
|
||||||
|
DynamicEntry {
|
||||||
|
name: #name,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialized tag loot entry holding the item tag's namespaced key.
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
pub struct TagEntryStruct {
|
||||||
|
/// Namespaced item tag key (e.g., `"minecraft:planks"`).
|
||||||
|
name: String,
|
||||||
|
/// If `true`, yields one random item from the tag instead of all items.
|
||||||
|
#[serde(default)]
|
||||||
|
expand: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for TagEntryStruct {
|
||||||
|
/// Emits a `TagEntry { … }` struct literal token stream for code generation.
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let name = LitStr::new(&self.name, Span::call_site());
|
||||||
|
let expand = self.expand;
|
||||||
|
|
||||||
|
tokens.extend(quote! {
|
||||||
|
TagEntry {
|
||||||
|
name: #name,
|
||||||
|
expand: #expand,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserialized variant of a loot pool entry, tagged by the `"type"` field.
|
/// Deserialized variant of a loot pool entry, tagged by the `"type"` field.
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
@ -141,28 +225,27 @@ pub enum LootPoolEntryTypesStruct {
|
|||||||
/// Yields a specific item.
|
/// Yields a specific item.
|
||||||
#[serde(rename = "minecraft:item")]
|
#[serde(rename = "minecraft:item")]
|
||||||
Item(ItemEntryStruct),
|
Item(ItemEntryStruct),
|
||||||
/// References another loot table.
|
/// References another loot table by namespaced key.
|
||||||
#[serde(rename = "minecraft:loot_table")]
|
#[serde(rename = "minecraft:loot_table")]
|
||||||
LootTable,
|
LootTable,
|
||||||
/// Yields dynamically determined drops (e.g., shulker box contents).
|
/// Yields dynamically determined drops (e.g., shulker box contents).
|
||||||
#[serde(rename = "minecraft:dynamic")]
|
#[serde(rename = "minecraft:dynamic")]
|
||||||
Dynamic,
|
Dynamic(DynamicEntryStruct),
|
||||||
/// Yields all items in a tag.
|
/// Yields all items (or one random item) in an item tag.
|
||||||
#[serde(rename = "minecraft:tag")]
|
#[serde(rename = "minecraft:tag")]
|
||||||
Tag,
|
Tag(TagEntryStruct),
|
||||||
/// Tries each child entry until one succeeds.
|
/// Tries each child entry until one succeeds.
|
||||||
#[serde(rename = "minecraft:alternatives")]
|
#[serde(rename = "minecraft:alternatives")]
|
||||||
Alternatives(AlternativeEntryStruct),
|
Alternatives(AlternativeEntryStruct),
|
||||||
/// Evaluates all children in order, stopping on the first failure.
|
/// Evaluates all children in order, stopping on the first failure.
|
||||||
#[serde(rename = "minecraft:sequence")]
|
#[serde(rename = "minecraft:sequence")]
|
||||||
Sequence,
|
Sequence(SequenceEntryStruct),
|
||||||
/// Evaluates all children regardless of individual success.
|
/// Evaluates all children regardless of individual success.
|
||||||
#[serde(rename = "minecraft:group")]
|
#[serde(rename = "minecraft:group")]
|
||||||
Group,
|
Group(GroupEntryStruct),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for LootPoolEntryTypesStruct {
|
impl ToTokens for LootPoolEntryTypesStruct {
|
||||||
/// Emits the matching `LootPoolEntryTypes::*` token stream for code generation.
|
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
match self {
|
match self {
|
||||||
Self::Empty => {
|
Self::Empty => {
|
||||||
@ -174,20 +257,21 @@ impl ToTokens for LootPoolEntryTypesStruct {
|
|||||||
Self::LootTable => {
|
Self::LootTable => {
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::LootTable });
|
tokens.extend(quote! { LootPoolEntryTypes::LootTable });
|
||||||
}
|
}
|
||||||
Self::Dynamic => {
|
Self::Dynamic(entry) => {
|
||||||
|
// TODO
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::Dynamic });
|
tokens.extend(quote! { LootPoolEntryTypes::Dynamic });
|
||||||
}
|
}
|
||||||
Self::Tag => {
|
Self::Tag(entry) => {
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::Tag });
|
tokens.extend(quote! { LootPoolEntryTypes::Tag(#entry) });
|
||||||
}
|
}
|
||||||
Self::Alternatives(alt) => {
|
Self::Alternatives(alt) => {
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::Alternatives(#alt) });
|
tokens.extend(quote! { LootPoolEntryTypes::Alternatives(#alt) });
|
||||||
}
|
}
|
||||||
Self::Sequence => {
|
Self::Sequence(seq) => {
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::Sequence });
|
tokens.extend(quote! { LootPoolEntryTypes::Sequence(#seq) });
|
||||||
}
|
}
|
||||||
Self::Group => {
|
Self::Group(grp) => {
|
||||||
tokens.extend(quote! { LootPoolEntryTypes::Group });
|
tokens.extend(quote! { LootPoolEntryTypes::Group(#grp) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,7 +292,9 @@ pub enum LootConditionStruct {
|
|||||||
AllOf,
|
AllOf,
|
||||||
/// Passes with the given probability.
|
/// Passes with the given probability.
|
||||||
#[serde(rename = "minecraft:random_chance")]
|
#[serde(rename = "minecraft:random_chance")]
|
||||||
RandomChance,
|
RandomChance {
|
||||||
|
chance: f32,
|
||||||
|
},
|
||||||
/// Passes with probability scaled by an enchantment level.
|
/// Passes with probability scaled by an enchantment level.
|
||||||
#[serde(rename = "minecraft:random_chance_with_enchanted_bonus")]
|
#[serde(rename = "minecraft:random_chance_with_enchanted_bonus")]
|
||||||
RandomChanceWithEnchantedBonus,
|
RandomChanceWithEnchantedBonus,
|
||||||
@ -268,7 +354,9 @@ impl ToTokens for LootConditionStruct {
|
|||||||
Self::Inverted => quote! { LootCondition::Inverted },
|
Self::Inverted => quote! { LootCondition::Inverted },
|
||||||
Self::AnyOf => quote! { LootCondition::AnyOf },
|
Self::AnyOf => quote! { LootCondition::AnyOf },
|
||||||
Self::AllOf => quote! { LootCondition::AllOf },
|
Self::AllOf => quote! { LootCondition::AllOf },
|
||||||
Self::RandomChance => quote! { LootCondition::RandomChance },
|
Self::RandomChance { chance } => {
|
||||||
|
quote! { LootCondition::RandomChance { chance: #chance } }
|
||||||
|
}
|
||||||
Self::RandomChanceWithEnchantedBonus => {
|
Self::RandomChanceWithEnchantedBonus => {
|
||||||
quote! { LootCondition::RandomChanceWithEnchantedBonus }
|
quote! { LootCondition::RandomChanceWithEnchantedBonus }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41378,7 +41378,9 @@ impl Block {
|
|||||||
content: LootPoolEntryTypes::Item(ItemEntry {
|
content: LootPoolEntryTypes::Item(ItemEntry {
|
||||||
name: "minecraft:wheat_seeds",
|
name: "minecraft:wheat_seeds",
|
||||||
}),
|
}),
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance {
|
||||||
|
chance: 0.125f32,
|
||||||
|
}]),
|
||||||
functions: Some(&[
|
functions: Some(&[
|
||||||
LootFunction {
|
LootFunction {
|
||||||
content: LootFunctionTypes::ApplyBonus {
|
content: LootFunctionTypes::ApplyBonus {
|
||||||
@ -41468,7 +41470,9 @@ impl Block {
|
|||||||
content: LootPoolEntryTypes::Item(ItemEntry {
|
content: LootPoolEntryTypes::Item(ItemEntry {
|
||||||
name: "minecraft:wheat_seeds",
|
name: "minecraft:wheat_seeds",
|
||||||
}),
|
}),
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance {
|
||||||
|
chance: 0.125f32,
|
||||||
|
}]),
|
||||||
functions: Some(&[
|
functions: Some(&[
|
||||||
LootFunction {
|
LootFunction {
|
||||||
content: LootFunctionTypes::ApplyBonus {
|
content: LootFunctionTypes::ApplyBonus {
|
||||||
@ -166451,7 +166455,7 @@ impl Block {
|
|||||||
content: LootPoolEntryTypes::Item(ItemEntry {
|
content: LootPoolEntryTypes::Item(ItemEntry {
|
||||||
name: "minecraft:poisonous_potato",
|
name: "minecraft:poisonous_potato",
|
||||||
}),
|
}),
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance { chance: 0.02f32 }]),
|
||||||
functions: None,
|
functions: None,
|
||||||
}],
|
}],
|
||||||
rolls: LootNumberProviderTypes::Constant(1f32),
|
rolls: LootNumberProviderTypes::Constant(1f32),
|
||||||
@ -201193,7 +201197,7 @@ impl Block {
|
|||||||
}),
|
}),
|
||||||
conditions: Some(&[
|
conditions: Some(&[
|
||||||
LootCondition::SurvivesExplosion,
|
LootCondition::SurvivesExplosion,
|
||||||
LootCondition::RandomChance,
|
LootCondition::RandomChance { chance: 0.125f32 },
|
||||||
]),
|
]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
@ -201238,7 +201242,7 @@ impl Block {
|
|||||||
}),
|
}),
|
||||||
conditions: Some(&[
|
conditions: Some(&[
|
||||||
LootCondition::SurvivesExplosion,
|
LootCondition::SurvivesExplosion,
|
||||||
LootCondition::RandomChance,
|
LootCondition::RandomChance { chance: 0.125f32 },
|
||||||
]),
|
]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
@ -201345,7 +201349,7 @@ impl Block {
|
|||||||
}),
|
}),
|
||||||
conditions: Some(&[
|
conditions: Some(&[
|
||||||
LootCondition::SurvivesExplosion,
|
LootCondition::SurvivesExplosion,
|
||||||
LootCondition::RandomChance,
|
LootCondition::RandomChance { chance: 0.125f32 },
|
||||||
]),
|
]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
@ -201390,7 +201394,7 @@ impl Block {
|
|||||||
}),
|
}),
|
||||||
conditions: Some(&[
|
conditions: Some(&[
|
||||||
LootCondition::SurvivesExplosion,
|
LootCondition::SurvivesExplosion,
|
||||||
LootCondition::RandomChance,
|
LootCondition::RandomChance { chance: 0.125f32 },
|
||||||
]),
|
]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1441,7 +1441,7 @@ impl EntityType {
|
|||||||
}],
|
}],
|
||||||
rolls: LootNumberProviderTypes::Constant(1f32),
|
rolls: LootNumberProviderTypes::Constant(1f32),
|
||||||
bonus_rolls: 0f32,
|
bonus_rolls: 0f32,
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance { chance: 0.05f32 }]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
@ -1774,7 +1774,10 @@ impl EntityType {
|
|||||||
},
|
},
|
||||||
LootPool {
|
LootPool {
|
||||||
entries: &[LootPoolEntry {
|
entries: &[LootPoolEntry {
|
||||||
content: LootPoolEntryTypes::Tag,
|
content: LootPoolEntryTypes::Tag(TagEntry {
|
||||||
|
name: "minecraft:creeper_drop_music_discs",
|
||||||
|
expand: true,
|
||||||
|
}),
|
||||||
conditions: None,
|
conditions: None,
|
||||||
functions: None,
|
functions: None,
|
||||||
}],
|
}],
|
||||||
@ -5590,7 +5593,7 @@ impl EntityType {
|
|||||||
}],
|
}],
|
||||||
rolls: LootNumberProviderTypes::Constant(1f32),
|
rolls: LootNumberProviderTypes::Constant(1f32),
|
||||||
bonus_rolls: 0f32,
|
bonus_rolls: 0f32,
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance { chance: 0.05f32 }]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
@ -5856,7 +5859,7 @@ impl EntityType {
|
|||||||
}],
|
}],
|
||||||
rolls: LootNumberProviderTypes::Constant(1f32),
|
rolls: LootNumberProviderTypes::Constant(1f32),
|
||||||
bonus_rolls: 0f32,
|
bonus_rolls: 0f32,
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance { chance: 0.05f32 }]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
@ -7358,7 +7361,7 @@ impl EntityType {
|
|||||||
}],
|
}],
|
||||||
rolls: LootNumberProviderTypes::Constant(1f32),
|
rolls: LootNumberProviderTypes::Constant(1f32),
|
||||||
bonus_rolls: 0f32,
|
bonus_rolls: 0f32,
|
||||||
conditions: Some(&[LootCondition::RandomChance]),
|
conditions: Some(&[LootCondition::RandomChance { chance: 0.05f32 }]),
|
||||||
functions: None,
|
functions: None,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use serde::Deserialize;
|
|||||||
use crate::random::RandomImpl;
|
use crate::random::RandomImpl;
|
||||||
|
|
||||||
/// Represents a loot table used to generate items or rewards.
|
/// Represents a loot table used to generate items or rewards.
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct LootTable {
|
pub struct LootTable {
|
||||||
/// The type of loot table (e.g., `Entity`, `Block`, `Chest`).
|
/// The type of loot table (e.g., `Entity`, `Block`, `Chest`).
|
||||||
pub r#type: LootTableType,
|
pub r#type: LootTableType,
|
||||||
@ -16,7 +16,7 @@ pub struct LootTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defines a loot pool containing entries, rolls, and conditions.
|
/// Defines a loot pool containing entries, rolls, and conditions.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LootPool {
|
pub struct LootPool {
|
||||||
/// Entries contained in this loot pool.
|
/// Entries contained in this loot pool.
|
||||||
pub entries: &'static [LootPoolEntry],
|
pub entries: &'static [LootPoolEntry],
|
||||||
@ -38,35 +38,42 @@ pub struct ItemEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an alternative loot entry, which chooses one of its children.
|
/// Represents an alternative loot entry, which chooses one of its children.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct AlternativeEntry {
|
pub struct AlternativeEntry {
|
||||||
/// Child entries for this alternative.
|
/// Child entries for this alternative.
|
||||||
pub children: &'static [LootPoolEntry],
|
pub children: &'static [LootPoolEntry],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types of entries that can exist in a loot pool.
|
#[derive(Clone, Debug)]
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
pub struct TagEntry {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub expand: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct SequenceEntry {
|
||||||
|
pub children: &'static [LootPoolEntry],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct GroupEntry {
|
||||||
|
pub children: &'static [LootPoolEntry],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub enum LootPoolEntryTypes {
|
pub enum LootPoolEntryTypes {
|
||||||
/// Empty entry; no item is generated.
|
|
||||||
Empty,
|
Empty,
|
||||||
/// Entry that generates a specific item.
|
|
||||||
Item(ItemEntry),
|
Item(ItemEntry),
|
||||||
/// Entry that references another loot table.
|
|
||||||
LootTable,
|
LootTable,
|
||||||
/// Dynamic entry, resolved at runtime.
|
|
||||||
Dynamic,
|
Dynamic,
|
||||||
/// Entry that references a tag.
|
Tag(TagEntry),
|
||||||
Tag,
|
|
||||||
/// Entry that provides alternatives.
|
|
||||||
Alternatives(AlternativeEntry),
|
Alternatives(AlternativeEntry),
|
||||||
/// Entry that executes sequentially.
|
Sequence(SequenceEntry),
|
||||||
Sequence,
|
Group(GroupEntry),
|
||||||
/// Entry that groups multiple entries.
|
|
||||||
Group,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conditions that can modify whether loot entries are applied.
|
/// Conditions that can modify whether loot entries are applied.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum LootCondition {
|
pub enum LootCondition {
|
||||||
/// Inverts the result of another condition.
|
/// Inverts the result of another condition.
|
||||||
Inverted,
|
Inverted,
|
||||||
@ -75,7 +82,7 @@ pub enum LootCondition {
|
|||||||
/// Passes only if all the given conditions are met.
|
/// Passes only if all the given conditions are met.
|
||||||
AllOf,
|
AllOf,
|
||||||
/// Passes based on a random chance.
|
/// Passes based on a random chance.
|
||||||
RandomChance,
|
RandomChance { chance: f32 },
|
||||||
/// Passes based on a random chance modified by item enchantments.
|
/// Passes based on a random chance modified by item enchantments.
|
||||||
RandomChanceWithEnchantedBonus,
|
RandomChanceWithEnchantedBonus,
|
||||||
/// Checks properties of the entity (e.g. type, attributes).
|
/// Checks properties of the entity (e.g. type, attributes).
|
||||||
@ -181,7 +188,7 @@ pub enum LootFunctionBonusParameter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Single entry in a loot pool with optional conditions and functions.
|
/// Single entry in a loot pool with optional conditions and functions.
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LootPoolEntry {
|
pub struct LootPoolEntry {
|
||||||
/// The type of entry.
|
/// The type of entry.
|
||||||
pub content: LootPoolEntryTypes,
|
pub content: LootPoolEntryTypes,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use pumpkin_data::item_stack::ItemStack;
|
use pumpkin_data::item_stack::ItemStack;
|
||||||
|
use pumpkin_data::tag;
|
||||||
use pumpkin_data::{Block, BlockState, item::Item};
|
use pumpkin_data::{Block, BlockState, item::Item};
|
||||||
use pumpkin_util::{
|
use pumpkin_util::{
|
||||||
loot_table::{
|
loot_table::{
|
||||||
@ -168,7 +169,33 @@ impl LootPoolEntryTypesExt for LootPoolEntryTypes {
|
|||||||
}
|
}
|
||||||
Self::LootTable => todo!(),
|
Self::LootTable => todo!(),
|
||||||
Self::Dynamic => todo!(),
|
Self::Dynamic => todo!(),
|
||||||
Self::Tag => todo!(),
|
Self::Tag(tag) => {
|
||||||
|
let key = tag.name.strip_prefix("minecraft:").unwrap_or(tag.name);
|
||||||
|
|
||||||
|
let items = pumpkin_data::tag::get_tag_values(tag::RegistryKey::Item, key)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|registry_key| {
|
||||||
|
let item_key = registry_key
|
||||||
|
.strip_prefix("minecraft:")
|
||||||
|
.unwrap_or(registry_key);
|
||||||
|
Item::from_registry_key(item_key)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if items.is_empty() {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag.expand {
|
||||||
|
// Pick one random item from the tag
|
||||||
|
let index = rand::random_range(0..items.len() as i32) as usize;
|
||||||
|
vec![ItemStack::new(1, items[index])]
|
||||||
|
} else {
|
||||||
|
// Yield one stack of every item in the tag
|
||||||
|
items.iter().map(|&item| ItemStack::new(1, item)).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::Alternatives(alternative_entry) => {
|
Self::Alternatives(alternative_entry) => {
|
||||||
for entry in alternative_entry.children {
|
for entry in alternative_entry.children {
|
||||||
if let Some(loot) = entry.get_loot(params) {
|
if let Some(loot) = entry.get_loot(params) {
|
||||||
@ -177,8 +204,35 @@ impl LootPoolEntryTypesExt for LootPoolEntryTypes {
|
|||||||
}
|
}
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
Self::Sequence => todo!(),
|
Self::Sequence(sequence_entry) => {
|
||||||
Self::Group => todo!(),
|
let mut stacks = Vec::new();
|
||||||
|
for entry in sequence_entry.children {
|
||||||
|
if entry
|
||||||
|
.conditions
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|c| !c.iter().all(|cond| cond.is_fulfilled(params)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
match entry.get_loot(params) {
|
||||||
|
Some(loot) => stacks.extend(loot),
|
||||||
|
// get_loot returning None also signals failure — stop.
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacks
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::Group(group_entry) => {
|
||||||
|
let mut stacks = Vec::new();
|
||||||
|
for entry in group_entry.children {
|
||||||
|
if let Some(loot) = entry.get_loot(params) {
|
||||||
|
stacks.extend(loot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,6 +251,7 @@ impl LootConditionExt for LootCondition {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
Self::RandomChance { chance } => rand::rng().random::<f32>() < *chance,
|
||||||
Self::KilledByPlayer => params.killed_by_player.unwrap_or(false),
|
Self::KilledByPlayer => params.killed_by_player.unwrap_or(false),
|
||||||
Self::BlockStateProperty {
|
Self::BlockStateProperty {
|
||||||
block: _,
|
block: _,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user