mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-05 11:27:07 +00:00
Merge branch 'next-minor' into next-major
This commit is contained in:
commit
ffa88aff67
@ -37,7 +37,7 @@
|
||||
"pocketmine/bedrock-block-upgrade-schema": "dev-master@dev",
|
||||
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "dev-master",
|
||||
"pocketmine/bedrock-protocol": "~17.0.0+bedrock-1.19.50",
|
||||
"pocketmine/bedrock-protocol": "~17.1.0+bedrock-1.19.50",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
|
16
composer.lock
generated
16
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "6c40129ef11a3cfc79081b8f53edda8e",
|
||||
"content-hash": "614023b483badb5ec8720775dd2d3d12",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -329,16 +329,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "17.0.0+bedrock-1.19.50",
|
||||
"version": "17.1.0+bedrock-1.19.50",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "272e10197bb1603c0a81075bf5b9dae0d081a6e2"
|
||||
"reference": "c572706cf5e3202718dd35a35dd30fe08cd671de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/272e10197bb1603c0a81075bf5b9dae0d081a6e2",
|
||||
"reference": "272e10197bb1603c0a81075bf5b9dae0d081a6e2",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c572706cf5e3202718dd35a35dd30fe08cd671de",
|
||||
"reference": "c572706cf5e3202718dd35a35dd30fe08cd671de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -352,7 +352,7 @@
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.9.0",
|
||||
"phpstan/phpstan": "1.9.3",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
@ -370,9 +370,9 @@
|
||||
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/17.0.0+bedrock-1.19.50"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/17.1.0+bedrock-1.19.50"
|
||||
},
|
||||
"time": "2022-11-30T16:16:27+00:00"
|
||||
"time": "2022-12-15T20:34:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
|
@ -378,7 +378,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
||||
array_values($this->inventory->getContents()),
|
||||
array_values($this->armorInventory->getContents()),
|
||||
array_values($this->offHandInventory->getContents()),
|
||||
), function(Item $item) : bool{ return !$item->hasEnchantment(VanillaEnchantments::VANISHING()); });
|
||||
), function(Item $item) : bool{ return !$item->hasEnchantment(VanillaEnchantments::VANISHING()) && !$item->keepOnDeath(); });
|
||||
}
|
||||
|
||||
public function saveNBT() : CompoundTag{
|
||||
|
@ -66,6 +66,8 @@ class Item implements \JsonSerializable{
|
||||
public const TAG_DISPLAY_NAME = "Name";
|
||||
public const TAG_DISPLAY_LORE = "Lore";
|
||||
|
||||
public const TAG_KEEP_ON_DEATH = "minecraft:keep_on_death";
|
||||
|
||||
private CompoundTag $nbt;
|
||||
|
||||
protected int $count = 1;
|
||||
@ -89,6 +91,8 @@ class Item implements \JsonSerializable{
|
||||
*/
|
||||
protected array $canDestroy = [];
|
||||
|
||||
protected bool $keepOnDeath = false;
|
||||
|
||||
/**
|
||||
* Constructs a new Item type. This constructor should ONLY be used when constructing a new item TYPE to register
|
||||
* into the index.
|
||||
@ -213,6 +217,17 @@ class Item implements \JsonSerializable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether players will retain this item on death. If a non-player dies it will be excluded from the drops.
|
||||
*/
|
||||
public function keepOnDeath() : bool{
|
||||
return $this->keepOnDeath;
|
||||
}
|
||||
|
||||
public function setKeepOnDeath(bool $keepOnDeath) : void{
|
||||
$this->keepOnDeath = $keepOnDeath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this Item has a non-empty NBT.
|
||||
*/
|
||||
@ -311,6 +326,8 @@ class Item implements \JsonSerializable{
|
||||
$this->canDestroy[$entry->getValue()] = $entry->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
$this->keepOnDeath = $tag->getByte(self::TAG_KEEP_ON_DEATH, 0) !== 0;
|
||||
}
|
||||
|
||||
protected function serializeCompoundTag(CompoundTag $tag) : void{
|
||||
@ -368,6 +385,12 @@ class Item implements \JsonSerializable{
|
||||
}else{
|
||||
$tag->removeTag("CanDestroy");
|
||||
}
|
||||
|
||||
if($this->keepOnDeath){
|
||||
$tag->setByte(self::TAG_KEEP_ON_DEATH, 1);
|
||||
}else{
|
||||
$tag->removeTag(self::TAG_KEEP_ON_DEATH);
|
||||
}
|
||||
}
|
||||
|
||||
public function getCount() : int{
|
||||
|
@ -131,6 +131,7 @@ use pocketmine\world\sound\Sound;
|
||||
use pocketmine\world\World;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use function abs;
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function array_shift;
|
||||
use function assert;
|
||||
@ -2280,10 +2281,11 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->getWorld()->dropItem($this->location, $item);
|
||||
}
|
||||
|
||||
$clearInventory = fn(Inventory $inventory) => $inventory->setContents(array_filter($inventory->getContents(), fn(Item $item) => $item->keepOnDeath()));
|
||||
$this->inventory->setHeldItemIndex(0);
|
||||
$this->inventory->clearAll();
|
||||
$this->armorInventory->clearAll();
|
||||
$this->offHandInventory->clearAll();
|
||||
$clearInventory($this->inventory);
|
||||
$clearInventory($this->armorInventory);
|
||||
$clearInventory($this->offHandInventory);
|
||||
}
|
||||
|
||||
if(!$ev->getKeepXp()){
|
||||
|
@ -38,6 +38,8 @@ use function is_float;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function mkdir;
|
||||
use function rtrim;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
@ -93,41 +95,26 @@ class ResourcePackManager{
|
||||
}
|
||||
$pack = (string) $pack;
|
||||
try{
|
||||
$packPath = Path::join($this->path, $pack);
|
||||
if(!file_exists($packPath)){
|
||||
throw new ResourcePackException("File or directory not found");
|
||||
}
|
||||
if(is_dir($packPath)){
|
||||
throw new ResourcePackException("Directory resource packs are unsupported");
|
||||
}
|
||||
$newPack = $this->loadPackFromPath(Path::join($this->path, $pack));
|
||||
|
||||
$newPack = null;
|
||||
//Detect the type of resource pack.
|
||||
$info = new \SplFileInfo($packPath);
|
||||
switch($info->getExtension()){
|
||||
case "zip":
|
||||
case "mcpack":
|
||||
$newPack = new ZippedResourcePack($packPath);
|
||||
break;
|
||||
}
|
||||
$this->resourcePacks[] = $newPack;
|
||||
$index = strtolower($newPack->getPackId());
|
||||
$this->uuidList[$index] = $newPack;
|
||||
|
||||
if($newPack instanceof ResourcePack){
|
||||
$this->resourcePacks[] = $newPack;
|
||||
$index = strtolower($newPack->getPackId());
|
||||
$this->uuidList[$index] = $newPack;
|
||||
|
||||
$keyPath = Path::join($this->path, $pack . ".key");
|
||||
if(file_exists($keyPath)){
|
||||
try{
|
||||
$this->encryptionKeys[$index] = ErrorToExceptionHandler::trapAndRemoveFalse(
|
||||
fn() => file_get_contents($keyPath)
|
||||
);
|
||||
}catch(\ErrorException $e){
|
||||
throw new ResourcePackException("Could not read encryption key file: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
$keyPath = Path::join($this->path, $pack . ".key");
|
||||
if(file_exists($keyPath)){
|
||||
try{
|
||||
$key = ErrorToExceptionHandler::trapAndRemoveFalse(
|
||||
fn() => file_get_contents($keyPath)
|
||||
);
|
||||
}catch(\ErrorException $e){
|
||||
throw new ResourcePackException("Could not read encryption key file: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
}else{
|
||||
throw new ResourcePackException("Format not recognized");
|
||||
$key = rtrim($key, "\r\n");
|
||||
if(strlen($key) !== 32){
|
||||
throw new ResourcePackException("Invalid encryption key length, must be exactly 32 bytes");
|
||||
}
|
||||
$this->encryptionKeys[$index] = $key;
|
||||
}
|
||||
}catch(ResourcePackException $e){
|
||||
$logger->critical("Could not load resource pack \"$pack\": " . $e->getMessage());
|
||||
@ -137,6 +124,25 @@ class ResourcePackManager{
|
||||
$logger->debug("Successfully loaded " . count($this->resourcePacks) . " resource packs");
|
||||
}
|
||||
|
||||
private function loadPackFromPath(string $packPath) : ResourcePack{
|
||||
if(!file_exists($packPath)){
|
||||
throw new ResourcePackException("File or directory not found");
|
||||
}
|
||||
if(is_dir($packPath)){
|
||||
throw new ResourcePackException("Directory resource packs are unsupported");
|
||||
}
|
||||
|
||||
//Detect the type of resource pack.
|
||||
$info = new \SplFileInfo($packPath);
|
||||
switch($info->getExtension()){
|
||||
case "zip":
|
||||
case "mcpack":
|
||||
return new ZippedResourcePack($packPath);
|
||||
}
|
||||
|
||||
throw new ResourcePackException("Format not recognized");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory which resource packs are loaded from.
|
||||
*/
|
||||
@ -159,6 +165,29 @@ class ResourcePackManager{
|
||||
return $this->resourcePacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource packs to use. Packs earliest in the list will appear at the top of the stack (maximum
|
||||
* priority), and later ones will appear below (lower priority), in the same manner as the Bedrock resource packs
|
||||
* screen in-game.
|
||||
*
|
||||
* @param ResourcePack[] $resourceStack
|
||||
* @phpstan-param list<ResourcePack> $resourceStack
|
||||
*/
|
||||
public function setResourceStack(array $resourceStack) : void{
|
||||
$uuidList = [];
|
||||
$resourcePacks = [];
|
||||
foreach($resourceStack as $pack){
|
||||
$uuid = strtolower($pack->getPackId());
|
||||
if(isset($uuidList[$uuid])){
|
||||
throw new \InvalidArgumentException("Cannot load two resource pack with the same UUID ($uuid)");
|
||||
}
|
||||
$uuidList[$uuid] = $pack;
|
||||
$resourcePacks[] = $pack;
|
||||
}
|
||||
$this->resourcePacks = $resourcePacks;
|
||||
$this->uuidList = $uuidList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource pack matching the specified UUID string, or null if the ID was not recognized.
|
||||
*/
|
||||
@ -180,4 +209,23 @@ class ResourcePackManager{
|
||||
public function getPackEncryptionKey(string $id) : ?string{
|
||||
return $this->encryptionKeys[strtolower($id)] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the encryption key to use for decrypting the specified resource pack. The pack will **NOT** be decrypted by
|
||||
* PocketMine-MP; the key is simply passed to the client to allow it to decrypt the pack after downloading it.
|
||||
*/
|
||||
public function setPackEncryptionKey(string $id, ?string $key) : void{
|
||||
$id = strtolower($id);
|
||||
if($key === null){
|
||||
//allow deprovisioning keys for resource packs that have been removed
|
||||
unset($this->encryptionKeys[$id]);
|
||||
}elseif(isset($this->uuidList[$id])){
|
||||
if(strlen($key) !== 32){
|
||||
throw new \InvalidArgumentException("Encryption key must be exactly 32 bytes long");
|
||||
}
|
||||
$this->encryptionKeys[$id] = $key;
|
||||
}else{
|
||||
throw new \InvalidArgumentException("Unknown pack ID $id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user