maxBudget = $this->averagePerTick * $maxBufferTicks; $this->budget = $this->maxBudget; $this->lastUpdateTimeNs = hrtime(true); } /** * @throws PacketHandlingException if the rate limit has been exceeded */ public function decrement(int $amount = 1) : void{ if($this->budget <= 0){ $this->update(); if($this->budget <= 0){ throw new PacketHandlingException("Exceeded rate limit for \"$this->name\""); } } $this->budget -= $amount; } public function update() : void{ $nowNs = hrtime(true); $timeSinceLastUpdateNs = $nowNs - $this->lastUpdateTimeNs; if($timeSinceLastUpdateNs > $this->updateFrequencyNs){ $ticksSinceLastUpdate = intdiv($timeSinceLastUpdateNs, $this->updateFrequencyNs); /* * If the server takes an abnormally long time to process a tick, add the budget for time difference to * compensate. This extra budget may be very large, but it will disappear the next time a normal update * occurs. This ensures that backlogs during a large lag spike don't cause everyone to get kicked. * As long as all the backlogged packets are processed before the next tick, everything should be OK for * clients behaving normally. */ $this->budget = min($this->budget, $this->maxBudget) + ($this->averagePerTick * 2 * $ticksSinceLastUpdate); $this->lastUpdateTimeNs = $nowNs; } } }