mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-08-30 06:55:11 +00:00
Player: added a server-side forced cooldown mechanism
This is necessary because the stupid client constantly spams right-click actions if you carry on trying to eat/throw/whatever the item when cooldown is in effect. Therefore ender pearls would be fired like machine guns without these checks server side.
This commit is contained in:
parent
3827892e48
commit
2f266a5922
@ -299,6 +299,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
*/
|
*/
|
||||||
protected $lastPingMeasure = 1;
|
protected $lastPingMeasure = 1;
|
||||||
|
|
||||||
|
/** @var int[] ID => ticks map */
|
||||||
|
protected $usedItemsCooldown = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return TranslationContainer|string
|
* @return TranslationContainer|string
|
||||||
*/
|
*/
|
||||||
@ -860,6 +863,39 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return $this->startAction === -1 ? -1 : ($this->server->getTick() - $this->startAction);
|
return $this->startAction === -1 ? -1 : ($this->server->getTick() - $this->startAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the player has a cooldown period left before it can use the given item again.
|
||||||
|
*
|
||||||
|
* @param Item $item
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasItemCooldown(Item $item) : bool{
|
||||||
|
$this->checkItemCooldowns();
|
||||||
|
return isset($this->usedItemsCooldown[$item->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the player's cooldown time for the given item back to the maximum.
|
||||||
|
*
|
||||||
|
* @param Item $item
|
||||||
|
*/
|
||||||
|
public function resetItemCooldown(Item $item) : void{
|
||||||
|
$ticks = $item->getCooldownTicks();
|
||||||
|
if($ticks > 0){
|
||||||
|
$this->usedItemsCooldown[$item->getId()] = $this->server->getTick() + $ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function checkItemCooldowns() : void{
|
||||||
|
$serverTick = $this->server->getTick();
|
||||||
|
foreach($this->usedItemsCooldown as $itemId => $cooldownUntil){
|
||||||
|
if($cooldownUntil <= $serverTick){
|
||||||
|
unset($this->usedItemsCooldown[$itemId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function switchLevel(Level $targetLevel) : bool{
|
protected function switchLevel(Level $targetLevel) : bool{
|
||||||
$oldLevel = $this->level;
|
$oldLevel = $this->level;
|
||||||
if(parent::switchLevel($targetLevel)){
|
if(parent::switchLevel($targetLevel)){
|
||||||
@ -2384,6 +2420,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$ev = new PlayerInteractEvent($this, $item, null, $directionVector, $face, PlayerInteractEvent::RIGHT_CLICK_AIR);
|
$ev = new PlayerInteractEvent($this, $item, null, $directionVector, $face, PlayerInteractEvent::RIGHT_CLICK_AIR);
|
||||||
|
if($this->hasItemCooldown($item)){
|
||||||
|
$ev->setCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
$this->server->getPluginManager()->callEvent($ev);
|
$this->server->getPluginManager()->callEvent($ev);
|
||||||
|
|
||||||
@ -2392,8 +2431,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($item->onClickAir($this, $directionVector) and $this->isSurvival()){
|
if($item->onClickAir($this, $directionVector)){
|
||||||
$this->inventory->setItemInHand($item);
|
$this->resetItemCooldown($item);
|
||||||
|
if($this->isSurvival()){
|
||||||
|
$this->inventory->setItemInHand($item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setUsingItem(true);
|
$this->setUsingItem(true);
|
||||||
@ -2486,7 +2528,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
case InventoryTransactionPacket::RELEASE_ITEM_ACTION_RELEASE:
|
case InventoryTransactionPacket::RELEASE_ITEM_ACTION_RELEASE:
|
||||||
if($this->isUsingItem()){
|
if($this->isUsingItem()){
|
||||||
$item = $this->inventory->getItemInHand();
|
$item = $this->inventory->getItemInHand();
|
||||||
|
if($this->hasItemCooldown($item)){
|
||||||
|
$this->inventory->sendContents($this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if($item->onReleaseUsing($this)){
|
if($item->onReleaseUsing($this)){
|
||||||
|
$this->resetItemCooldown($item);
|
||||||
$this->inventory->setItemInHand($item);
|
$this->inventory->setItemInHand($item);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -2499,6 +2546,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
|
|
||||||
if($slot instanceof Consumable){
|
if($slot instanceof Consumable){
|
||||||
$ev = new PlayerItemConsumeEvent($this, $slot);
|
$ev = new PlayerItemConsumeEvent($this, $slot);
|
||||||
|
if($this->hasItemCooldown($slot)){
|
||||||
|
$ev->setCancelled();
|
||||||
|
}
|
||||||
$this->server->getPluginManager()->callEvent($ev);
|
$this->server->getPluginManager()->callEvent($ev);
|
||||||
|
|
||||||
if($ev->isCancelled() or !$this->consumeObject($slot)){
|
if($ev->isCancelled() or !$this->consumeObject($slot)){
|
||||||
@ -2506,6 +2556,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->resetItemCooldown($slot);
|
||||||
|
|
||||||
if($this->isSurvival()){
|
if($this->isSurvival()){
|
||||||
$slot->pop();
|
$slot->pop();
|
||||||
$this->inventory->setItemInHand($slot);
|
$this->inventory->setItemInHand($slot);
|
||||||
|
@ -84,4 +84,8 @@ class ChorusFruit extends Food{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCooldownTicks() : int{
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,6 +821,15 @@ class Item implements ItemIds, \JsonSerializable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of ticks a player must wait before activating this item again.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getCooldownTicks() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares an Item to this Item and check if they match.
|
* Compares an Item to this Item and check if they match.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user