38    private ?
Item $inputItem = 
null;
 
   39    private ?
Item $outputItem = 
null;
 
   41    public function __construct(
 
   44        private readonly 
int $cost
 
   46        parent::__construct($source);
 
   49    private function validateOutput() : 
void{
 
   50        if($this->inputItem === 
null || $this->outputItem === 
null){
 
   51            throw new AssumptionFailedError(
"Expected that inputItem and outputItem are not null before validating output");
 
   54        $enchantedInput = EnchantingHelper::enchantItem($this->inputItem, $this->option->getEnchantments());
 
   55        if(!$this->outputItem->equalsExact($enchantedInput)){
 
   60    private function validateFiniteResources(
int $lapisSpent) : 
void{
 
   61        if($lapisSpent !== $this->cost){
 
   65        $xpLevel = $this->source->getXpManager()->getXpLevel();
 
   66        $requiredXpLevel = $this->option->getRequiredXpLevel();
 
   68        if($xpLevel < $requiredXpLevel){
 
   76        if(count($this->actions) < 1){
 
   87        foreach($inputs as $input){
 
   88            if($input->getTypeId() === ItemTypeIds::LAPIS_LAZULI){
 
   89                $lapisSpent = $input->getCount();
 
   91                if($this->inputItem !== 
null){
 
   94                $this->inputItem = $input;
 
   98        if($this->inputItem === 
null){
 
   99            throw new TransactionValidationException(
"No item to enchant received");
 
  102        if(($outputCount = count($outputs)) !== 1){
 
  103            throw new TransactionValidationException(
"Expected 1 output item, but received $outputCount");
 
  105        $this->outputItem = $outputs[0];
 
  107        $this->validateOutput();
 
  109        if($this->source->hasFiniteResources()){
 
  110            $this->validateFiniteResources($lapisSpent);
 
 
  117        if($this->source->hasFiniteResources()){
 
  120            $this->source->getXpManager()->subtractXpLevels(min($this->cost, $this->source->getXpManager()->getXpLevel()));
 
  122        $this->source->regenerateEnchantmentSeed();
 
 
  125    protected function callExecuteEvent() : bool{
 
  126        if($this->inputItem === null || $this->outputItem === null){
 
  127            throw new AssumptionFailedError(
"Expected that inputItem and outputItem are not null before executing the event");
 
  130        $event = 
new PlayerItemEnchantEvent($this->source, $this, $this->option, $this->inputItem, $this->outputItem, $this->cost);
 
  132        return !$event->isCancelled();