mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
feat(loot-table): add luck
This commit is contained in:
446
Cargo.lock
generated
446
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -126,7 +126,7 @@ console-subscriber = { version = "0.5.0", default-features = false }
|
||||
crc-fast = "1.10.0"
|
||||
criterion = { version = "0.8", default-features = false }
|
||||
crossbeam-utils = "0.8.21"
|
||||
crossfire = { version = "3.1.12", features = ["compat"] }
|
||||
crossfire = { version = "3.1.15", features = ["compat"] }
|
||||
crypto-bigint = "0.7.3"
|
||||
dashmap = "6.2"
|
||||
ecdsa = "0.16.9"
|
||||
@@ -183,9 +183,9 @@ toml = "1.1"
|
||||
ureq = "3.3.0"
|
||||
notify = "8.2.0"
|
||||
|
||||
wasmtime = "44.0"
|
||||
wasmtime-wasi = { version = "44.0", default-features = false, features = ["p2"] }
|
||||
wasmtime-wasi-http = "44.0"
|
||||
wasmtime = "45.0"
|
||||
wasmtime-wasi = { version = "45.0", default-features = false, features = ["p2"] }
|
||||
wasmtime-wasi-http = "45.0"
|
||||
# needed for interacting with wasmtime-wasi-http - keep in sync
|
||||
hyper = { version = "^1.9", features = ["full"] }
|
||||
wit-bindgen = "0.57"
|
||||
|
||||
4
pumpkin-codegen/Cargo.lock
generated
4
pumpkin-codegen/Cargo.lock
generated
@@ -319,9 +319,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
|
||||
@@ -51,9 +51,9 @@ pub struct LootPoolStruct {
|
||||
/// Entries that can be selected during a roll of this pool.
|
||||
entries: Vec<LootPoolEntryStruct>,
|
||||
/// Number of times the pool is rolled.
|
||||
rolls: LootNumberProviderTypes, // TODO
|
||||
rolls: LootNumberProviderTypes,
|
||||
/// Extra rolls granted by luck-related enchantments.
|
||||
bonus_rolls: f32,
|
||||
bonus_rolls: LootNumberProviderTypes,
|
||||
/// Conditions that must all pass for this pool to be rolled, if any.
|
||||
conditions: Option<Vec<LootConditionStruct>>,
|
||||
/// Functions applied to the selected entries, if any.
|
||||
@@ -91,6 +91,7 @@ impl ToTokens for LootPoolStruct {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Deserialized single-item loot entry holding the item's registry key.
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
pub struct ItemEntryStruct {
|
||||
@@ -653,16 +654,28 @@ pub struct LootPoolEntryStruct {
|
||||
/// The concrete entry type (item, alternatives, etc.).
|
||||
#[serde(flatten)]
|
||||
content: LootPoolEntryTypesStruct,
|
||||
/// Relative probability weight; higher values are more likely.
|
||||
#[serde(default = "default_weight")]
|
||||
weight: i32,
|
||||
/// Quality of the entry, used to modify weight based on luck.
|
||||
#[serde(default)]
|
||||
quality: i32,
|
||||
/// Conditions that must all pass for this entry to be evaluated.
|
||||
conditions: Option<Vec<LootConditionStruct>>,
|
||||
/// Functions applied to the item if this entry is selected.
|
||||
functions: Option<Vec<LootFunctionStruct>>,
|
||||
}
|
||||
|
||||
fn default_weight() -> i32 {
|
||||
1
|
||||
}
|
||||
|
||||
impl ToTokens for LootPoolEntryStruct {
|
||||
/// Emits a `LootPoolEntry { … }` struct literal token stream for code generation.
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let content = &self.content;
|
||||
let weight = self.weight;
|
||||
let quality = self.quality;
|
||||
let conditions_tokens = if let Some(conds) = &self.conditions {
|
||||
let cond_tokens: Vec<_> = conds.iter().map(ToTokens::to_token_stream).collect();
|
||||
quote! { Some(&[#(#cond_tokens),*]) }
|
||||
@@ -679,6 +692,8 @@ impl ToTokens for LootPoolEntryStruct {
|
||||
tokens.extend(quote! {
|
||||
LootPoolEntry {
|
||||
content: #content,
|
||||
weight: #weight,
|
||||
quality: #quality,
|
||||
conditions: #conditions_tokens,
|
||||
functions: #functions_tokens,
|
||||
}
|
||||
@@ -686,6 +701,7 @@ impl ToTokens for LootPoolEntryStruct {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Deserialized loot table category, tagged by its `"type"` field.
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[serde(rename = "snake_case")]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ pub struct LootPool {
|
||||
/// Number of rolls, specified using a number provider.
|
||||
pub rolls: LootNumberProviderTypes,
|
||||
/// Additional bonus rolls to apply.
|
||||
pub bonus_rolls: f32,
|
||||
pub bonus_rolls: LootNumberProviderTypes,
|
||||
/// Optional conditions that must be met for this pool to be applied.
|
||||
pub conditions: Option<&'static [LootCondition]>,
|
||||
/// Optional functions applied to each entry in the pool.
|
||||
@@ -192,6 +192,10 @@ pub enum LootFunctionBonusParameter {
|
||||
pub struct LootPoolEntry {
|
||||
/// The type of entry.
|
||||
pub content: LootPoolEntryTypes,
|
||||
/// Relative probability weight; higher values are more likely.
|
||||
pub weight: i32,
|
||||
/// Quality of the entry, used to modify weight based on luck.
|
||||
pub quality: i32,
|
||||
/// Optional conditions for this entry.
|
||||
pub conditions: Option<&'static [LootCondition]>,
|
||||
/// Optional functions for this entry.
|
||||
|
||||
@@ -15,6 +15,7 @@ pub struct LootContextParameters {
|
||||
pub explosion_radius: Option<f32>,
|
||||
pub block_state: Option<&'static BlockState>,
|
||||
pub killed_by_player: Option<bool>,
|
||||
pub luck: f32,
|
||||
}
|
||||
|
||||
pub trait LootTableExt {
|
||||
@@ -34,7 +35,8 @@ impl LootTableExt for LootTable {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rolls = pool.rolls.get(&mut random).round() as i32;
|
||||
let rolls = pool.rolls.get(&mut random) as i32
|
||||
+ (pool.bonus_rolls.get(&mut random) * params.luck).floor() as i32;
|
||||
|
||||
for _ in 0..rolls {
|
||||
let mut total_weight = 0;
|
||||
@@ -46,9 +48,11 @@ impl LootTableExt for LootTable {
|
||||
.as_ref()
|
||||
.is_none_or(|c| c.iter().all(|cond| cond.is_fulfilled(¶ms)))
|
||||
{
|
||||
let w = 1; // TODO: weight
|
||||
total_weight += w;
|
||||
valid_entries.push((entry, w));
|
||||
let weight = (entry.weight as f32 + entry.quality as f32 * params.luck)
|
||||
.floor() as i32;
|
||||
let weight = weight.max(0);
|
||||
total_weight += weight;
|
||||
valid_entries.push((entry, weight));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::block::entities::BlockEntity;
|
||||
use dashmap::DashMap;
|
||||
use pumpkin_data::attributes::Attributes;
|
||||
use pumpkin_data::chunk::Biome;
|
||||
use pumpkin_protocol::bedrock::client::level_event::{CLevelEvent, LevelEvent};
|
||||
use pumpkin_protocol::codec::data_component::data_to_proto_sound;
|
||||
@@ -3572,6 +3573,10 @@ impl World {
|
||||
// Close container screens for any players viewing this block
|
||||
self.close_container_screens_at(position).await;
|
||||
|
||||
let luck = cause.as_ref().map_or(0.0, |player| {
|
||||
player.living_entity.get_attribute_value(&Attributes::LUCK) as f32
|
||||
});
|
||||
|
||||
if Block::from_state_id(broken_state_id) != &Block::FIRE {
|
||||
let particles_packet = CWorldEvent::new(
|
||||
WorldEvent::ParticlesDestroyBlock as i32,
|
||||
@@ -3591,10 +3596,10 @@ impl World {
|
||||
None => self.broadcast_to_chunk(chunk_pos, &particles_packet),
|
||||
}
|
||||
}
|
||||
|
||||
if !flags.contains(BlockFlags::SKIP_DROPS) {
|
||||
let params = LootContextParameters {
|
||||
block_state: Some(BlockState::from_id(broken_state_id)),
|
||||
luck,
|
||||
..Default::default()
|
||||
};
|
||||
block::drop_loot(self, broken_block, position, true, params).await;
|
||||
|
||||
Reference in New Issue
Block a user