mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-18 15:05:56 +00:00
Bedrock 1.21.60 (#6627)
Co-authored-by: Dylan K. Taylor <dktapps@pmmp.io>
This commit is contained in:
parent
9402a20ee3
commit
91ac64783f
@ -33,15 +33,15 @@
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "~1.2.0",
|
||||
"netresearch/jsonmapper": "~v5.0.0",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~5.0.0+bedrock-1.21.40",
|
||||
"pocketmine/bedrock-data": "~2.15.0+bedrock-1.21.50",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~5.1.0+bedrock-1.21.60",
|
||||
"pocketmine/bedrock-data": "~4.0.0+bedrock-1.21.60",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.14.0+bedrock-1.21.50",
|
||||
"pocketmine/bedrock-protocol": "~35.0.0+bedrock-1.21.50",
|
||||
"pocketmine/bedrock-protocol": "~36.0.0+bedrock-1.21.60",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
"pocketmine/errorhandler": "^0.7.0",
|
||||
"pocketmine/locale-data": "~2.22.0",
|
||||
"pocketmine/locale-data": "~2.24.0",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/math": "~1.0.0",
|
||||
"pocketmine/nbt": "~1.0.0",
|
||||
|
52
composer.lock
generated
52
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": "a6aa0a34a230d325528d2e11f1439057",
|
||||
"content-hash": "af7547291a131bfac6d7087957601325",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -178,16 +178,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-block-upgrade-schema",
|
||||
"version": "5.0.0",
|
||||
"version": "5.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
|
||||
"reference": "20dd5c11e9915bacea4fe2cf649e1d23697a6e52"
|
||||
"reference": "2218512e4b91f5bfd09ef55f7a4c4b04e169e41a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/20dd5c11e9915bacea4fe2cf649e1d23697a6e52",
|
||||
"reference": "20dd5c11e9915bacea4fe2cf649e1d23697a6e52",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/2218512e4b91f5bfd09ef55f7a4c4b04e169e41a",
|
||||
"reference": "2218512e4b91f5bfd09ef55f7a4c4b04e169e41a",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -198,22 +198,22 @@
|
||||
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/5.0.0"
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/5.1.0"
|
||||
},
|
||||
"time": "2024-11-03T14:13:50+00:00"
|
||||
"time": "2025-02-11T17:41:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "2.15.0+bedrock-1.21.50",
|
||||
"version": "4.0.0+bedrock-1.21.60",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "6e819f36d781866ce63d2406be2ce7f2d1afd9ad"
|
||||
"reference": "2e5f16ec2facac653f3f894f22eb831d880ba98e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/6e819f36d781866ce63d2406be2ce7f2d1afd9ad",
|
||||
"reference": "6e819f36d781866ce63d2406be2ce7f2d1afd9ad",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/2e5f16ec2facac653f3f894f22eb831d880ba98e",
|
||||
"reference": "2e5f16ec2facac653f3f894f22eb831d880ba98e",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -224,9 +224,9 @@
|
||||
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockData/issues",
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.21.50"
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.21.60"
|
||||
},
|
||||
"time": "2024-12-04T12:59:12+00:00"
|
||||
"time": "2025-02-16T15:56:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
@ -256,16 +256,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "35.0.3+bedrock-1.21.50",
|
||||
"version": "36.0.0+bedrock-1.21.60",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "c4d62581cb62d29ec426914c6b4d7e0ff835da9c"
|
||||
"reference": "2057de319c5c551001c2a544e08d1bc7727d9963"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c4d62581cb62d29ec426914c6b4d7e0ff835da9c",
|
||||
"reference": "c4d62581cb62d29ec426914c6b4d7e0ff835da9c",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/2057de319c5c551001c2a544e08d1bc7727d9963",
|
||||
"reference": "2057de319c5c551001c2a544e08d1bc7727d9963",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -296,9 +296,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/35.0.3+bedrock-1.21.50"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/36.0.0+bedrock-1.21.60"
|
||||
},
|
||||
"time": "2025-01-07T23:06:29+00:00"
|
||||
"time": "2025-02-16T15:59:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -471,16 +471,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/locale-data",
|
||||
"version": "2.22.1",
|
||||
"version": "2.24.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Language.git",
|
||||
"reference": "fa4e377c437391cfcfdedd08eea3a848eabd1b49"
|
||||
"reference": "6ec5e92c77a2102b2692763733e4763012facae9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/fa4e377c437391cfcfdedd08eea3a848eabd1b49",
|
||||
"reference": "fa4e377c437391cfcfdedd08eea3a848eabd1b49",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/6ec5e92c77a2102b2692763733e4763012facae9",
|
||||
"reference": "6ec5e92c77a2102b2692763733e4763012facae9",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -488,9 +488,9 @@
|
||||
"description": "Language resources used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Language/issues",
|
||||
"source": "https://github.com/pmmp/Language/tree/2.22.1"
|
||||
"source": "https://github.com/pmmp/Language/tree/2.24.0"
|
||||
},
|
||||
"time": "2024-12-06T14:44:17+00:00"
|
||||
"time": "2025-02-16T20:46:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
@ -2967,5 +2967,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "8.1.0"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
@ -39,12 +39,11 @@ final class BedrockDataFiles{
|
||||
public const BLOCK_STATE_META_MAP_JSON = BEDROCK_DATA_PATH . '/block_state_meta_map.json';
|
||||
public const CANONICAL_BLOCK_STATES_NBT = BEDROCK_DATA_PATH . '/canonical_block_states.nbt';
|
||||
public const COMMAND_ARG_TYPES_JSON = BEDROCK_DATA_PATH . '/command_arg_types.json';
|
||||
public const CREATIVEITEMS_JSON = BEDROCK_DATA_PATH . '/creativeitems.json';
|
||||
public const ENTITY_ID_MAP_JSON = BEDROCK_DATA_PATH . '/entity_id_map.json';
|
||||
public const ENTITY_IDENTIFIERS_NBT = BEDROCK_DATA_PATH . '/entity_identifiers.nbt';
|
||||
public const ENUMS_PY = BEDROCK_DATA_PATH . '/enums.py';
|
||||
public const ITEM_TAGS_JSON = BEDROCK_DATA_PATH . '/item_tags.json';
|
||||
public const LEVEL_SOUND_ID_MAP_JSON = BEDROCK_DATA_PATH . '/level_sound_id_map.json';
|
||||
public const PARTICLE_ID_MAP_JSON = BEDROCK_DATA_PATH . '/particle_id_map.json';
|
||||
public const PROTOCOL_INFO_JSON = BEDROCK_DATA_PATH . '/protocol_info.json';
|
||||
public const R12_TO_CURRENT_BLOCK_MAP_BIN = BEDROCK_DATA_PATH . '/r12_to_current_block_map.bin';
|
||||
public const R16_TO_CURRENT_ITEM_MAP_JSON = BEDROCK_DATA_PATH . '/r16_to_current_item_map.json';
|
||||
|
@ -45,8 +45,8 @@ final class BlockStateData{
|
||||
public const CURRENT_VERSION =
|
||||
(1 << 24) | //major
|
||||
(21 << 16) | //minor
|
||||
(40 << 8) | //patch
|
||||
(1); //revision
|
||||
(60 << 8) | //patch
|
||||
(33); //revision
|
||||
|
||||
public const TAG_NAME = "name";
|
||||
public const TAG_STATES = "states";
|
||||
|
@ -59,6 +59,7 @@ final class BlockStateNames{
|
||||
public const COVERED_BIT = "covered_bit";
|
||||
public const CRACKED_STATE = "cracked_state";
|
||||
public const CRAFTING = "crafting";
|
||||
public const CREAKING_HEART_STATE = "creaking_heart_state";
|
||||
public const DEAD_BIT = "dead_bit";
|
||||
public const DEPRECATED = "deprecated";
|
||||
public const DIRECTION = "direction";
|
||||
|
@ -56,6 +56,10 @@ final class BlockStateStringValues{
|
||||
public const CRACKED_STATE_MAX_CRACKED = "max_cracked";
|
||||
public const CRACKED_STATE_NO_CRACKS = "no_cracks";
|
||||
|
||||
public const CREAKING_HEART_STATE_AWAKE = "awake";
|
||||
public const CREAKING_HEART_STATE_DORMANT = "dormant";
|
||||
public const CREAKING_HEART_STATE_UPROOTED = "uprooted";
|
||||
|
||||
public const DRIPSTONE_THICKNESS_BASE = "base";
|
||||
public const DRIPSTONE_THICKNESS_FRUSTUM = "frustum";
|
||||
public const DRIPSTONE_THICKNESS_MERGE = "merge";
|
||||
|
@ -131,7 +131,7 @@ final class BlockStateDeserializerHelper{
|
||||
//TODO: check if these need any special treatment to get the appropriate data to both halves of the door
|
||||
return $block
|
||||
->setTop($in->readBool(BlockStateNames::UPPER_BLOCK_BIT))
|
||||
->setFacing(Facing::rotateY($in->readLegacyHorizontalFacing(), false))
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setHingeRight($in->readBool(BlockStateNames::DOOR_HINGE_BIT))
|
||||
->setOpen($in->readBool(BlockStateNames::OPEN_BIT));
|
||||
}
|
||||
@ -145,7 +145,7 @@ final class BlockStateDeserializerHelper{
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeFenceGate(FenceGate $block, BlockStateReader $in) : FenceGate{
|
||||
return $block
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setInWall($in->readBool(BlockStateNames::IN_WALL_BIT))
|
||||
->setOpen($in->readBool(BlockStateNames::OPEN_BIT));
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ final class BlockStateSerializerHelper{
|
||||
public static function encodeDoor(Door $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop())
|
||||
->writeLegacyHorizontalFacing(Facing::rotateY($block->getFacing(), true))
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeBool(BlockStateNames::DOOR_HINGE_BIT, $block->isHingeRight())
|
||||
->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
|
||||
}
|
||||
@ -112,7 +112,7 @@ final class BlockStateSerializerHelper{
|
||||
|
||||
public static function encodeFenceGate(FenceGate $block, Writer $out) : Writer{
|
||||
return $out
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeBool(BlockStateNames::IN_WALL_BIT, $block->isInWall())
|
||||
->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
|
||||
}
|
||||
|
@ -513,6 +513,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
||||
AbilitiesLayer::LAYER_BASE,
|
||||
array_fill(0, AbilitiesLayer::NUMBER_OF_ABILITIES, false),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
)
|
||||
])),
|
||||
|
34
src/inventory/CreativeCategory.php
Normal file
34
src/inventory/CreativeCategory.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
/**
|
||||
* Available tabs in the creative inventory that an item can be displayed in.
|
||||
*/
|
||||
enum CreativeCategory{
|
||||
case CONSTRUCTION;
|
||||
case NATURE;
|
||||
case EQUIPMENT;
|
||||
case ITEMS;
|
||||
}
|
51
src/inventory/CreativeGroup.php
Normal file
51
src/inventory/CreativeGroup.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\lang\Translatable;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* Info for an item group in the creative inventory menu.
|
||||
*/
|
||||
final class CreativeGroup{
|
||||
/**
|
||||
* @param Translatable|string $name Tooltip shown to the player on hover
|
||||
* @param Item $icon Item shown when the group is collapsed
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly Translatable|string $name,
|
||||
private readonly Item $icon
|
||||
){
|
||||
$nameLength = $name instanceof Translatable ? strlen($name->getText()) : strlen($name);
|
||||
if($nameLength === 0){
|
||||
throw new \InvalidArgumentException("Creative group name cannot be empty");
|
||||
}
|
||||
}
|
||||
|
||||
public function getName() : Translatable|string{ return $this->name; }
|
||||
|
||||
public function getIcon() : Item{ return clone $this->icon; }
|
||||
}
|
@ -24,21 +24,23 @@ declare(strict_types=1);
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
||||
use pocketmine\crafting\json\ItemStackData;
|
||||
use pocketmine\data\bedrock\BedrockDataFiles;
|
||||
use pocketmine\inventory\json\CreativeGroupData;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\utils\DestructorCallbackTrait;
|
||||
use pocketmine\utils\ObjectSet;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use pocketmine\utils\Utils;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
|
||||
final class CreativeInventory{
|
||||
use SingletonTrait;
|
||||
use DestructorCallbackTrait;
|
||||
|
||||
/**
|
||||
* @var Item[]
|
||||
* @phpstan-var array<int, Item>
|
||||
* @var CreativeInventoryEntry[]
|
||||
* @phpstan-var array<int, CreativeInventoryEntry>
|
||||
*/
|
||||
private array $creative = [];
|
||||
|
||||
@ -47,17 +49,32 @@ final class CreativeInventory{
|
||||
|
||||
private function __construct(){
|
||||
$this->contentChangedCallbacks = new ObjectSet();
|
||||
$creativeItems = CraftingManagerFromDataHelper::loadJsonArrayOfObjectsFile(
|
||||
BedrockDataFiles::CREATIVEITEMS_JSON,
|
||||
ItemStackData::class
|
||||
);
|
||||
foreach($creativeItems as $data){
|
||||
$item = CraftingManagerFromDataHelper::deserializeItemStack($data);
|
||||
if($item === null){
|
||||
//unknown item
|
||||
continue;
|
||||
|
||||
foreach([
|
||||
"construction" => CreativeCategory::CONSTRUCTION,
|
||||
"nature" => CreativeCategory::NATURE,
|
||||
"equipment" => CreativeCategory::EQUIPMENT,
|
||||
"items" => CreativeCategory::ITEMS,
|
||||
] as $categoryId => $categoryEnum){
|
||||
$groups = CraftingManagerFromDataHelper::loadJsonArrayOfObjectsFile(
|
||||
Path::join(\pocketmine\BEDROCK_DATA_PATH, "creative", $categoryId . ".json"),
|
||||
CreativeGroupData::class
|
||||
);
|
||||
|
||||
foreach($groups as $groupData){
|
||||
$icon = $groupData->group_icon === null ? null : CraftingManagerFromDataHelper::deserializeItemStack($groupData->group_icon);
|
||||
|
||||
$group = $icon === null ? null : new CreativeGroup(
|
||||
new Translatable($groupData->group_name),
|
||||
$icon
|
||||
);
|
||||
|
||||
$items = array_filter(array_map(static fn($itemStack) => CraftingManagerFromDataHelper::deserializeItemStack($itemStack), $groupData->items));
|
||||
|
||||
foreach($items as $item){
|
||||
$this->add($item, $categoryEnum, $group);
|
||||
}
|
||||
}
|
||||
$this->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,16 +92,28 @@ final class CreativeInventory{
|
||||
* @phpstan-return array<int, Item>
|
||||
*/
|
||||
public function getAll() : array{
|
||||
return Utils::cloneObjectArray($this->creative);
|
||||
return array_map(fn(CreativeInventoryEntry $entry) => $entry->getItem(), $this->creative);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CreativeInventoryEntry[]
|
||||
* @phpstan-return array<int, CreativeInventoryEntry>
|
||||
*/
|
||||
public function getAllEntries() : array{
|
||||
return $this->creative;
|
||||
}
|
||||
|
||||
public function getItem(int $index) : ?Item{
|
||||
return isset($this->creative[$index]) ? clone $this->creative[$index] : null;
|
||||
return $this->getEntry($index)?->getItem();
|
||||
}
|
||||
|
||||
public function getEntry(int $index) : ?CreativeInventoryEntry{
|
||||
return $this->creative[$index] ?? null;
|
||||
}
|
||||
|
||||
public function getItemIndex(Item $item) : int{
|
||||
foreach($this->creative as $i => $d){
|
||||
if($item->equals($d, true, false)){
|
||||
if($d->matchesItem($item)){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
@ -96,8 +125,8 @@ final class CreativeInventory{
|
||||
* Adds an item to the creative menu.
|
||||
* Note: Players who are already online when this is called will not see this change.
|
||||
*/
|
||||
public function add(Item $item) : void{
|
||||
$this->creative[] = clone $item;
|
||||
public function add(Item $item, CreativeCategory $category = CreativeCategory::ITEMS, ?CreativeGroup $group = null) : void{
|
||||
$this->creative[] = new CreativeInventoryEntry($item, $category, $group);
|
||||
$this->onContentChange();
|
||||
}
|
||||
|
||||
|
48
src/inventory/CreativeInventoryEntry.php
Normal file
48
src/inventory/CreativeInventoryEntry.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
final class CreativeInventoryEntry{
|
||||
private readonly Item $item;
|
||||
|
||||
public function __construct(
|
||||
Item $item,
|
||||
private readonly CreativeCategory $category,
|
||||
private readonly ?CreativeGroup $group = null
|
||||
){
|
||||
$this->item = clone $item;
|
||||
}
|
||||
|
||||
public function getItem() : Item{ return clone $this->item; }
|
||||
|
||||
public function getCategory() : CreativeCategory{ return $this->category; }
|
||||
|
||||
public function getGroup() : ?CreativeGroup{ return $this->group; }
|
||||
|
||||
public function matchesItem(Item $item) : bool{
|
||||
return $item->equals($this->item, checkDamage: true, checkCompound: false);
|
||||
}
|
||||
}
|
38
src/inventory/json/CreativeGroupData.php
Normal file
38
src/inventory/json/CreativeGroupData.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory\json;
|
||||
|
||||
use pocketmine\crafting\json\ItemStackData;
|
||||
|
||||
final class CreativeGroupData{
|
||||
/** @required */
|
||||
public string $group_name;
|
||||
/** @required */
|
||||
public ?ItemStackData $group_icon;
|
||||
/**
|
||||
* @var \pocketmine\crafting\json\ItemStackData[]
|
||||
* @required
|
||||
*/
|
||||
public array $items;
|
||||
}
|
@ -897,6 +897,18 @@ final class KnownTranslationFactory{
|
||||
return new Translatable(KnownTranslationKeys::ENCHANTMENT_FROSTWALKER, []);
|
||||
}
|
||||
|
||||
public static function enchantment_heavy_weapon_breach() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ENCHANTMENT_HEAVY_WEAPON_BREACH, []);
|
||||
}
|
||||
|
||||
public static function enchantment_heavy_weapon_density() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ENCHANTMENT_HEAVY_WEAPON_DENSITY, []);
|
||||
}
|
||||
|
||||
public static function enchantment_heavy_weapon_windburst() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ENCHANTMENT_HEAVY_WEAPON_WINDBURST, []);
|
||||
}
|
||||
|
||||
public static function enchantment_knockback() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ENCHANTMENT_KNOCKBACK, []);
|
||||
}
|
||||
@ -1108,6 +1120,318 @@ final class KnownTranslationFactory{
|
||||
return new Translatable(KnownTranslationKeys::ITEM_RECORD_WARD_DESC, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_anvil() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_ANVIL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_arrow() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_ARROW, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_axe() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_AXE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_banner() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BANNER, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_banner_pattern() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BANNER_PATTERN, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_bed() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BED, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_boat() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BOAT, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_boots() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BOOTS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_bundles() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BUNDLES, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_buttons() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_BUTTONS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_candles() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CANDLES, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_chalkboard() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CHALKBOARD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_chest() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CHEST, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_chestboat() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CHESTBOAT, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_chestplate() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CHESTPLATE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_compounds() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_COMPOUNDS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_concrete() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CONCRETE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_concretePowder() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CONCRETEPOWDER, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_cookedFood() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_COOKEDFOOD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_coral() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CORAL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_coral_decorations() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CORAL_DECORATIONS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_crop() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_CROP, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_door() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_DOOR, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_dye() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_DYE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_enchantedBook() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_ENCHANTEDBOOK, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_fence() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_FENCE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_fenceGate() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_FENCEGATE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_firework() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_FIREWORK, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_fireworkStars() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_FIREWORKSTARS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_flower() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_FLOWER, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_glass() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_GLASS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_glassPane() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_GLASSPANE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_glazedTerracotta() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_GLAZEDTERRACOTTA, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_goatHorn() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_GOATHORN, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_grass() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_GRASS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_helmet() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_HELMET, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_hoe() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_HOE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_horseArmor() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_HORSEARMOR, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_leaves() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_LEAVES, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_leggings() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_LEGGINGS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_lingeringPotion() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_LINGERINGPOTION, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_log() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_LOG, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_minecart() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_MINECART, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_miscFood() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_MISCFOOD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_mobEgg() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_MOBEGG, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_monsterStoneEgg() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_MONSTERSTONEEGG, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_mushroom() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_MUSHROOM, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_netherWartBlock() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_NETHERWARTBLOCK, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_ominousBottle() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_OMINOUSBOTTLE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_ore() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_ORE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_permission() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_PERMISSION, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_pickaxe() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_PICKAXE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_planks() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_PLANKS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_potion() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_POTION, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_pressurePlate() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_PRESSUREPLATE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_products() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_PRODUCTS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_rail() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_RAIL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_rawFood() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_RAWFOOD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_record() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_RECORD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_sandstone() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SANDSTONE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_sapling() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SAPLING, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_seed() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SEED, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_shovel() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SHOVEL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_shulkerBox() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SHULKERBOX, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_sign() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SIGN, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_skull() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SKULL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_slab() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SLAB, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_splashPotion() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SPLASHPOTION, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_stainedClay() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_STAINEDCLAY, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_stairs() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_STAIRS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_stone() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_STONE, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_stoneBrick() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_STONEBRICK, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_sword() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_SWORD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_trapdoor() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_TRAPDOOR, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_walls() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_WALLS, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_wood() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_WOOD, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_wool() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_WOOL, []);
|
||||
}
|
||||
|
||||
public static function itemGroup_name_woolCarpet() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::ITEMGROUP_NAME_WOOLCARPET, []);
|
||||
}
|
||||
|
||||
public static function kick_admin() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::KICK_ADMIN, []);
|
||||
}
|
||||
|
@ -194,6 +194,9 @@ final class KnownTranslationKeys{
|
||||
public const ENCHANTMENT_FIRE = "enchantment.fire";
|
||||
public const ENCHANTMENT_FISHINGSPEED = "enchantment.fishingSpeed";
|
||||
public const ENCHANTMENT_FROSTWALKER = "enchantment.frostwalker";
|
||||
public const ENCHANTMENT_HEAVY_WEAPON_BREACH = "enchantment.heavy_weapon.breach";
|
||||
public const ENCHANTMENT_HEAVY_WEAPON_DENSITY = "enchantment.heavy_weapon.density";
|
||||
public const ENCHANTMENT_HEAVY_WEAPON_WINDBURST = "enchantment.heavy_weapon.windburst";
|
||||
public const ENCHANTMENT_KNOCKBACK = "enchantment.knockback";
|
||||
public const ENCHANTMENT_LOOTBONUS = "enchantment.lootBonus";
|
||||
public const ENCHANTMENT_LOOTBONUSDIGGER = "enchantment.lootBonusDigger";
|
||||
@ -245,6 +248,84 @@ final class KnownTranslationKeys{
|
||||
public const ITEM_RECORD_STRAD_DESC = "item.record_strad.desc";
|
||||
public const ITEM_RECORD_WAIT_DESC = "item.record_wait.desc";
|
||||
public const ITEM_RECORD_WARD_DESC = "item.record_ward.desc";
|
||||
public const ITEMGROUP_NAME_ANVIL = "itemGroup.name.anvil";
|
||||
public const ITEMGROUP_NAME_ARROW = "itemGroup.name.arrow";
|
||||
public const ITEMGROUP_NAME_AXE = "itemGroup.name.axe";
|
||||
public const ITEMGROUP_NAME_BANNER = "itemGroup.name.banner";
|
||||
public const ITEMGROUP_NAME_BANNER_PATTERN = "itemGroup.name.banner_pattern";
|
||||
public const ITEMGROUP_NAME_BED = "itemGroup.name.bed";
|
||||
public const ITEMGROUP_NAME_BOAT = "itemGroup.name.boat";
|
||||
public const ITEMGROUP_NAME_BOOTS = "itemGroup.name.boots";
|
||||
public const ITEMGROUP_NAME_BUNDLES = "itemGroup.name.bundles";
|
||||
public const ITEMGROUP_NAME_BUTTONS = "itemGroup.name.buttons";
|
||||
public const ITEMGROUP_NAME_CANDLES = "itemGroup.name.candles";
|
||||
public const ITEMGROUP_NAME_CHALKBOARD = "itemGroup.name.chalkboard";
|
||||
public const ITEMGROUP_NAME_CHEST = "itemGroup.name.chest";
|
||||
public const ITEMGROUP_NAME_CHESTBOAT = "itemGroup.name.chestboat";
|
||||
public const ITEMGROUP_NAME_CHESTPLATE = "itemGroup.name.chestplate";
|
||||
public const ITEMGROUP_NAME_COMPOUNDS = "itemGroup.name.compounds";
|
||||
public const ITEMGROUP_NAME_CONCRETE = "itemGroup.name.concrete";
|
||||
public const ITEMGROUP_NAME_CONCRETEPOWDER = "itemGroup.name.concretePowder";
|
||||
public const ITEMGROUP_NAME_COOKEDFOOD = "itemGroup.name.cookedFood";
|
||||
public const ITEMGROUP_NAME_CORAL = "itemGroup.name.coral";
|
||||
public const ITEMGROUP_NAME_CORAL_DECORATIONS = "itemGroup.name.coral_decorations";
|
||||
public const ITEMGROUP_NAME_CROP = "itemGroup.name.crop";
|
||||
public const ITEMGROUP_NAME_DOOR = "itemGroup.name.door";
|
||||
public const ITEMGROUP_NAME_DYE = "itemGroup.name.dye";
|
||||
public const ITEMGROUP_NAME_ENCHANTEDBOOK = "itemGroup.name.enchantedBook";
|
||||
public const ITEMGROUP_NAME_FENCE = "itemGroup.name.fence";
|
||||
public const ITEMGROUP_NAME_FENCEGATE = "itemGroup.name.fenceGate";
|
||||
public const ITEMGROUP_NAME_FIREWORK = "itemGroup.name.firework";
|
||||
public const ITEMGROUP_NAME_FIREWORKSTARS = "itemGroup.name.fireworkStars";
|
||||
public const ITEMGROUP_NAME_FLOWER = "itemGroup.name.flower";
|
||||
public const ITEMGROUP_NAME_GLASS = "itemGroup.name.glass";
|
||||
public const ITEMGROUP_NAME_GLASSPANE = "itemGroup.name.glassPane";
|
||||
public const ITEMGROUP_NAME_GLAZEDTERRACOTTA = "itemGroup.name.glazedTerracotta";
|
||||
public const ITEMGROUP_NAME_GOATHORN = "itemGroup.name.goatHorn";
|
||||
public const ITEMGROUP_NAME_GRASS = "itemGroup.name.grass";
|
||||
public const ITEMGROUP_NAME_HELMET = "itemGroup.name.helmet";
|
||||
public const ITEMGROUP_NAME_HOE = "itemGroup.name.hoe";
|
||||
public const ITEMGROUP_NAME_HORSEARMOR = "itemGroup.name.horseArmor";
|
||||
public const ITEMGROUP_NAME_LEAVES = "itemGroup.name.leaves";
|
||||
public const ITEMGROUP_NAME_LEGGINGS = "itemGroup.name.leggings";
|
||||
public const ITEMGROUP_NAME_LINGERINGPOTION = "itemGroup.name.lingeringPotion";
|
||||
public const ITEMGROUP_NAME_LOG = "itemGroup.name.log";
|
||||
public const ITEMGROUP_NAME_MINECART = "itemGroup.name.minecart";
|
||||
public const ITEMGROUP_NAME_MISCFOOD = "itemGroup.name.miscFood";
|
||||
public const ITEMGROUP_NAME_MOBEGG = "itemGroup.name.mobEgg";
|
||||
public const ITEMGROUP_NAME_MONSTERSTONEEGG = "itemGroup.name.monsterStoneEgg";
|
||||
public const ITEMGROUP_NAME_MUSHROOM = "itemGroup.name.mushroom";
|
||||
public const ITEMGROUP_NAME_NETHERWARTBLOCK = "itemGroup.name.netherWartBlock";
|
||||
public const ITEMGROUP_NAME_OMINOUSBOTTLE = "itemGroup.name.ominousBottle";
|
||||
public const ITEMGROUP_NAME_ORE = "itemGroup.name.ore";
|
||||
public const ITEMGROUP_NAME_PERMISSION = "itemGroup.name.permission";
|
||||
public const ITEMGROUP_NAME_PICKAXE = "itemGroup.name.pickaxe";
|
||||
public const ITEMGROUP_NAME_PLANKS = "itemGroup.name.planks";
|
||||
public const ITEMGROUP_NAME_POTION = "itemGroup.name.potion";
|
||||
public const ITEMGROUP_NAME_PRESSUREPLATE = "itemGroup.name.pressurePlate";
|
||||
public const ITEMGROUP_NAME_PRODUCTS = "itemGroup.name.products";
|
||||
public const ITEMGROUP_NAME_RAIL = "itemGroup.name.rail";
|
||||
public const ITEMGROUP_NAME_RAWFOOD = "itemGroup.name.rawFood";
|
||||
public const ITEMGROUP_NAME_RECORD = "itemGroup.name.record";
|
||||
public const ITEMGROUP_NAME_SANDSTONE = "itemGroup.name.sandstone";
|
||||
public const ITEMGROUP_NAME_SAPLING = "itemGroup.name.sapling";
|
||||
public const ITEMGROUP_NAME_SEED = "itemGroup.name.seed";
|
||||
public const ITEMGROUP_NAME_SHOVEL = "itemGroup.name.shovel";
|
||||
public const ITEMGROUP_NAME_SHULKERBOX = "itemGroup.name.shulkerBox";
|
||||
public const ITEMGROUP_NAME_SIGN = "itemGroup.name.sign";
|
||||
public const ITEMGROUP_NAME_SKULL = "itemGroup.name.skull";
|
||||
public const ITEMGROUP_NAME_SLAB = "itemGroup.name.slab";
|
||||
public const ITEMGROUP_NAME_SPLASHPOTION = "itemGroup.name.splashPotion";
|
||||
public const ITEMGROUP_NAME_STAINEDCLAY = "itemGroup.name.stainedClay";
|
||||
public const ITEMGROUP_NAME_STAIRS = "itemGroup.name.stairs";
|
||||
public const ITEMGROUP_NAME_STONE = "itemGroup.name.stone";
|
||||
public const ITEMGROUP_NAME_STONEBRICK = "itemGroup.name.stoneBrick";
|
||||
public const ITEMGROUP_NAME_SWORD = "itemGroup.name.sword";
|
||||
public const ITEMGROUP_NAME_TRAPDOOR = "itemGroup.name.trapdoor";
|
||||
public const ITEMGROUP_NAME_WALLS = "itemGroup.name.walls";
|
||||
public const ITEMGROUP_NAME_WOOD = "itemGroup.name.wood";
|
||||
public const ITEMGROUP_NAME_WOOL = "itemGroup.name.wool";
|
||||
public const ITEMGROUP_NAME_WOOLCARPET = "itemGroup.name.woolCarpet";
|
||||
public const KICK_ADMIN = "kick.admin";
|
||||
public const KICK_ADMIN_REASON = "kick.admin.reason";
|
||||
public const KICK_REASON_CHEAT = "kick.reason.cheat";
|
||||
|
@ -690,7 +690,7 @@ class InventoryManager{
|
||||
}
|
||||
|
||||
public function syncCreative() : void{
|
||||
$this->session->sendDataPacket(CreativeInventoryCache::getInstance()->getCache($this->player->getCreativeInventory()));
|
||||
$this->session->sendDataPacket(CreativeInventoryCache::getInstance()->buildPacket($this->player->getCreativeInventory(), $this->session));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1058,7 +1058,7 @@ class NetworkSession{
|
||||
];
|
||||
|
||||
$layers = [
|
||||
new AbilitiesLayer(AbilitiesLayer::LAYER_BASE, $boolAbilities, $for->getFlightSpeedMultiplier(), 0.1),
|
||||
new AbilitiesLayer(AbilitiesLayer::LAYER_BASE, $boolAbilities, $for->getFlightSpeedMultiplier(), 1, 0.1),
|
||||
];
|
||||
if(!$for->hasBlockCollision()){
|
||||
//TODO: HACK! In 1.19.80, the client starts falling in our faux spectator mode when it clips into a
|
||||
@ -1068,7 +1068,7 @@ class NetworkSession{
|
||||
|
||||
$layers[] = new AbilitiesLayer(AbilitiesLayer::LAYER_SPECTATOR, [
|
||||
AbilitiesLayer::ABILITY_FLYING => true,
|
||||
], null, null);
|
||||
], null, null, null);
|
||||
}
|
||||
|
||||
$this->sendDataPacket(UpdateAbilitiesPacket::create(new AbilitiesData(
|
||||
|
106
src/network/mcpe/cache/CreativeInventoryCache.php
vendored
106
src/network/mcpe/cache/CreativeInventoryCache.php
vendored
@ -23,23 +23,30 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\cache;
|
||||
|
||||
use pocketmine\inventory\CreativeCategory;
|
||||
use pocketmine\inventory\CreativeInventory;
|
||||
use pocketmine\lang\Translatable;
|
||||
use pocketmine\network\mcpe\convert\TypeConverter;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\CreativeContentPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeContentEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeGroupEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeItemEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function is_string;
|
||||
use function spl_object_id;
|
||||
use const PHP_INT_MIN;
|
||||
|
||||
final class CreativeInventoryCache{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var CreativeContentPacket[]
|
||||
* @phpstan-var array<int, CreativeContentPacket>
|
||||
* @var CreativeInventoryCacheEntry[]
|
||||
* @phpstan-var array<int, CreativeInventoryCacheEntry>
|
||||
*/
|
||||
private array $caches = [];
|
||||
|
||||
public function getCache(CreativeInventory $inventory) : CreativeContentPacket{
|
||||
private function getCacheEntry(CreativeInventory $inventory) : CreativeInventoryCacheEntry{
|
||||
$id = spl_object_id($inventory);
|
||||
if(!isset($this->caches[$id])){
|
||||
$inventory->getDestructorCallbacks()->add(function() use ($id) : void{
|
||||
@ -48,7 +55,7 @@ final class CreativeInventoryCache{
|
||||
$inventory->getContentChangedCallbacks()->add(function() use ($id) : void{
|
||||
unset($this->caches[$id]);
|
||||
});
|
||||
$this->caches[$id] = $this->buildCreativeInventoryCache($inventory);
|
||||
$this->caches[$id] = $this->buildCacheEntry($inventory);
|
||||
}
|
||||
return $this->caches[$id];
|
||||
}
|
||||
@ -56,14 +63,91 @@ final class CreativeInventoryCache{
|
||||
/**
|
||||
* Rebuild the cache for the given inventory.
|
||||
*/
|
||||
private function buildCreativeInventoryCache(CreativeInventory $inventory) : CreativeContentPacket{
|
||||
$entries = [];
|
||||
private function buildCacheEntry(CreativeInventory $inventory) : CreativeInventoryCacheEntry{
|
||||
$categories = [];
|
||||
$groups = [];
|
||||
|
||||
$typeConverter = TypeConverter::getInstance();
|
||||
//creative inventory may have holes if items were unregistered - ensure network IDs used are always consistent
|
||||
foreach($inventory->getAll() as $k => $item){
|
||||
$entries[] = new CreativeContentEntry($k, $typeConverter->coreItemStackToNet($item));
|
||||
|
||||
$nextIndex = 0;
|
||||
$groupIndexes = [];
|
||||
$itemGroupIndexes = [];
|
||||
|
||||
foreach($inventory->getAllEntries() as $k => $entry){
|
||||
$group = $entry->getGroup();
|
||||
$category = $entry->getCategory();
|
||||
if($group === null){
|
||||
$groupId = PHP_INT_MIN;
|
||||
}else{
|
||||
$groupId = spl_object_id($group);
|
||||
unset($groupIndexes[$category->name][PHP_INT_MIN]); //start a new anonymous group for this category
|
||||
}
|
||||
|
||||
//group object may be reused by multiple categories
|
||||
if(!isset($groupIndexes[$category->name][$groupId])){
|
||||
$groupIndexes[$category->name][$groupId] = $nextIndex++;
|
||||
$categories[] = $category;
|
||||
$groups[] = $group;
|
||||
}
|
||||
$itemGroupIndexes[$k] = $groupIndexes[$category->name][$groupId];
|
||||
}
|
||||
|
||||
return CreativeContentPacket::create($entries);
|
||||
//creative inventory may have holes if items were unregistered - ensure network IDs used are always consistent
|
||||
$items = [];
|
||||
foreach($inventory->getAllEntries() as $k => $entry){
|
||||
$items[] = new CreativeItemEntry(
|
||||
$k,
|
||||
$typeConverter->coreItemStackToNet($entry->getItem()),
|
||||
$itemGroupIndexes[$k]
|
||||
);
|
||||
}
|
||||
|
||||
return new CreativeInventoryCacheEntry($categories, $groups, $items);
|
||||
}
|
||||
|
||||
public function buildPacket(CreativeInventory $inventory, NetworkSession $session) : CreativeContentPacket{
|
||||
$player = $session->getPlayer() ?? throw new \LogicException("Cannot prepare creative data for a session without a player");
|
||||
$language = $player->getLanguage();
|
||||
$forceLanguage = $player->getServer()->isLanguageForced();
|
||||
$typeConverter = $session->getTypeConverter();
|
||||
$cachedEntry = $this->getCacheEntry($inventory);
|
||||
$translate = function(Translatable|string $translatable) use ($session, $language, $forceLanguage) : string{
|
||||
if(is_string($translatable)){
|
||||
$message = $translatable;
|
||||
}elseif(!$forceLanguage){
|
||||
[$message,] = $session->prepareClientTranslatableMessage($translatable);
|
||||
}else{
|
||||
$message = $language->translate($translatable);
|
||||
}
|
||||
return $message;
|
||||
};
|
||||
|
||||
$groupEntries = [];
|
||||
foreach($cachedEntry->categories as $index => $category){
|
||||
$group = $cachedEntry->groups[$index];
|
||||
$categoryId = match ($category) {
|
||||
CreativeCategory::CONSTRUCTION => CreativeContentPacket::CATEGORY_CONSTRUCTION,
|
||||
CreativeCategory::NATURE => CreativeContentPacket::CATEGORY_NATURE,
|
||||
CreativeCategory::EQUIPMENT => CreativeContentPacket::CATEGORY_EQUIPMENT,
|
||||
CreativeCategory::ITEMS => CreativeContentPacket::CATEGORY_ITEMS
|
||||
};
|
||||
if($group === null){
|
||||
$groupEntries[] = new CreativeGroupEntry($categoryId, "", ItemStack::null());
|
||||
}else{
|
||||
$groupIcon = $group->getIcon();
|
||||
//TODO: HACK! In 1.21.60, Workaround glitchy behaviour when an item is used as an icon for a group it
|
||||
//doesn't belong to. Without this hack, both instances of the item will show a +, but neither of them
|
||||
//will actually expand the group work correctly.
|
||||
$groupIcon->getNamedTag()->setInt("___GroupBugWorkaround___", $index);
|
||||
$groupName = $group->getName();
|
||||
$groupEntries[] = new CreativeGroupEntry(
|
||||
$categoryId,
|
||||
$translate($groupName),
|
||||
$typeConverter->coreItemStackToNet($groupIcon)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return CreativeContentPacket::create($groupEntries, $cachedEntry->items);
|
||||
}
|
||||
}
|
||||
|
48
src/network/mcpe/cache/CreativeInventoryCacheEntry.php
vendored
Normal file
48
src/network/mcpe/cache/CreativeInventoryCacheEntry.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?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/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\cache;
|
||||
|
||||
use pocketmine\inventory\CreativeCategory;
|
||||
use pocketmine\inventory\CreativeGroup;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeItemEntry;
|
||||
|
||||
final class CreativeInventoryCacheEntry{
|
||||
|
||||
/**
|
||||
* @param CreativeCategory[] $categories
|
||||
* @param CreativeGroup[]|null[] $groups
|
||||
* @param CreativeItemEntry[] $items
|
||||
*
|
||||
* @phpstan-param list<CreativeCategory> $categories
|
||||
* @phpstan-param list<CreativeGroup|null> $groups
|
||||
* @phpstan-param list<CreativeItemEntry> $items
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly array $categories,
|
||||
public readonly array $groups,
|
||||
public readonly array $items,
|
||||
){
|
||||
//NOOP
|
||||
}
|
||||
}
|
@ -23,10 +23,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\convert;
|
||||
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
|
||||
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
|
||||
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use function base64_decode;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_int;
|
||||
@ -41,12 +46,15 @@ final class ItemTypeDictionaryFromDataHelper{
|
||||
throw new AssumptionFailedError("Invalid item list format");
|
||||
}
|
||||
|
||||
$emptyNBT = new CacheableNbt(new CompoundTag());
|
||||
$nbtSerializer = new LittleEndianNbtSerializer();
|
||||
|
||||
$params = [];
|
||||
foreach(Utils::promoteKeys($table) as $name => $entry){
|
||||
if(!is_array($entry) || !is_string($name) || !isset($entry["component_based"], $entry["runtime_id"]) || !is_bool($entry["component_based"]) || !is_int($entry["runtime_id"])){
|
||||
if(!is_array($entry) || !is_string($name) || !isset($entry["component_based"], $entry["runtime_id"], $entry["version"]) || !is_bool($entry["component_based"]) || !is_int($entry["runtime_id"]) || !is_int($entry["version"]) || !(is_string($componentNbt = $entry["component_nbt"] ?? null) || $componentNbt === null)){
|
||||
throw new AssumptionFailedError("Invalid item list format");
|
||||
}
|
||||
$params[] = new ItemTypeEntry($name, $entry["runtime_id"], $entry["component_based"]);
|
||||
$params[] = new ItemTypeEntry($name, $entry["runtime_id"], $entry["component_based"], $entry["version"], $componentNbt === null ? $emptyNBT : new CacheableNbt($nbtSerializer->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($componentNbt, true)))->mustGetCompoundTag()));
|
||||
}
|
||||
return new ItemTypeDictionary($params);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\network\mcpe\cache\CraftingDataCache;
|
||||
use pocketmine\network\mcpe\cache\StaticPacketCache;
|
||||
use pocketmine\network\mcpe\InventoryManager;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\ItemRegistryPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
|
||||
use pocketmine\network\mcpe\protocol\StartGamePacket;
|
||||
@ -110,9 +111,11 @@ class PreSpawnPacketHandler extends PacketHandler{
|
||||
new NetworkPermissions(disableClientSounds: true),
|
||||
[],
|
||||
0,
|
||||
$typeConverter->getItemTypeDictionary()->getEntries(),
|
||||
));
|
||||
|
||||
$this->session->getLogger()->debug("Sending items");
|
||||
$this->session->sendDataPacket(ItemRegistryPacket::create($typeConverter->getItemTypeDictionary()->getEntries()));
|
||||
|
||||
$this->session->getLogger()->debug("Sending actor identifiers");
|
||||
$this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers());
|
||||
|
||||
|
@ -51,12 +51,12 @@ use function time;
|
||||
class BedrockWorldData extends BaseNbtWorldData{
|
||||
|
||||
public const CURRENT_STORAGE_VERSION = 10;
|
||||
public const CURRENT_STORAGE_NETWORK_VERSION = 748;
|
||||
public const CURRENT_STORAGE_NETWORK_VERSION = 776;
|
||||
public const CURRENT_CLIENT_VERSION_TARGET = [
|
||||
1, //major
|
||||
21, //minor
|
||||
40, //patch
|
||||
1, //revision
|
||||
60, //patch
|
||||
33, //revision
|
||||
0 //is beta
|
||||
];
|
||||
|
||||
|
@ -35,6 +35,7 @@ use pocketmine\crafting\json\SmithingTrimRecipeData;
|
||||
use pocketmine\data\bedrock\block\BlockStateData;
|
||||
use pocketmine\data\bedrock\item\BlockItemIdMap;
|
||||
use pocketmine\data\bedrock\item\ItemTypeNames;
|
||||
use pocketmine\inventory\json\CreativeGroupData;
|
||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
@ -48,15 +49,17 @@ use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\CreativeContentPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemRegistryPacket;
|
||||
use pocketmine\network\mcpe\protocol\PacketPool;
|
||||
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
|
||||
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
|
||||
use pocketmine\network\mcpe\protocol\StartGamePacket;
|
||||
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeContentEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\CreativeGroupEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackExtraData;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackExtraDataShield;
|
||||
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\ComplexAliasItemDescriptor;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe;
|
||||
use pocketmine\network\mcpe\protocol\types\recipe\IntIdMetaItemDescriptor;
|
||||
@ -134,6 +137,19 @@ class ParserPacketHandler extends PacketHandler{
|
||||
return base64_encode((new LittleEndianNbtSerializer())->write(new TreeRoot($statePropertiesTag)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ItemStackData[] $items
|
||||
*/
|
||||
private function creativeGroupEntryToJson(CreativeGroupEntry $entry, array $items) : CreativeGroupData{
|
||||
$data = new CreativeGroupData();
|
||||
|
||||
$data->group_name = $entry->getCategoryName();
|
||||
$data->group_icon = $entry->getIcon()->getId() === 0 ? null : $this->itemStackToJson($entry->getIcon());
|
||||
$data->items = $items;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function itemStackToJson(ItemStack $itemStack) : ItemStackData{
|
||||
if($itemStack->getId() === 0){
|
||||
throw new InvalidArgumentException("Cannot serialize a null itemstack");
|
||||
@ -234,31 +250,68 @@ class ParserPacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
public function handleStartGame(StartGamePacket $packet) : bool{
|
||||
$this->itemTypeDictionary = new ItemTypeDictionary($packet->itemTable);
|
||||
|
||||
echo "updating legacy item ID mapping table\n";
|
||||
$table = [];
|
||||
foreach($packet->itemTable as $entry){
|
||||
$table[$entry->getStringId()] = [
|
||||
"runtime_id" => $entry->getNumericId(),
|
||||
"component_based" => $entry->isComponentBased()
|
||||
];
|
||||
}
|
||||
ksort($table, SORT_STRING);
|
||||
file_put_contents($this->bedrockDataPath . '/required_item_list.json', json_encode($table, JSON_PRETTY_PRINT) . "\n");
|
||||
|
||||
foreach(Utils::promoteKeys($packet->levelSettings->experiments->getExperiments()) as $name => $experiment){
|
||||
echo "Experiment \"$name\" is " . ($experiment ? "" : "not ") . "active\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleItemRegistry(ItemRegistryPacket $packet) : bool{
|
||||
$this->itemTypeDictionary = new ItemTypeDictionary($packet->getEntries());
|
||||
|
||||
echo "updating legacy item ID mapping table\n";
|
||||
$emptyNBT = new CompoundTag();
|
||||
$table = [];
|
||||
foreach($packet->getEntries() as $entry){
|
||||
$table[$entry->getStringId()] = [
|
||||
"runtime_id" => $entry->getNumericId(),
|
||||
"component_based" => $entry->isComponentBased(),
|
||||
"version" => $entry->getVersion(),
|
||||
];
|
||||
|
||||
$componentNBT = $entry->getComponentNbt()->getRoot();
|
||||
if(!$componentNBT->equals($emptyNBT)){
|
||||
$table[$entry->getStringId()]["component_nbt"] = base64_encode((new LittleEndianNbtSerializer())->write(new TreeRoot($componentNBT)));
|
||||
}
|
||||
}
|
||||
ksort($table, SORT_STRING);
|
||||
file_put_contents($this->bedrockDataPath . '/required_item_list.json', json_encode($table, JSON_PRETTY_PRINT) . "\n");
|
||||
|
||||
echo "updating item registry\n";
|
||||
$items = array_map(function(ItemTypeEntry $entry) : array{
|
||||
return self::objectToOrderedArray($entry);
|
||||
}, $packet->getEntries());
|
||||
file_put_contents($this->bedrockDataPath . '/item_registry.json', json_encode($items, JSON_PRETTY_PRINT) . "\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleCreativeContent(CreativeContentPacket $packet) : bool{
|
||||
echo "updating creative inventory data\n";
|
||||
$items = array_map(function(CreativeContentEntry $entry) : array{
|
||||
return self::objectToOrderedArray($this->itemStackToJson($entry->getItem()));
|
||||
}, $packet->getEntries());
|
||||
file_put_contents($this->bedrockDataPath . '/creativeitems.json', json_encode($items, JSON_PRETTY_PRINT) . "\n");
|
||||
|
||||
$groupItems = [];
|
||||
foreach($packet->getItems() as $itemEntry){
|
||||
$groupItems[$itemEntry->getGroupId()][] = $this->itemStackToJson($itemEntry->getItem());
|
||||
}
|
||||
|
||||
static $typeMap = [
|
||||
CreativeContentPacket::CATEGORY_CONSTRUCTION => "construction",
|
||||
CreativeContentPacket::CATEGORY_NATURE => "nature",
|
||||
CreativeContentPacket::CATEGORY_EQUIPMENT => "equipment",
|
||||
CreativeContentPacket::CATEGORY_ITEMS => "items",
|
||||
];
|
||||
|
||||
$groupCategories = [];
|
||||
foreach(Utils::promoteKeys($packet->getGroups()) as $groupId => $group){
|
||||
$category = $typeMap[$group->getCategoryId()] ?? throw new PacketHandlingException("Unknown creative category ID " . $group->getCategoryId());
|
||||
//FIXME: objectToOrderedArray might mess with the order of groupItems
|
||||
//this isn't a problem right now because it's a list, but could cause problems in the future
|
||||
$groupCategories[$category][] = self::objectToOrderedArray($this->creativeGroupEntryToJson($group, $groupItems[$groupId]));
|
||||
}
|
||||
|
||||
foreach(Utils::promoteKeys($groupCategories) as $category => $categoryGroups){
|
||||
file_put_contents($this->bedrockDataPath . '/creative/' . $category . '.json', json_encode($categoryGroups, JSON_PRETTY_PRINT) . "\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user