mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-23 11:26:37 +00:00
Merge branch 'resource-pack-ack-receipts' into minor-next
This commit is contained in:
commit
dbc7105e5b
@ -45,8 +45,8 @@
|
|||||||
"pocketmine/log": "^0.4.0",
|
"pocketmine/log": "^0.4.0",
|
||||||
"pocketmine/math": "~1.0.0",
|
"pocketmine/math": "~1.0.0",
|
||||||
"pocketmine/nbt": "~1.0.0",
|
"pocketmine/nbt": "~1.0.0",
|
||||||
"pocketmine/raklib": "^0.15.0",
|
"pocketmine/raklib": "~1.1.0",
|
||||||
"pocketmine/raklib-ipc": "^0.2.0",
|
"pocketmine/raklib-ipc": "~1.0.0",
|
||||||
"pocketmine/snooze": "^0.5.0",
|
"pocketmine/snooze": "^0.5.0",
|
||||||
"ramsey/uuid": "~4.7.0",
|
"ramsey/uuid": "~4.7.0",
|
||||||
"symfony/filesystem": "~6.4.0"
|
"symfony/filesystem": "~6.4.0"
|
||||||
|
34
composer.lock
generated
34
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "f9a2f433a86f9ea1351d6dc81b508160",
|
"content-hash": "016eb0e55295aa5250888b4e096d8dca",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/json-comment",
|
"name": "adhocore/json-comment",
|
||||||
@ -616,28 +616,28 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/raklib",
|
"name": "pocketmine/raklib",
|
||||||
"version": "0.15.1",
|
"version": "1.1.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/RakLib.git",
|
"url": "https://github.com/pmmp/RakLib.git",
|
||||||
"reference": "79b7b4d1d7516dc6e322514453645ad9452b20ca"
|
"reference": "be2783be516bf6e2872ff5c81fb9048596617b97"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/79b7b4d1d7516dc6e322514453645ad9452b20ca",
|
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/be2783be516bf6e2872ff5c81fb9048596617b97",
|
||||||
"reference": "79b7b4d1d7516dc6e322514453645ad9452b20ca",
|
"reference": "be2783be516bf6e2872ff5c81fb9048596617b97",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
"php": "^8.0",
|
"php": "^8.1",
|
||||||
"php-64bit": "*",
|
"php-64bit": "*",
|
||||||
"php-ipv6": "*",
|
"php-ipv6": "*",
|
||||||
"pocketmine/binaryutils": "^0.2.0",
|
"pocketmine/binaryutils": "^0.2.0",
|
||||||
"pocketmine/log": "^0.3.0 || ^0.4.0"
|
"pocketmine/log": "^0.3.0 || ^0.4.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "1.9.17",
|
"phpstan/phpstan": "1.10.1",
|
||||||
"phpstan/phpstan-strict-rules": "^1.0"
|
"phpstan/phpstan-strict-rules": "^1.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -653,32 +653,32 @@
|
|||||||
"description": "A RakNet server implementation written in PHP",
|
"description": "A RakNet server implementation written in PHP",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pmmp/RakLib/issues",
|
"issues": "https://github.com/pmmp/RakLib/issues",
|
||||||
"source": "https://github.com/pmmp/RakLib/tree/0.15.1"
|
"source": "https://github.com/pmmp/RakLib/tree/1.1.1"
|
||||||
},
|
},
|
||||||
"time": "2023-03-07T15:10:34+00:00"
|
"time": "2024-03-04T14:02:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/raklib-ipc",
|
"name": "pocketmine/raklib-ipc",
|
||||||
"version": "0.2.0",
|
"version": "1.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/RakLibIpc.git",
|
"url": "https://github.com/pmmp/RakLibIpc.git",
|
||||||
"reference": "26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c"
|
"reference": "ce632ef2c6743e71eddb5dc329c49af6555f90bc"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/RakLibIpc/zipball/26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c",
|
"url": "https://api.github.com/repos/pmmp/RakLibIpc/zipball/ce632ef2c6743e71eddb5dc329c49af6555f90bc",
|
||||||
"reference": "26ed56fa9db06e4ca6e8920c0ede2e01e219bb9c",
|
"reference": "ce632ef2c6743e71eddb5dc329c49af6555f90bc",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0",
|
"php": "^8.0",
|
||||||
"php-64bit": "*",
|
"php-64bit": "*",
|
||||||
"pocketmine/binaryutils": "^0.2.0",
|
"pocketmine/binaryutils": "^0.2.0",
|
||||||
"pocketmine/raklib": "^0.15.0"
|
"pocketmine/raklib": "^0.15.0 || ^1.0.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "1.9.17",
|
"phpstan/phpstan": "1.10.1",
|
||||||
"phpstan/phpstan-strict-rules": "^1.0.0"
|
"phpstan/phpstan-strict-rules": "^1.0.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -694,9 +694,9 @@
|
|||||||
"description": "Channel-based protocols for inter-thread/inter-process communication with RakLib",
|
"description": "Channel-based protocols for inter-thread/inter-process communication with RakLib",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pmmp/RakLibIpc/issues",
|
"issues": "https://github.com/pmmp/RakLibIpc/issues",
|
||||||
"source": "https://github.com/pmmp/RakLibIpc/tree/0.2.0"
|
"source": "https://github.com/pmmp/RakLibIpc/tree/1.0.1"
|
||||||
},
|
},
|
||||||
"time": "2023-02-13T13:40:40+00:00"
|
"time": "2024-03-01T15:55:05+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/snooze",
|
"name": "pocketmine/snooze",
|
||||||
|
@ -101,6 +101,8 @@ use pocketmine\player\Player;
|
|||||||
use pocketmine\player\PlayerInfo;
|
use pocketmine\player\PlayerInfo;
|
||||||
use pocketmine\player\UsedChunkStatus;
|
use pocketmine\player\UsedChunkStatus;
|
||||||
use pocketmine\player\XboxLivePlayerInfo;
|
use pocketmine\player\XboxLivePlayerInfo;
|
||||||
|
use pocketmine\promise\Promise;
|
||||||
|
use pocketmine\promise\PromiseResolver;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use pocketmine\timings\Timings;
|
use pocketmine\timings\Timings;
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
@ -159,15 +161,24 @@ class NetworkSession{
|
|||||||
|
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private array $sendBuffer = [];
|
private array $sendBuffer = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \SplQueue|CompressBatchPromise[]|string[]
|
* @var PromiseResolver[]
|
||||||
* @phpstan-var \SplQueue<CompressBatchPromise|string>
|
* @phpstan-var list<PromiseResolver<true>>
|
||||||
*/
|
*/
|
||||||
|
private array $sendBufferAckPromises = [];
|
||||||
|
|
||||||
|
/** @phpstan-var \SplQueue<array{CompressBatchPromise|string, list<PromiseResolver<true>>}> */
|
||||||
private \SplQueue $compressedQueue;
|
private \SplQueue $compressedQueue;
|
||||||
private bool $forceAsyncCompression = true;
|
private bool $forceAsyncCompression = true;
|
||||||
private bool $enableCompression = false; //disabled until handshake completed
|
private bool $enableCompression = false; //disabled until handshake completed
|
||||||
|
|
||||||
|
private int $nextAckReceiptId = 0;
|
||||||
|
/**
|
||||||
|
* @var PromiseResolver[][]
|
||||||
|
* @phpstan-var array<int, list<PromiseResolver<true>>>
|
||||||
|
*/
|
||||||
|
private array $ackPromisesByReceiptId = [];
|
||||||
|
|
||||||
private ?InventoryManager $invManager = null;
|
private ?InventoryManager $invManager = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -465,7 +476,23 @@ class NetworkSession{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendDataPacket(ClientboundPacket $packet, bool $immediate = false) : bool{
|
public function handleAckReceipt(int $receiptId) : void{
|
||||||
|
if(!$this->connected){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(isset($this->ackPromisesByReceiptId[$receiptId])){
|
||||||
|
$promises = $this->ackPromisesByReceiptId[$receiptId];
|
||||||
|
unset($this->ackPromisesByReceiptId[$receiptId]);
|
||||||
|
foreach($promises as $promise){
|
||||||
|
$promise->resolve(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-param PromiseResolver<true>|null $ackReceiptResolver
|
||||||
|
*/
|
||||||
|
private function sendDataPacketInternal(ClientboundPacket $packet, bool $immediate, ?PromiseResolver $ackReceiptResolver) : bool{
|
||||||
if(!$this->connected){
|
if(!$this->connected){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -488,6 +515,9 @@ class NetworkSession{
|
|||||||
$packets = [$packet];
|
$packets = [$packet];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($ackReceiptResolver !== null){
|
||||||
|
$this->sendBufferAckPromises[] = $ackReceiptResolver;
|
||||||
|
}
|
||||||
foreach($packets as $evPacket){
|
foreach($packets as $evPacket){
|
||||||
$this->addToSendBuffer(self::encodePacketTimed(PacketSerializer::encoder(), $evPacket));
|
$this->addToSendBuffer(self::encodePacketTimed(PacketSerializer::encoder(), $evPacket));
|
||||||
}
|
}
|
||||||
@ -501,6 +531,23 @@ class NetworkSession{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sendDataPacket(ClientboundPacket $packet, bool $immediate = false) : bool{
|
||||||
|
return $this->sendDataPacketInternal($packet, $immediate, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-return Promise<true>
|
||||||
|
*/
|
||||||
|
public function sendDataPacketWithReceipt(ClientboundPacket $packet, bool $immediate = false) : Promise{
|
||||||
|
$resolver = new PromiseResolver();
|
||||||
|
|
||||||
|
if(!$this->sendDataPacketInternal($packet, $immediate, $resolver)){
|
||||||
|
$resolver->reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resolver->getPromise();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -542,7 +589,9 @@ class NetworkSession{
|
|||||||
$batch = $stream->getBuffer();
|
$batch = $stream->getBuffer();
|
||||||
}
|
}
|
||||||
$this->sendBuffer = [];
|
$this->sendBuffer = [];
|
||||||
$this->queueCompressedNoBufferFlush($batch, $immediate);
|
$ackPromises = $this->sendBufferAckPromises;
|
||||||
|
$this->sendBufferAckPromises = [];
|
||||||
|
$this->queueCompressedNoBufferFlush($batch, $immediate, $ackPromises);
|
||||||
}finally{
|
}finally{
|
||||||
Timings::$playerNetworkSend->stopTiming();
|
Timings::$playerNetworkSend->stopTiming();
|
||||||
}
|
}
|
||||||
@ -569,22 +618,27 @@ class NetworkSession{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function queueCompressedNoBufferFlush(CompressBatchPromise|string $batch, bool $immediate = false) : void{
|
/**
|
||||||
|
* @param PromiseResolver[] $ackPromises
|
||||||
|
*
|
||||||
|
* @phpstan-param list<PromiseResolver<true>> $ackPromises
|
||||||
|
*/
|
||||||
|
private function queueCompressedNoBufferFlush(CompressBatchPromise|string $batch, bool $immediate = false, array $ackPromises = []) : void{
|
||||||
Timings::$playerNetworkSend->startTiming();
|
Timings::$playerNetworkSend->startTiming();
|
||||||
try{
|
try{
|
||||||
if(is_string($batch)){
|
if(is_string($batch)){
|
||||||
if($immediate){
|
if($immediate){
|
||||||
//Skips all queues
|
//Skips all queues
|
||||||
$this->sendEncoded($batch, true);
|
$this->sendEncoded($batch, true, $ackPromises);
|
||||||
}else{
|
}else{
|
||||||
$this->compressedQueue->enqueue($batch);
|
$this->compressedQueue->enqueue([$batch, $ackPromises]);
|
||||||
$this->flushCompressedQueue();
|
$this->flushCompressedQueue();
|
||||||
}
|
}
|
||||||
}elseif($immediate){
|
}elseif($immediate){
|
||||||
//Skips all queues
|
//Skips all queues
|
||||||
$this->sendEncoded($batch->getResult(), true);
|
$this->sendEncoded($batch->getResult(), true, $ackPromises);
|
||||||
}else{
|
}else{
|
||||||
$this->compressedQueue->enqueue($batch);
|
$this->compressedQueue->enqueue([$batch, $ackPromises]);
|
||||||
$batch->onResolve(function() : void{
|
$batch->onResolve(function() : void{
|
||||||
if($this->connected){
|
if($this->connected){
|
||||||
$this->flushCompressedQueue();
|
$this->flushCompressedQueue();
|
||||||
@ -601,14 +655,14 @@ class NetworkSession{
|
|||||||
try{
|
try{
|
||||||
while(!$this->compressedQueue->isEmpty()){
|
while(!$this->compressedQueue->isEmpty()){
|
||||||
/** @var CompressBatchPromise|string $current */
|
/** @var CompressBatchPromise|string $current */
|
||||||
$current = $this->compressedQueue->bottom();
|
[$current, $ackPromises] = $this->compressedQueue->bottom();
|
||||||
if(is_string($current)){
|
if(is_string($current)){
|
||||||
$this->compressedQueue->dequeue();
|
$this->compressedQueue->dequeue();
|
||||||
$this->sendEncoded($current);
|
$this->sendEncoded($current, false, $ackPromises);
|
||||||
|
|
||||||
}elseif($current->hasResult()){
|
}elseif($current->hasResult()){
|
||||||
$this->compressedQueue->dequeue();
|
$this->compressedQueue->dequeue();
|
||||||
$this->sendEncoded($current->getResult());
|
$this->sendEncoded($current->getResult(), false, $ackPromises);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
//can't send any more queued until this one is ready
|
//can't send any more queued until this one is ready
|
||||||
@ -620,13 +674,24 @@ class NetworkSession{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendEncoded(string $payload, bool $immediate = false) : void{
|
/**
|
||||||
|
* @param PromiseResolver[] $ackPromises
|
||||||
|
* @phpstan-param list<PromiseResolver<true>> $ackPromises
|
||||||
|
*/
|
||||||
|
private function sendEncoded(string $payload, bool $immediate, array $ackPromises) : void{
|
||||||
if($this->cipher !== null){
|
if($this->cipher !== null){
|
||||||
Timings::$playerNetworkSendEncrypt->startTiming();
|
Timings::$playerNetworkSendEncrypt->startTiming();
|
||||||
$payload = $this->cipher->encrypt($payload);
|
$payload = $this->cipher->encrypt($payload);
|
||||||
Timings::$playerNetworkSendEncrypt->stopTiming();
|
Timings::$playerNetworkSendEncrypt->stopTiming();
|
||||||
}
|
}
|
||||||
$this->sender->send($payload, $immediate);
|
|
||||||
|
if(count($ackPromises) > 0){
|
||||||
|
$ackReceiptId = $this->nextAckReceiptId++;
|
||||||
|
$this->ackPromisesByReceiptId[$ackReceiptId] = $ackPromises;
|
||||||
|
}else{
|
||||||
|
$ackReceiptId = null;
|
||||||
|
}
|
||||||
|
$this->sender->send($payload, $immediate, $ackReceiptId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -646,6 +711,19 @@ class NetworkSession{
|
|||||||
$this->setHandler(null);
|
$this->setHandler(null);
|
||||||
$this->connected = false;
|
$this->connected = false;
|
||||||
|
|
||||||
|
$ackPromisesByReceiptId = $this->ackPromisesByReceiptId;
|
||||||
|
$this->ackPromisesByReceiptId = [];
|
||||||
|
foreach($ackPromisesByReceiptId as $resolvers){
|
||||||
|
foreach($resolvers as $resolver){
|
||||||
|
$resolver->reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sendBufferAckPromises = $this->sendBufferAckPromises;
|
||||||
|
$this->sendBufferAckPromises = [];
|
||||||
|
foreach($sendBufferAckPromises as $resolver){
|
||||||
|
$resolver->reject();
|
||||||
|
}
|
||||||
|
|
||||||
$this->logger->info($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_network_session_close($reason)));
|
$this->logger->info($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_network_session_close($reason)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ interface PacketSender{
|
|||||||
/**
|
/**
|
||||||
* Pushes a packet into the channel to be processed.
|
* Pushes a packet into the channel to be processed.
|
||||||
*/
|
*/
|
||||||
public function send(string $payload, bool $immediate) : void;
|
public function send(string $payload, bool $immediate, ?int $receiptId) : void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the channel, terminating the connection.
|
* Closes the channel, terminating the connection.
|
||||||
|
@ -51,7 +51,13 @@ use function substr;
|
|||||||
* packs to the client.
|
* packs to the client.
|
||||||
*/
|
*/
|
||||||
class ResourcePacksPacketHandler extends PacketHandler{
|
class ResourcePacksPacketHandler extends PacketHandler{
|
||||||
private const PACK_CHUNK_SIZE = 128 * 1024; //128KB
|
private const PACK_CHUNK_SIZE = 256 * 1024; //256KB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Larger values allow downloading more chunks at the same time, increasing download speed, but the client may choke
|
||||||
|
* and cause the download speed to drop (due to ACKs taking too long to arrive).
|
||||||
|
*/
|
||||||
|
private const MAX_CONCURRENT_CHUNK_REQUESTS = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ResourcePack[]
|
* @var ResourcePack[]
|
||||||
@ -62,6 +68,11 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
|||||||
/** @var bool[][] uuid => [chunk index => hasSent] */
|
/** @var bool[][] uuid => [chunk index => hasSent] */
|
||||||
private array $downloadedChunks = [];
|
private array $downloadedChunks = [];
|
||||||
|
|
||||||
|
/** @phpstan-var \SplQueue<array{ResourcePack, int}> */
|
||||||
|
private \SplQueue $requestQueue;
|
||||||
|
|
||||||
|
private int $activeRequests = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ResourcePack[] $resourcePackStack
|
* @param ResourcePack[] $resourcePackStack
|
||||||
* @param string[] $encryptionKeys pack UUID => key, leave unset for any packs that are not encrypted
|
* @param string[] $encryptionKeys pack UUID => key, leave unset for any packs that are not encrypted
|
||||||
@ -77,6 +88,7 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
|||||||
private bool $mustAccept,
|
private bool $mustAccept,
|
||||||
private \Closure $completionCallback
|
private \Closure $completionCallback
|
||||||
){
|
){
|
||||||
|
$this->requestQueue = new \SplQueue();
|
||||||
foreach($resourcePackStack as $pack){
|
foreach($resourcePackStack as $pack){
|
||||||
$this->resourcePacksById[$pack->getPackId()] = $pack;
|
$this->resourcePacksById[$pack->getPackId()] = $pack;
|
||||||
}
|
}
|
||||||
@ -197,8 +209,37 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
|||||||
$this->downloadedChunks[$packId][$packet->chunkIndex] = true;
|
$this->downloadedChunks[$packId][$packet->chunkIndex] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->sendDataPacket(ResourcePackChunkDataPacket::create($packId, $packet->chunkIndex, $offset, $pack->getPackChunk($offset, self::PACK_CHUNK_SIZE)));
|
$this->requestQueue->enqueue([$pack, $packet->chunkIndex]);
|
||||||
|
$this->processChunkRequestQueue();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function processChunkRequestQueue() : void{
|
||||||
|
if($this->activeRequests >= self::MAX_CONCURRENT_CHUNK_REQUESTS || $this->requestQueue->isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @var ResourcePack $pack
|
||||||
|
* @var int $chunkIndex
|
||||||
|
*/
|
||||||
|
[$pack, $chunkIndex] = $this->requestQueue->dequeue();
|
||||||
|
|
||||||
|
$packId = $pack->getPackId();
|
||||||
|
$offset = $chunkIndex * self::PACK_CHUNK_SIZE;
|
||||||
|
$chunkData = $pack->getPackChunk($offset, self::PACK_CHUNK_SIZE);
|
||||||
|
$this->activeRequests++;
|
||||||
|
$this->session
|
||||||
|
->sendDataPacketWithReceipt(ResourcePackChunkDataPacket::create($packId, $chunkIndex, $offset, $chunkData))
|
||||||
|
->onCompletion(
|
||||||
|
function() : void{
|
||||||
|
$this->activeRequests--;
|
||||||
|
$this->processChunkRequestQueue();
|
||||||
|
},
|
||||||
|
function() : void{
|
||||||
|
//this may have been rejected because of a disconnection - this will do nothing in that case
|
||||||
|
$this->disconnectWithError("Plugin interrupted sending of resource packs");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,9 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onPacketAck(int $sessionId, int $identifierACK) : void{
|
public function onPacketAck(int $sessionId, int $identifierACK) : void{
|
||||||
|
if(isset($this->sessions[$sessionId])){
|
||||||
|
$this->sessions[$sessionId]->handleAckReceipt($identifierACK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName(string $name) : void{
|
public function setName(string $name) : void{
|
||||||
@ -289,12 +291,13 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
|||||||
$this->network->getBandwidthTracker()->add($bytesSentDiff, $bytesReceivedDiff);
|
$this->network->getBandwidthTracker()->add($bytesSentDiff, $bytesReceivedDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function putPacket(int $sessionId, string $payload, bool $immediate = true) : void{
|
public function putPacket(int $sessionId, string $payload, bool $immediate = true, ?int $receiptId = null) : void{
|
||||||
if(isset($this->sessions[$sessionId])){
|
if(isset($this->sessions[$sessionId])){
|
||||||
$pk = new EncapsulatedPacket();
|
$pk = new EncapsulatedPacket();
|
||||||
$pk->buffer = self::MCPE_RAKNET_PACKET_ID . $payload;
|
$pk->buffer = self::MCPE_RAKNET_PACKET_ID . $payload;
|
||||||
$pk->reliability = PacketReliability::RELIABLE_ORDERED;
|
$pk->reliability = PacketReliability::RELIABLE_ORDERED;
|
||||||
$pk->orderChannel = 0;
|
$pk->orderChannel = 0;
|
||||||
|
$pk->identifierACK = $receiptId;
|
||||||
|
|
||||||
$this->interface->sendEncapsulated($sessionId, $pk, $immediate);
|
$this->interface->sendEncapsulated($sessionId, $pk, $immediate);
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,9 @@ class RakLibPacketSender implements PacketSender{
|
|||||||
private RakLibInterface $handler
|
private RakLibInterface $handler
|
||||||
){}
|
){}
|
||||||
|
|
||||||
public function send(string $payload, bool $immediate) : void{
|
public function send(string $payload, bool $immediate, ?int $receiptId) : void{
|
||||||
if(!$this->closed){
|
if(!$this->closed){
|
||||||
$this->handler->putPacket($this->sessionId, $payload, $immediate);
|
$this->handler->putPacket($this->sessionId, $payload, $immediate, $receiptId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user