mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Added resource packs support
This commit is contained in:
parent
1f2b584400
commit
d41bdfc31c
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@ timings/*
|
||||
server.properties
|
||||
/pocketmine.yml
|
||||
memoryDump_*/*
|
||||
resource_packs/
|
||||
|
||||
# Common IDEs
|
||||
.idea/
|
||||
|
@ -189,6 +189,7 @@ use pocketmine\network\SourceInterface;
|
||||
use pocketmine\permission\PermissibleBase;
|
||||
use pocketmine\permission\PermissionAttachment;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\resourcepacks\ResourcePack;
|
||||
use pocketmine\tile\ItemFrame;
|
||||
use pocketmine\tile\Spawnable;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -1934,7 +1935,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->sendPlayStatus(PlayStatusPacket::LOGIN_SUCCESS);
|
||||
|
||||
$pk = new ResourcePacksInfoPacket();
|
||||
$this->dataPacket($pk); //TODO: add resource packs stuff
|
||||
$manager = $this->server->getResourceManager();
|
||||
$pk->resourcePackEntries = $manager->getResourceStack();
|
||||
$pk->mustAccept = $manager->resourcePacksRequired();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1984,11 +1988,31 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->close("", "must accept resource packs to join", true);
|
||||
break;
|
||||
case ResourcePackClientResponsePacket::STATUS_SEND_PACKS:
|
||||
//TODO
|
||||
$manager = $this->server->getResourceManager();
|
||||
foreach($packet->packIds as $uuid){
|
||||
$pack = $manager->getPackById($uuid);
|
||||
if(!($pack instanceof ResourcePack)){
|
||||
//Client requested a resource pack but we don't have it available on the server
|
||||
$this->close("", "disconnectionScreen.resourcePack", true); //TODO: add strings to lang files
|
||||
break;
|
||||
}
|
||||
|
||||
$pk = new ResourcePackDataInfoPacket();
|
||||
$pk->packId = $pack->getPackId();
|
||||
$pk->maxChunkSize = 1048576; //1MB
|
||||
$pk->chunkCount = $pack->getPackSize() / $pk->maxChunkSize;
|
||||
$pk->compressedPackSize = $pack->getPackSize();
|
||||
$pk->sha256 = $pack->getSha256();
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
break;
|
||||
case ResourcePackClientResponsePacket::STATUS_HAVE_ALL_PACKS:
|
||||
$pk = new ResourcePackStackPacket();
|
||||
$this->dataPacket($pk); //TODO: send resource stack
|
||||
$manager = $this->server->getResourceManager();
|
||||
$pk->resourcePackStack = $manager->getResourceStack();
|
||||
$pk->mustAccept = $manager->resourcePacksRequired();
|
||||
$this->dataPacket($pk);
|
||||
break;
|
||||
case ResourcePackClientResponsePacket::STATUS_COMPLETED:
|
||||
$this->processLogin();
|
||||
@ -3292,7 +3316,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
public function handleResourcePackChunkRequest(ResourcePackChunkRequestPacket $packet) : bool{
|
||||
return false;
|
||||
$manager = $this->server->getResourceManager();
|
||||
$pack = $manager->getPackById($packet->packId);
|
||||
if(!($pack instanceof ResourcePack)){
|
||||
$this->close("", "disconnectionScreen.resourcePack", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
$pk = new ResourcePackChunkDataPacket();
|
||||
$pk->packId = $pack->getPackId();
|
||||
$pk->chunkIndex = $packet->chunkIndex;
|
||||
$pk->data = $pack->getPackChunk(1048576 * $packet->chunkIndex, 1048576);
|
||||
$pk->progress = (1048576 * $packet->chunkIndex);
|
||||
$this->dataPacket($pk);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleTransfer(TransferPacket $packet) : bool{
|
||||
|
@ -446,6 +446,11 @@ namespace pocketmine {
|
||||
++$errors;
|
||||
}
|
||||
|
||||
if(!extension_loaded("openssl")){
|
||||
$logger->critical("Unable to find the OpenSSL extension.");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$logger->shutdown();
|
||||
|
@ -90,6 +90,7 @@ use pocketmine\plugin\Plugin;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\plugin\ScriptPluginLoader;
|
||||
use pocketmine\resourcepacks\ResourcePackManager;
|
||||
use pocketmine\scheduler\FileWriteTask;
|
||||
use pocketmine\scheduler\SendUsageTask;
|
||||
use pocketmine\scheduler\ServerScheduler;
|
||||
@ -176,6 +177,9 @@ class Server{
|
||||
/** @var CraftingManager */
|
||||
private $craftingManager;
|
||||
|
||||
/** @var ResourcePackManager */
|
||||
private $resourceManager;
|
||||
|
||||
/** @var ConsoleCommandSender */
|
||||
private $consoleSender;
|
||||
|
||||
@ -594,6 +598,13 @@ class Server{
|
||||
return $this->craftingManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResourcePackManager
|
||||
*/
|
||||
public function getResourceManager() : ResourcePackManager{
|
||||
return $this->resourceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ServerScheduler
|
||||
*/
|
||||
@ -1510,6 +1521,8 @@ class Server{
|
||||
Attribute::init();
|
||||
$this->craftingManager = new CraftingManager();
|
||||
|
||||
$this->resourceManager = new ResourcePackManager($this, \pocketmine\PATH . "resource_packs" . DIRECTORY_SEPARATOR);
|
||||
|
||||
$this->pluginManager = new PluginManager($this, $this->commandMap);
|
||||
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
|
||||
$this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false));
|
||||
@ -2165,9 +2178,7 @@ class Server{
|
||||
|
||||
private function checkTickUpdates($currentTick, $tickTime){
|
||||
foreach($this->players as $p){
|
||||
if(!$p->loggedIn and ($tickTime - $p->creationTime) >= 10){
|
||||
$p->close("", "Login timeout");
|
||||
}elseif($this->alwaysTickPlayers){
|
||||
if($this->alwaysTickPlayers){
|
||||
$p->onUpdate($currentTick);
|
||||
}
|
||||
}
|
||||
|
@ -31,21 +31,22 @@ class ResourcePackChunkDataPacket extends DataPacket{
|
||||
const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_CHUNK_DATA_PACKET;
|
||||
|
||||
public $packId;
|
||||
public $unknown1;
|
||||
public $unknown2;
|
||||
public $chunkIndex;
|
||||
public $progress;
|
||||
public $data;
|
||||
|
||||
public function decode(){
|
||||
$this->packId = $this->getString();
|
||||
$this->unknown1 = $this->getLInt();
|
||||
$this->unknown2 = $this->getLLong();
|
||||
$this->chunkIndex = $this->getLInt();
|
||||
$this->progress = $this->getLLong();
|
||||
$this->data = $this->get($this->getLInt());
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
$this->reset();
|
||||
$this->putString($this->packId);
|
||||
$this->putLInt($this->unknown1);
|
||||
$this->putLLong($this->unknown2);
|
||||
$this->putLInt($this->chunkIndex);
|
||||
$this->putLLong($this->progress);
|
||||
$this->putLInt(strlen($this->data));
|
||||
$this->put($this->data);
|
||||
}
|
||||
|
@ -31,17 +31,17 @@ class ResourcePackChunkRequestPacket extends DataPacket{
|
||||
const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_CHUNK_REQUEST_PACKET;
|
||||
|
||||
public $packId;
|
||||
public $unknown;
|
||||
public $chunkIndex;
|
||||
|
||||
public function decode(){
|
||||
$this->packId = $this->getString();
|
||||
$this->unknown = $this->getLInt();
|
||||
$this->chunkIndex = $this->getLInt();
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
$this->reset();
|
||||
$this->putString($this->packId);
|
||||
$this->putLInt($this->unknown);
|
||||
$this->putLInt($this->chunkIndex);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -31,26 +31,26 @@ class ResourcePackDataInfoPacket extends DataPacket{
|
||||
const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_DATA_INFO_PACKET;
|
||||
|
||||
public $packId;
|
||||
public $int1;
|
||||
public $int2;
|
||||
public $packSize;
|
||||
public $unknown;
|
||||
public $maxChunkSize;
|
||||
public $chunkCount;
|
||||
public $compressedPackSize;
|
||||
public $sha256;
|
||||
|
||||
public function decode(){
|
||||
$this->packId = $this->getString();
|
||||
$this->int1 = $this->getLInt();
|
||||
$this->int2 = $this->getLInt();
|
||||
$this->packSize = $this->getLLong();
|
||||
$this->unknown = $this->getString();
|
||||
$this->maxChunkSize = $this->getLInt();
|
||||
$this->chunkCount = $this->getLInt();
|
||||
$this->compressedPackSize = $this->getLLong();
|
||||
$this->sha256 = $this->getString();
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
$this->reset();
|
||||
$this->putString($this->packId);
|
||||
$this->putLInt($this->int1);
|
||||
$this->putLInt($this->int2);
|
||||
$this->putLLong($this->packSize);
|
||||
$this->putString($this->unknown);
|
||||
$this->putLInt($this->maxChunkSize);
|
||||
$this->putLInt($this->chunkCount);
|
||||
$this->putLLong($this->compressedPackSize);
|
||||
$this->putString($this->sha256);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\resourcepacks\ResourcePack;
|
||||
use pocketmine\resourcepacks\ResourcePackInfoEntry;
|
||||
|
||||
class ResourcePackStackPacket extends DataPacket{
|
||||
@ -33,13 +34,13 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
|
||||
public $mustAccept = false;
|
||||
|
||||
/** @var ResourcePackInfoEntry[] */
|
||||
/** @var ResourcePack[] */
|
||||
public $behaviorPackStack = [];
|
||||
/** @var ResourcePackInfoEntry[] */
|
||||
/** @var ResourcePack[] */
|
||||
public $resourcePackStack = [];
|
||||
|
||||
public function decode(){
|
||||
$this->mustAccept = $this->getBool();
|
||||
/*$this->mustAccept = $this->getBool();
|
||||
$behaviorPackCount = $this->getLShort();
|
||||
while($behaviorPackCount-- > 0){
|
||||
$packId = $this->getString();
|
||||
@ -52,7 +53,7 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
$packId = $this->getString();
|
||||
$version = $this->getString();
|
||||
$this->resourcePackStack[] = new ResourcePackInfoEntry($packId, $version);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
@ -62,13 +63,13 @@ class ResourcePackStackPacket extends DataPacket{
|
||||
$this->putLShort(count($this->behaviorPackStack));
|
||||
foreach($this->behaviorPackStack as $entry){
|
||||
$this->putString($entry->getPackId());
|
||||
$this->putString($entry->getVersion());
|
||||
$this->putString($entry->getPackVersion());
|
||||
}
|
||||
|
||||
$this->putLShort(count($this->resourcePackStack));
|
||||
foreach($this->resourcePackStack as $entry){
|
||||
$this->putString($entry->getPackId());
|
||||
$this->putString($entry->getVersion());
|
||||
$this->putString($entry->getPackVersion());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,19 +25,20 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\resourcepacks\ResourcePack;
|
||||
use pocketmine\resourcepacks\ResourcePackInfoEntry;
|
||||
|
||||
class ResourcePacksInfoPacket extends DataPacket{
|
||||
const NETWORK_ID = ProtocolInfo::RESOURCE_PACKS_INFO_PACKET;
|
||||
|
||||
public $mustAccept = false; //if true, forces client to use selected resource packs
|
||||
/** @var ResourcePackInfoEntry[] */
|
||||
/** @var ResourcePack[] */
|
||||
public $behaviorPackEntries = [];
|
||||
/** @var ResourcePackInfoEntry[] */
|
||||
/** @var ResourcePack[] */
|
||||
public $resourcePackEntries = [];
|
||||
|
||||
public function decode(){
|
||||
$this->mustAccept = $this->getBool();
|
||||
/*$this->mustAccept = $this->getBool();
|
||||
$behaviorPackCount = $this->getLShort();
|
||||
while($behaviorPackCount-- > 0){
|
||||
$id = $this->getString();
|
||||
@ -52,7 +53,7 @@ class ResourcePacksInfoPacket extends DataPacket{
|
||||
$version = $this->getString();
|
||||
$size = $this->getLLong();
|
||||
$this->resourcePackEntries[] = new ResourcePackInfoEntry($id, $version, $size);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public function encode(){
|
||||
@ -62,13 +63,13 @@ class ResourcePacksInfoPacket extends DataPacket{
|
||||
$this->putLShort(count($this->behaviorPackEntries));
|
||||
foreach($this->behaviorPackEntries as $entry){
|
||||
$this->putString($entry->getPackId());
|
||||
$this->putString($entry->getVersion());
|
||||
$this->putString($entry->getPackVersion());
|
||||
$this->putLLong($entry->getPackSize());
|
||||
}
|
||||
$this->putLShort(count($this->resourcePackEntries));
|
||||
foreach($this->resourcePackEntries as $entry){
|
||||
$this->putString($entry->getPackId());
|
||||
$this->putString($entry->getVersion());
|
||||
$this->putString($entry->getPackVersion());
|
||||
$this->putLLong($entry->getPackSize());
|
||||
}
|
||||
}
|
||||
|
39
src/pocketmine/resourcepacks/ResourcePack.php
Normal file
39
src/pocketmine/resourcepacks/ResourcePack.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace pocketmine\resourcepacks;
|
||||
|
||||
|
||||
interface ResourcePack{
|
||||
|
||||
public function getPackName() : string;
|
||||
|
||||
public function getPackId() : string;
|
||||
|
||||
public function getPackSize() : int;
|
||||
|
||||
public function getPackVersion() : string;
|
||||
|
||||
public function getSha256() : string;
|
||||
|
||||
public function getPackChunk(int $start, int $length) : string;
|
||||
}
|
129
src/pocketmine/resourcepacks/ResourcePackManager.php
Normal file
129
src/pocketmine/resourcepacks/ResourcePackManager.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace pocketmine\resourcepacks;
|
||||
|
||||
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Config;
|
||||
|
||||
class ResourcePackManager{
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
|
||||
/** @var string */
|
||||
private $path;
|
||||
|
||||
/** @var Config */
|
||||
private $resourcePacksConfig;
|
||||
|
||||
/** @var bool */
|
||||
private $serverForceResources = false;
|
||||
|
||||
/** @var ResourcePack[] */
|
||||
private $resourcePacks = [];
|
||||
|
||||
/** @var ResourcePack[] */
|
||||
private $uuidList = [];
|
||||
|
||||
public function __construct(Server $server, string $path){
|
||||
$this->server = $server;
|
||||
$this->path = $path;
|
||||
|
||||
if(!file_exists($this->path)){
|
||||
$this->server->getLogger()->debug("Resource packs path $path does not exist, creating directory");
|
||||
mkdir($this->path);
|
||||
}elseif(!is_dir($this->path)){
|
||||
throw new \InvalidArgumentException("Resource packs path $path exists and is not a directory");
|
||||
}
|
||||
|
||||
$this->resourcePacksConfig = new Config($this->path . "resource_packs.yml", Config::YAML, []);
|
||||
|
||||
if(count($this->resourcePacksConfig->getAll()) === 0){
|
||||
$this->resourcePacksConfig->set("force_resources", false);
|
||||
$this->resourcePacksConfig->set("resource_stack", []);
|
||||
$this->resourcePacksConfig->save();
|
||||
}
|
||||
|
||||
$this->serverForceResources = (bool) $this->resourcePacksConfig->get("force_resources", false);
|
||||
|
||||
$this->server->getLogger()->info("Loading resource packs...");
|
||||
|
||||
foreach($this->resourcePacksConfig->get("resource_stack", []) as $pos => $pack){
|
||||
try{
|
||||
$packPath = $this->path . DIRECTORY_SEPARATOR . $pack;
|
||||
if(file_exists($packPath)){
|
||||
$newPack = null;
|
||||
//Detect the type of resource pack.
|
||||
if(is_dir($packPath)){
|
||||
$this->server->getLogger()->warning("Skipped resource entry $pack due to directory resource packs currently unsupported");
|
||||
}else{
|
||||
$info = new \SplFileInfo($packPath);
|
||||
switch($info->getExtension()){
|
||||
case "zip":
|
||||
$newPack = new ZippedResourcePack($packPath);
|
||||
break;
|
||||
default:
|
||||
$this->server->getLogger()->warning("Skipped resource entry $pack due to format not recognized");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($newPack instanceof ResourcePack){
|
||||
$this->resourcePacks[] = $newPack;
|
||||
$this->uuidList[$newPack->getPackId()] = $newPack;
|
||||
}
|
||||
}else{
|
||||
$this->server->getLogger()->warning("Skipped resource entry $pack due to file or directory not found");
|
||||
}
|
||||
}catch(\Throwable $e){
|
||||
$this->server->getLogger()->logException($e);
|
||||
}
|
||||
}
|
||||
|
||||
$this->server->getLogger()->debug("Successfully loaded " . count($this->resourcePacks) . " resource packs");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function resourcePacksRequired() : bool{
|
||||
return $this->serverForceResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ResourcePack[]
|
||||
*/
|
||||
public function getResourceStack() : array{
|
||||
return $this->resourcePacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*
|
||||
* @return ResourcePack|null
|
||||
*/
|
||||
public function getPackById(string $id){
|
||||
return $this->uuidList[$id] ?? null;
|
||||
}
|
||||
}
|
105
src/pocketmine/resourcepacks/ZippedResourcePack.php
Normal file
105
src/pocketmine/resourcepacks/ZippedResourcePack.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace pocketmine\resourcepacks;
|
||||
|
||||
|
||||
class ZippedResourcePack implements ResourcePack{
|
||||
|
||||
public static function verifyManifest(\stdClass $manifest){
|
||||
if(!isset($manifest->format_version) or !isset($manifest->header) or !isset($manifest->modules)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Right now we don't care about anything else, only the stuff we're sending to clients.
|
||||
//TODO: add more manifest validation
|
||||
return
|
||||
isset($manifest->header->description) and
|
||||
isset($manifest->header->name) and
|
||||
isset($manifest->header->uuid) and
|
||||
isset($manifest->header->version) and
|
||||
count($manifest->header->version) === 3;
|
||||
}
|
||||
|
||||
/** @var string */
|
||||
protected $path;
|
||||
|
||||
/** @var \stdClass */
|
||||
protected $manifest;
|
||||
|
||||
/** @var string */
|
||||
protected $sha256 = null;
|
||||
|
||||
|
||||
public function __construct(string $zipPath){
|
||||
$this->path = $zipPath;
|
||||
|
||||
if(!file_exists($zipPath)){
|
||||
throw new \InvalidArgumentException("Could not open resource pack $zipPath: file not found");
|
||||
}
|
||||
|
||||
$archive = new \ZipArchive();
|
||||
if(($openResult = $archive->open($zipPath)) !== true){
|
||||
throw new \InvalidStateException("Encountered ZipArchive error code $openResult while trying to open $zipPath");
|
||||
}
|
||||
|
||||
if(($manifestData = $archive->getFromName("manifest.json")) === false){
|
||||
throw new \InvalidStateException("Could not load resource pack from $zipPath: manifest.json not found");
|
||||
}
|
||||
|
||||
$archive->close();
|
||||
|
||||
$manifest = json_decode($manifestData);
|
||||
if(!self::verifyManifest($manifest)){
|
||||
throw new \InvalidStateException("Could not load resource pack from $zipPath: manifest.json is invalid or incomplete");
|
||||
}
|
||||
|
||||
$this->manifest = $manifest;
|
||||
}
|
||||
|
||||
public function getPackName() : string{
|
||||
return $this->manifest->header->name;
|
||||
}
|
||||
|
||||
public function getPackVersion() : string{
|
||||
return implode(".", $this->manifest->header->version);
|
||||
}
|
||||
|
||||
public function getPackId() : string{
|
||||
return $this->manifest->header->uuid;
|
||||
}
|
||||
|
||||
public function getPackSize() : int{
|
||||
return filesize($this->path);
|
||||
}
|
||||
|
||||
public function getSha256(bool $cached = true) : string{
|
||||
if($this->sha256 === null or !$cached){
|
||||
$this->sha256 = openssl_digest(file_get_contents($this->path), "sha256", true);
|
||||
}
|
||||
return $this->sha256;
|
||||
}
|
||||
|
||||
public function getPackChunk(int $start, int $length) : string{
|
||||
return substr(file_get_contents($this->path), $start, $length);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user