mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
fix(inventory): enchanting table offers and lapis validation (#2374)
* fix(inventory): match applied enchantments with table preview * fix(inventory): require lapis for enchanting purchases
This commit is contained in:
@@ -8,7 +8,7 @@ use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_data::screen::WindowType;
|
||||
use pumpkin_data::statistic::{CustomStatistic, StatisticCategory};
|
||||
use pumpkin_data::tag::{Enchantment as EnchantmentTag, Taggable};
|
||||
use pumpkin_util::random::RandomImpl;
|
||||
use pumpkin_util::random::{RandomImpl, legacy_rand::LegacyRand};
|
||||
use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::{
|
||||
@@ -17,10 +17,44 @@ use crate::{
|
||||
InventoryPlayer, ItemStackFuture, ScreenHandler, ScreenHandlerBehaviour,
|
||||
ScreenHandlerFuture, offer_or_drop_stack,
|
||||
},
|
||||
slot::NormalSlot,
|
||||
slot::{BoxFuture, NormalSlot, Slot},
|
||||
window_property::{EnchantmentTable, WindowProperty},
|
||||
};
|
||||
|
||||
struct LapisSlot(NormalSlot);
|
||||
|
||||
fn is_lapis(stack: &ItemStack) -> bool {
|
||||
stack.item == &Item::LAPIS_LAZULI
|
||||
}
|
||||
|
||||
impl LapisSlot {
|
||||
fn new(inventory: Arc<dyn Inventory>) -> Self {
|
||||
Self(NormalSlot::new(inventory, 1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Slot for LapisSlot {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory> {
|
||||
self.0.get_inventory()
|
||||
}
|
||||
|
||||
fn get_index(&self) -> usize {
|
||||
self.0.get_index()
|
||||
}
|
||||
|
||||
fn set_id(&self, id: usize) {
|
||||
self.0.set_id(id);
|
||||
}
|
||||
|
||||
fn can_insert<'a>(&'a self, stack: &'a ItemStack) -> BoxFuture<'a, bool> {
|
||||
Box::pin(async move { is_lapis(stack) })
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()> {
|
||||
self.0.mark_dirty()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EnchantingTableScreenHandler {
|
||||
pub inventory: Arc<dyn Inventory>,
|
||||
behaviour: ScreenHandlerBehaviour,
|
||||
@@ -51,7 +85,7 @@ impl EnchantingTableScreenHandler {
|
||||
|
||||
// Enchanting slots: 0 is item, 1 is lapis
|
||||
handler.add_slot(Arc::new(NormalSlot::new(inventory.clone(), 0)));
|
||||
handler.add_slot(Arc::new(NormalSlot::new(inventory.clone(), 1)));
|
||||
handler.add_slot(Arc::new(LapisSlot::new(inventory.clone())));
|
||||
|
||||
let player_inventory: Arc<dyn Inventory> = player_inventory.clone();
|
||||
handler.add_player_slots(&player_inventory);
|
||||
@@ -81,9 +115,7 @@ impl EnchantingTableScreenHandler {
|
||||
self.enchantment_level[i] = -1;
|
||||
}
|
||||
} else {
|
||||
let mut random = pumpkin_util::random::xoroshiro128::Xoroshiro::from_seed(
|
||||
self.enchantment_seed as u64,
|
||||
);
|
||||
let mut random = LegacyRand::from_seed(self.enchantment_seed as u64);
|
||||
|
||||
for i in 0..3 {
|
||||
let level = self.calculate_level_requirement(&mut random, i, enchantability);
|
||||
@@ -92,18 +124,22 @@ impl EnchantingTableScreenHandler {
|
||||
|
||||
for i in 0..3 {
|
||||
if self.level_requirements[i] > 0 {
|
||||
let mut random = self.create_enchantment_random(i);
|
||||
let enchantments = Self::get_enchantment_list(
|
||||
&mut random,
|
||||
&item,
|
||||
i,
|
||||
self.level_requirements[i],
|
||||
);
|
||||
if let Some(first) = enchantments.first() {
|
||||
self.enchantment_id[i] = first.0.id as i32;
|
||||
self.enchantment_level[i] = first.1;
|
||||
} else {
|
||||
if enchantments.is_empty() {
|
||||
self.enchantment_id[i] = -1;
|
||||
self.enchantment_level[i] = -1;
|
||||
} else {
|
||||
let clue_index =
|
||||
random.next_bounded_i32(enchantments.len() as i32) as usize;
|
||||
let clue = enchantments[clue_index];
|
||||
self.enchantment_id[i] = clue.0.id as i32;
|
||||
self.enchantment_level[i] = clue.1;
|
||||
}
|
||||
} else {
|
||||
self.enchantment_id[i] = -1;
|
||||
@@ -117,7 +153,7 @@ impl EnchantingTableScreenHandler {
|
||||
|
||||
fn calculate_level_requirement(
|
||||
&self,
|
||||
random: &mut pumpkin_util::random::xoroshiro128::Xoroshiro,
|
||||
random: &mut LegacyRand,
|
||||
slot: usize,
|
||||
_enchantability: i32,
|
||||
) -> i32 {
|
||||
@@ -132,8 +168,12 @@ impl EnchantingTableScreenHandler {
|
||||
}
|
||||
}
|
||||
|
||||
const fn create_enchantment_random(&self, slot: usize) -> LegacyRand {
|
||||
LegacyRand::from_seed(self.enchantment_seed.wrapping_add(slot as i32) as u64)
|
||||
}
|
||||
|
||||
fn get_enchantment_list(
|
||||
random: &mut pumpkin_util::random::xoroshiro128::Xoroshiro,
|
||||
random: &mut LegacyRand,
|
||||
item: &ItemStack,
|
||||
_slot: usize,
|
||||
level: i32,
|
||||
@@ -314,7 +354,9 @@ impl ScreenHandler for EnchantingTableScreenHandler {
|
||||
let lapis_cost = (id + 1) as u8;
|
||||
|
||||
if !player.is_creative()
|
||||
&& (lapis_stack.is_empty() || lapis_stack.item_count < lapis_cost)
|
||||
&& (lapis_stack.is_empty()
|
||||
|| !is_lapis(&lapis_stack)
|
||||
|| lapis_stack.item_count < lapis_cost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -327,9 +369,7 @@ impl ScreenHandler for EnchantingTableScreenHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut random = pumpkin_util::random::xoroshiro128::Xoroshiro::from_seed(
|
||||
self.enchantment_seed as u64,
|
||||
);
|
||||
let mut random = self.create_enchantment_random(id as usize);
|
||||
let enchantments =
|
||||
Self::get_enchantment_list(&mut random, &item_stack, id as usize, level_req);
|
||||
|
||||
@@ -444,3 +484,14 @@ impl ScreenHandler for EnchantingTableScreenHandler {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lapis_slot_only_accepts_lapis_lazuli() {
|
||||
assert!(is_lapis(&ItemStack::new(1, &Item::LAPIS_LAZULI)));
|
||||
assert!(!is_lapis(&ItemStack::new(1, &Item::DIRT)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user