Skip to content

Commit

Permalink
Implemented a proper way to handle items cooldown (#6405)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipad54 authored Sep 25, 2024
1 parent 4e6b34f commit f6e6f15
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/item/ChorusFruit.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ public function onConsume(Living $consumer) : void{
public function getCooldownTicks() : int{
return 20;
}

public function getCooldownTag() : ?string{
return ItemCooldownTags::CHORUS_FRUIT;
}
}
4 changes: 4 additions & 0 deletions src/item/EnderPearl.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ public function getThrowForce() : float{
public function getCooldownTicks() : int{
return 20;
}

public function getCooldownTag() : ?string{
return ItemCooldownTags::ENDER_PEARL;
}
}
14 changes: 14 additions & 0 deletions src/item/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,20 @@ public function getCooldownTicks() : int{
return 0;
}

/**
* Returns a tag that identifies a group of items that should have cooldown at the same time
* regardless of their state or type.
* When cooldown starts, any other items with the same cooldown tag can't be used until the cooldown expires.
* Such behaviour can be seen in goat horns and shields.
*
* If tag is null, item state id will be used to store cooldown.
*
* @see ItemCooldownTags
*/
public function getCooldownTag() : ?string{
return null;
}

/**
* Compares an Item to this Item and check if they match.
*
Expand Down
45 changes: 45 additions & 0 deletions src/item/ItemCooldownTags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/

declare(strict_types=1);

namespace pocketmine\item;

/**
* Tags used by items to determine their cooldown group.
*
* These tag values are not related to Minecraft internal IDs.
* They only share a visual similarity because these are the most obvious values to use.
* Any arbitrary string can be used.
*
* @see Item::getCooldownTag()
*/
final class ItemCooldownTags{

private function __construct(){
//NOOP
}

public const CHORUS_FRUIT = "chorus_fruit";
public const ENDER_PEARL = "ender_pearl";
public const SHIELD = "shield";
public const GOAT_HORN = "goat_horn";
}
10 changes: 10 additions & 0 deletions src/network/mcpe/NetworkSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\event\server\DataPacketSendEvent;
use pocketmine\form\Form;
use pocketmine\item\Item;
use pocketmine\lang\KnownTranslationFactory;
use pocketmine\lang\Translatable;
use pocketmine\math\Vector3;
Expand Down Expand Up @@ -65,6 +66,7 @@
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\protocol\PacketPool;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlayerStartItemCooldownPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
Expand Down Expand Up @@ -111,6 +113,7 @@
use pocketmine\utils\BinaryStream;
use pocketmine\utils\ObjectSet;
use pocketmine\utils\TextFormat;
use pocketmine\world\format\io\GlobalItemDataHandlers;
use pocketmine\world\Position;
use pocketmine\YmlServerProperties;
use function array_map;
Expand Down Expand Up @@ -1289,6 +1292,13 @@ public function onOpenSignEditor(Vector3 $signPosition, bool $frontSide) : void{
$this->sendDataPacket(OpenSignPacket::create(BlockPosition::fromVector3($signPosition), $frontSide));
}

public function onItemCooldownChanged(Item $item, int $ticks) : void{
$this->sendDataPacket(PlayerStartItemCooldownPacket::create(
GlobalItemDataHandlers::getSerializer()->serializeType($item)->getName(),
$ticks
));
}

public function tick() : void{
if(!$this->isConnected()){
$this->dispose();
Expand Down
13 changes: 9 additions & 4 deletions src/player/Player.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,11 @@ public static function isValidUserName(?string $name) : bool{
protected string $locale = "en_US";

protected int $startAction = -1;
/** @var int[] ID => ticks map */

/**
* @phpstan-var array<int|string, int>
* @var int[] stateId|cooldownTag => ticks map
*/
protected array $usedItemsCooldown = [];

private int $lastEmoteTick = 0;
Expand Down Expand Up @@ -697,15 +701,15 @@ public function getItemUseDuration() : int{
*/
public function getItemCooldownExpiry(Item $item) : int{
$this->checkItemCooldowns();
return $this->usedItemsCooldown[$item->getStateId()] ?? 0;
return $this->usedItemsCooldown[$item->getCooldownTag() ?? $item->getStateId()] ?? 0;
}

/**
* Returns whether the player has a cooldown period left before it can use the given item again.
*/
public function hasItemCooldown(Item $item) : bool{
$this->checkItemCooldowns();
return isset($this->usedItemsCooldown[$item->getStateId()]);
return isset($this->usedItemsCooldown[$item->getCooldownTag() ?? $item->getStateId()]);
}

/**
Expand All @@ -714,7 +718,8 @@ public function hasItemCooldown(Item $item) : bool{
public function resetItemCooldown(Item $item, ?int $ticks = null) : void{
$ticks = $ticks ?? $item->getCooldownTicks();
if($ticks > 0){
$this->usedItemsCooldown[$item->getStateId()] = $this->server->getTick() + $ticks;
$this->usedItemsCooldown[$item->getCooldownTag() ?? $item->getStateId()] = $this->server->getTick() + $ticks;
$this->getNetworkSession()->onItemCooldownChanged($item, $ticks);
}
}

Expand Down

0 comments on commit f6e6f15

Please sign in to comment.