mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Updated creative and crafting data to 1.19
This commit is contained in:
parent
59c5770cf2
commit
9f0b32e748
8
composer.lock
generated
8
composer.lock
generated
@ -280,12 +280,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "a546e15f6a8d7498fb25d5a02ce16184a429bb78"
|
||||
"reference": "01948a627448395d9946c2e6a5e8332a8456eaa0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/a546e15f6a8d7498fb25d5a02ce16184a429bb78",
|
||||
"reference": "a546e15f6a8d7498fb25d5a02ce16184a429bb78",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/01948a627448395d9946c2e6a5e8332a8456eaa0",
|
||||
"reference": "01948a627448395d9946c2e6a5e8332a8456eaa0",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -298,7 +298,7 @@
|
||||
"issues": "https://github.com/pmmp/BedrockData/issues",
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/modern-world-support"
|
||||
},
|
||||
"time": "2022-07-02T15:28:28+00:00"
|
||||
"time": "2022-07-04T16:59:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
|
@ -963,7 +963,7 @@ class Server{
|
||||
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
|
||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
|
||||
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes"));
|
||||
|
||||
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
|
||||
|
||||
|
@ -264,13 +264,13 @@ class CraftingManager{
|
||||
}
|
||||
|
||||
foreach($this->potionContainerChangeRecipes as $recipe){
|
||||
if($recipe->getIngredient()->equals($ingredient) && $recipe->getResultFor($input) !== null){
|
||||
if($recipe->getIngredient()->accepts($ingredient) && $recipe->getResultFor($input) !== null){
|
||||
return $this->brewingRecipeCache[$inputHash][$ingredientHash] = $recipe;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->potionTypeRecipes as $recipe){
|
||||
if($recipe->getIngredient()->equals($ingredient) && $recipe->getResultFor($input) !== null){
|
||||
if($recipe->getIngredient()->accepts($ingredient) && $recipe->getResultFor($input) !== null){
|
||||
return $this->brewingRecipeCache[$inputHash][$ingredientHash] = $recipe;
|
||||
}
|
||||
}
|
||||
|
@ -23,61 +23,205 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\crafting;
|
||||
|
||||
use pocketmine\crafting\json\FurnaceRecipeData;
|
||||
use pocketmine\crafting\json\ItemStackData;
|
||||
use pocketmine\crafting\json\PotionContainerChangeRecipeData;
|
||||
use pocketmine\crafting\json\PotionTypeRecipeData;
|
||||
use pocketmine\crafting\json\RecipeIngredientData;
|
||||
use pocketmine\crafting\json\ShapedRecipeData;
|
||||
use pocketmine\crafting\json\ShapelessRecipeData;
|
||||
use pocketmine\data\bedrock\block\BlockStateData;
|
||||
use pocketmine\data\bedrock\item\BlockItemIdMap;
|
||||
use pocketmine\data\bedrock\item\ItemTypeDeserializeException;
|
||||
use pocketmine\data\bedrock\item\upgrade\LegacyItemIdToStringIdMap;
|
||||
use pocketmine\data\bedrock\item\SavedItemData;
|
||||
use pocketmine\data\bedrock\item\SavedItemStackData;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\format\io\GlobalItemDataHandlers;
|
||||
use function array_map;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function base64_decode;
|
||||
use function file_get_contents;
|
||||
use function get_debug_type;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_object;
|
||||
use function json_decode;
|
||||
|
||||
final class CraftingManagerFromDataHelper{
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
*/
|
||||
private static function deserializeIngredient(array $data) : ?RecipeIngredient{
|
||||
if(!isset($data["id"]) || !is_int($data["id"])){
|
||||
throw new \InvalidArgumentException("Invalid input data, expected int ID");
|
||||
}
|
||||
if(isset($data["damage"]) && $data["damage"] === -1){
|
||||
try{
|
||||
$typeData = GlobalItemDataHandlers::getUpgrader()->upgradeItemTypeDataInt($data["id"], 0, 1, null);
|
||||
}catch(ItemTypeDeserializeException){
|
||||
//probably unknown item
|
||||
return null;
|
||||
|
||||
private static function deserializeItemStackFromNameMeta(string $name, int $meta) : ?Item{
|
||||
$blockName = BlockItemIdMap::getInstance()->lookupBlockId($name);
|
||||
if($blockName !== null){
|
||||
$blockStateDictionary = RuntimeBlockMapping::getInstance()->getBlockStateDictionary();
|
||||
$blockRuntimeId = $blockStateDictionary->lookupStateIdFromIdMeta($name, $meta === RecipeIngredientData::WILDCARD_META_VALUE ? 0 : $meta);
|
||||
if($blockRuntimeId === null){
|
||||
throw new \InvalidArgumentException("$blockName with meta $meta doesn't map to any known blockstate");
|
||||
}
|
||||
|
||||
return new MetaWildcardRecipeIngredient($typeData->getTypeData()->getName());
|
||||
$blockStateData = $blockStateDictionary->getDataFromStateId($blockRuntimeId);
|
||||
if($blockStateData === null){
|
||||
throw new AssumptionFailedError("We just looked up the runtime ID for this state, so it can't possibly be null");
|
||||
}
|
||||
}else{
|
||||
$blockStateData = null;
|
||||
}
|
||||
|
||||
//TODO: we need to stop using jsonDeserialize for this
|
||||
//TODO: for wildcards, we only need a way to check if the item serializer recognizes the ID; we don't need to
|
||||
//deserialize the whole itemstack, which might give bogus results anyway if meta 0 isn't recognized
|
||||
$itemTypeData = new SavedItemData(
|
||||
$name,
|
||||
$meta === RecipeIngredientData::WILDCARD_META_VALUE ? 0 : $meta,
|
||||
$blockStateData,
|
||||
null
|
||||
);
|
||||
|
||||
try{
|
||||
$item = Item::legacyJsonDeserialize($data);
|
||||
}catch(SavedDataLoadingException){
|
||||
//unknown item
|
||||
return GlobalItemDataHandlers::getDeserializer()->deserializeType($itemTypeData);
|
||||
}catch(ItemTypeDeserializeException){
|
||||
//probably unknown item
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExactRecipeIngredient($item);
|
||||
}
|
||||
|
||||
public static function make(string $filePath) : CraftingManager{
|
||||
$recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true);
|
||||
if(!is_array($recipes)){
|
||||
throw new AssumptionFailedError("recipes.json root should contain a map of recipe types");
|
||||
private static function deserializeIngredient(RecipeIngredientData $data) : ?RecipeIngredient{
|
||||
if(isset($data->count) && $data->count !== 1){
|
||||
//every case we've seen so far where this isn't the case, it's been a bug and the count was ignored anyway
|
||||
//e.g. gold blocks crafted from 9 ingots, but each input item individually had a count of 9
|
||||
throw new SavedDataLoadingException("Recipe inputs should have a count of exactly 1");
|
||||
}
|
||||
|
||||
$itemStack = self::deserializeItemStackFromNameMeta($data->name, $data->meta);
|
||||
if($itemStack === null){
|
||||
//probably unknown item
|
||||
return null;
|
||||
}
|
||||
return $data->meta === RecipeIngredientData::WILDCARD_META_VALUE ?
|
||||
new MetaWildcardRecipeIngredient($data->name) :
|
||||
new ExactRecipeIngredient($itemStack);
|
||||
}
|
||||
|
||||
public static function deserializeItemStack(ItemStackData $data) : ?Item{
|
||||
//count, name, block_name, block_states, meta, nbt, can_place_on, can_destroy
|
||||
$name = $data->name;
|
||||
$meta = $data->meta ?? 0;
|
||||
$count = $data->count ?? 1;
|
||||
|
||||
$blockStatesRaw = $data->block_states ?? null;
|
||||
$nbtRaw = $data->nbt ?? null;
|
||||
$canPlaceOn = $data->can_place_on ?? [];
|
||||
$canDestroy = $data->can_destroy ?? [];
|
||||
|
||||
$blockName = BlockItemIdMap::getInstance()->lookupBlockId($name);
|
||||
if($blockName !== null){
|
||||
if($meta !== 0){
|
||||
throw new \InvalidArgumentException("Meta should not be specified for blockitems");
|
||||
}
|
||||
$blockStatesTag = $blockStatesRaw === null ?
|
||||
CompoundTag::create() :
|
||||
(new LittleEndianNbtSerializer())
|
||||
->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($blockStatesRaw, true)))
|
||||
->mustGetCompoundTag();
|
||||
$blockStateData = new BlockStateData($blockName, $blockStatesTag, BlockStateData::CURRENT_VERSION);
|
||||
}else{
|
||||
$blockStateData = null;
|
||||
}
|
||||
|
||||
$nbt = $nbtRaw === null ? null : (new LittleEndianNbtSerializer())
|
||||
->read(ErrorToExceptionHandler::trapAndRemoveFalse(fn() => base64_decode($nbtRaw, true)))
|
||||
->mustGetCompoundTag();
|
||||
|
||||
$itemStackData = new SavedItemStackData(
|
||||
new SavedItemData(
|
||||
$name,
|
||||
$meta,
|
||||
$blockStateData,
|
||||
$nbt
|
||||
),
|
||||
$count,
|
||||
null,
|
||||
null,
|
||||
$canPlaceOn,
|
||||
$canDestroy,
|
||||
);
|
||||
|
||||
try{
|
||||
return GlobalItemDataHandlers::getDeserializer()->deserializeStack($itemStackData);
|
||||
}catch(ItemTypeDeserializeException){
|
||||
//probably unknown item
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*
|
||||
* @phpstan-template TData of object
|
||||
* @phpstan-param class-string<TData> $modelCLass
|
||||
* @phpstan-return list<TData>
|
||||
*/
|
||||
public static function loadJsonArrayOfObjectsFile(string $filePath, string $modelCLass) : array{
|
||||
$recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"));
|
||||
if(!is_array($recipes)){
|
||||
throw new AssumptionFailedError("$filePath root should be an array, got " . get_debug_type($recipes));
|
||||
}
|
||||
|
||||
$mapper = new \JsonMapper();
|
||||
$mapper->bStrictObjectTypeChecking = true;
|
||||
$mapper->bExceptionOnUndefinedProperty = true;
|
||||
$mapper->bExceptionOnMissingData = true;
|
||||
|
||||
return self::loadJsonObjectListIntoModel($mapper, $modelCLass, $recipes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-template TRecipeData of object
|
||||
* @phpstan-param class-string<TRecipeData> $modelClass
|
||||
* @phpstan-return TRecipeData
|
||||
*/
|
||||
private static function loadJsonObjectIntoModel(\JsonMapper $mapper, string $modelClass, object $data) : object{
|
||||
//JsonMapper does this for subtypes, but not for the base type :(
|
||||
try{
|
||||
return $mapper->map($data, (new \ReflectionClass($modelClass))->newInstanceWithoutConstructor());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $data
|
||||
* @return object[]
|
||||
*
|
||||
* @phpstan-template TRecipeData of object
|
||||
* @phpstan-param class-string<TRecipeData> $modelClass
|
||||
* @phpstan-return list<TRecipeData>
|
||||
*/
|
||||
private static function loadJsonObjectListIntoModel(\JsonMapper $mapper, string $modelClass, array $data) : array{
|
||||
$result = [];
|
||||
foreach($data as $i => $item){
|
||||
if(!is_object($item)){
|
||||
throw new SavedDataLoadingException("Invalid entry at index $i: expected object, got " . get_debug_type($item));
|
||||
}
|
||||
try{
|
||||
$result[] = self::loadJsonObjectIntoModel($mapper, $modelClass, $item);
|
||||
}catch(SavedDataLoadingException $e){
|
||||
throw new SavedDataLoadingException("Invalid entry at index $i: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function make(string $directoryPath) : CraftingManager{
|
||||
$result = new CraftingManager();
|
||||
|
||||
$ingredientDeserializerFunc = \Closure::fromCallable([self::class, "deserializeIngredient"]);
|
||||
$itemDeserializerFunc = \Closure::fromCallable([Item::class, 'legacyJsonDeserialize']);
|
||||
$itemDeserializerFunc = \Closure::fromCallable([self::class, 'deserializeItemStack']);
|
||||
|
||||
foreach($recipes["shapeless"] as $recipe){
|
||||
$recipeType = match($recipe["block"]){
|
||||
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'shapeless_crafting.json'), ShapelessRecipeData::class) as $recipe){
|
||||
$recipeType = match($recipe->block){
|
||||
"crafting_table" => ShapelessRecipeType::CRAFTING(),
|
||||
"stonecutter" => ShapelessRecipeType::STONECUTTER(),
|
||||
//TODO: Cartography Table
|
||||
@ -87,18 +231,20 @@ final class CraftingManagerFromDataHelper{
|
||||
continue;
|
||||
}
|
||||
$inputs = [];
|
||||
foreach($recipe["input"] as $inputData){
|
||||
foreach($recipe->input as $inputData){
|
||||
$input = $ingredientDeserializerFunc($inputData);
|
||||
if($input === null){ //unknown input item
|
||||
continue 2;
|
||||
}
|
||||
$inputs[] = $input;
|
||||
}
|
||||
try{
|
||||
$outputs = array_map($itemDeserializerFunc, $recipe["output"]);
|
||||
}catch(SavedDataLoadingException){
|
||||
//unknown output item
|
||||
continue;
|
||||
$outputs = [];
|
||||
foreach($recipe->output as $outputData){
|
||||
$output = $itemDeserializerFunc($outputData);
|
||||
if($output === null){ //unknown output item
|
||||
continue 2;
|
||||
}
|
||||
$outputs[] = $output;
|
||||
}
|
||||
$result->registerShapelessRecipe(new ShapelessRecipe(
|
||||
$inputs,
|
||||
@ -106,32 +252,34 @@ final class CraftingManagerFromDataHelper{
|
||||
$recipeType
|
||||
));
|
||||
}
|
||||
foreach($recipes["shaped"] as $recipe){
|
||||
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
|
||||
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'shaped_crafting.json'), ShapedRecipeData::class) as $recipe){
|
||||
if($recipe->block !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
|
||||
continue;
|
||||
}
|
||||
$inputs = [];
|
||||
foreach($recipe["input"] as $symbol => $inputData){
|
||||
foreach(Utils::stringifyKeys($recipe->input) as $symbol => $inputData){
|
||||
$input = $ingredientDeserializerFunc($inputData);
|
||||
if($input === null){ //unknown input item
|
||||
continue 2;
|
||||
}
|
||||
$inputs[$symbol] = $input;
|
||||
}
|
||||
try{
|
||||
$outputs = array_map($itemDeserializerFunc, $recipe["output"]);
|
||||
}catch(SavedDataLoadingException){
|
||||
//unknown output item
|
||||
continue;
|
||||
$outputs = [];
|
||||
foreach($recipe->output as $outputData){
|
||||
$output = $itemDeserializerFunc($outputData);
|
||||
if($output === null){ //unknown output item
|
||||
continue 2;
|
||||
}
|
||||
$outputs[] = $output;
|
||||
}
|
||||
$result->registerShapedRecipe(new ShapedRecipe(
|
||||
$recipe["shape"],
|
||||
$recipe->shape,
|
||||
$inputs,
|
||||
$outputs
|
||||
));
|
||||
}
|
||||
foreach($recipes["smelting"] as $recipe){
|
||||
$furnaceType = match ($recipe["block"]){
|
||||
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'smelting.json'), FurnaceRecipeData::class) as $recipe){
|
||||
$furnaceType = match ($recipe->block){
|
||||
"furnace" => FurnaceType::FURNACE(),
|
||||
"blast_furnace" => FurnaceType::BLAST_FURNACE(),
|
||||
"smoker" => FurnaceType::SMOKER(),
|
||||
@ -141,12 +289,11 @@ final class CraftingManagerFromDataHelper{
|
||||
if($furnaceType === null){
|
||||
continue;
|
||||
}
|
||||
try{
|
||||
$output = Item::legacyJsonDeserialize($recipe["output"]);
|
||||
}catch(SavedDataLoadingException){
|
||||
$output = self::deserializeItemStack($recipe->output);
|
||||
if($output === null){
|
||||
continue;
|
||||
}
|
||||
$input = self::deserializeIngredient($recipe["input"]);
|
||||
$input = self::deserializeIngredient($recipe->input);
|
||||
if($input === null){
|
||||
continue;
|
||||
}
|
||||
@ -155,13 +302,12 @@ final class CraftingManagerFromDataHelper{
|
||||
$input
|
||||
));
|
||||
}
|
||||
foreach($recipes["potion_type"] as $recipe){
|
||||
try{
|
||||
$input = Item::legacyJsonDeserialize($recipe["input"]);
|
||||
$ingredient = Item::legacyJsonDeserialize($recipe["ingredient"]);
|
||||
$output = Item::legacyJsonDeserialize($recipe["output"]);
|
||||
}catch(SavedDataLoadingException){
|
||||
//unknown item
|
||||
|
||||
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'potion_type.json'), PotionTypeRecipeData::class) as $recipe){
|
||||
$input = self::deserializeIngredient($recipe->input);
|
||||
$ingredient = self::deserializeIngredient($recipe->ingredient);
|
||||
$output = self::deserializeItemStack($recipe->output);
|
||||
if($input === null || $ingredient === null || $output === null){
|
||||
continue;
|
||||
}
|
||||
$result->registerPotionTypeRecipe(new PotionTypeRecipe(
|
||||
@ -170,18 +316,16 @@ final class CraftingManagerFromDataHelper{
|
||||
$output
|
||||
));
|
||||
}
|
||||
foreach($recipes["potion_container_change"] as $recipe){
|
||||
try{
|
||||
$ingredient = Item::legacyJsonDeserialize($recipe["ingredient"]);
|
||||
}catch(SavedDataLoadingException){
|
||||
//unknown item
|
||||
foreach(self::loadJsonArrayOfObjectsFile(Path::join($directoryPath, 'potion_container_change.json'), PotionContainerChangeRecipeData::class) as $recipe){
|
||||
$ingredient = self::deserializeIngredient($recipe->ingredient);
|
||||
if($ingredient === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: we'll be able to get rid of these conversions once the crafting data is updated
|
||||
$inputId = LegacyItemIdToStringIdMap::getInstance()->legacyToString($recipe["input_item_id"]);
|
||||
$outputId = LegacyItemIdToStringIdMap::getInstance()->legacyToString($recipe["output_item_id"]);
|
||||
if($inputId === null || $outputId === null){
|
||||
$inputId = $recipe->input_item_name;
|
||||
$outputId = $recipe->output_item_name;
|
||||
|
||||
if(self::deserializeItemStackFromNameMeta($inputId, 0) === null || self::deserializeItemStackFromNameMeta($outputId, 0) === null){
|
||||
//unknown item
|
||||
continue;
|
||||
}
|
||||
|
@ -31,18 +31,16 @@ class PotionContainerChangeRecipe implements BrewingRecipe{
|
||||
|
||||
public function __construct(
|
||||
private string $inputItemId,
|
||||
private Item $ingredient,
|
||||
private RecipeIngredient $ingredient,
|
||||
private string $outputItemId
|
||||
){
|
||||
$this->ingredient = clone $ingredient;
|
||||
}
|
||||
){}
|
||||
|
||||
public function getInputItemId() : string{
|
||||
return $this->inputItemId;
|
||||
}
|
||||
|
||||
public function getIngredient() : Item{
|
||||
return clone $this->ingredient;
|
||||
public function getIngredient() : RecipeIngredient{
|
||||
return $this->ingredient;
|
||||
}
|
||||
|
||||
public function getOutputItemId() : string{
|
||||
|
@ -28,21 +28,19 @@ use pocketmine\item\Item;
|
||||
class PotionTypeRecipe implements BrewingRecipe{
|
||||
|
||||
public function __construct(
|
||||
private Item $input,
|
||||
private Item $ingredient,
|
||||
private RecipeIngredient $input,
|
||||
private RecipeIngredient $ingredient,
|
||||
private Item $output
|
||||
){
|
||||
$this->input = clone $input;
|
||||
$this->ingredient = clone $ingredient;
|
||||
$this->output = clone $output;
|
||||
}
|
||||
|
||||
public function getInput() : Item{
|
||||
return clone $this->input;
|
||||
public function getInput() : RecipeIngredient{
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
public function getIngredient() : Item{
|
||||
return clone $this->ingredient;
|
||||
public function getIngredient() : RecipeIngredient{
|
||||
return $this->ingredient;
|
||||
}
|
||||
|
||||
public function getOutput() : Item{
|
||||
@ -50,6 +48,6 @@ class PotionTypeRecipe implements BrewingRecipe{
|
||||
}
|
||||
|
||||
public function getResultFor(Item $input) : ?Item{
|
||||
return $input->equals($this->input, true, false) ? $this->getOutput() : null;
|
||||
return $this->input->accepts($input) ? $this->getOutput() : null;
|
||||
}
|
||||
}
|
||||
|
42
src/crafting/json/FurnaceRecipeData.php
Normal file
42
src/crafting/json/FurnaceRecipeData.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class FurnaceRecipeData{
|
||||
|
||||
/** @required */
|
||||
public RecipeIngredientData $input;
|
||||
|
||||
/** @required */
|
||||
public ItemStackData $output;
|
||||
|
||||
/** @required */
|
||||
public string $block;
|
||||
|
||||
public function __construct(RecipeIngredientData $input, ItemStackData $output, string $block){
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
$this->block = $block;
|
||||
}
|
||||
}
|
43
src/crafting/json/ItemStackData.php
Normal file
43
src/crafting/json/ItemStackData.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class ItemStackData{
|
||||
|
||||
/** @required */
|
||||
public string $name;
|
||||
|
||||
public int $count;
|
||||
public string $block_states;
|
||||
public int $meta;
|
||||
public string $nbt;
|
||||
/** @var string[] */
|
||||
public array $can_place_on;
|
||||
/** @var string[] */
|
||||
public array $can_destroy;
|
||||
|
||||
public function __construct(string $name){
|
||||
$this->name = $name;
|
||||
}
|
||||
}
|
41
src/crafting/json/PotionContainerChangeRecipeData.php
Normal file
41
src/crafting/json/PotionContainerChangeRecipeData.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class PotionContainerChangeRecipeData{
|
||||
/** @required */
|
||||
public string $input_item_name;
|
||||
|
||||
/** @required */
|
||||
public RecipeIngredientData $ingredient;
|
||||
|
||||
/** @required */
|
||||
public string $output_item_name;
|
||||
|
||||
public function __construct(string $input_item_name, RecipeIngredientData $ingredient, string $output_item_name){
|
||||
$this->input_item_name = $input_item_name;
|
||||
$this->ingredient = $ingredient;
|
||||
$this->output_item_name = $output_item_name;
|
||||
}
|
||||
}
|
41
src/crafting/json/PotionTypeRecipeData.php
Normal file
41
src/crafting/json/PotionTypeRecipeData.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class PotionTypeRecipeData{
|
||||
/** @required */
|
||||
public RecipeIngredientData $input;
|
||||
|
||||
/** @required */
|
||||
public RecipeIngredientData $ingredient;
|
||||
|
||||
/** @required */
|
||||
public ItemStackData $output;
|
||||
|
||||
public function __construct(RecipeIngredientData $input, RecipeIngredientData $ingredient, ItemStackData $output){
|
||||
$this->input = $input;
|
||||
$this->ingredient = $ingredient;
|
||||
$this->output = $output;
|
||||
}
|
||||
}
|
40
src/crafting/json/RecipeIngredientData.php
Normal file
40
src/crafting/json/RecipeIngredientData.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class RecipeIngredientData{
|
||||
public const WILDCARD_META_VALUE = 32767;
|
||||
|
||||
/** @required */
|
||||
public string $name;
|
||||
/** @required */
|
||||
public int $meta;
|
||||
|
||||
public int $count;
|
||||
|
||||
public function __construct(string $name, int $meta){
|
||||
$this->name = $name;
|
||||
$this->meta = $meta;
|
||||
}
|
||||
}
|
72
src/crafting/json/ShapedRecipeData.php
Normal file
72
src/crafting/json/ShapedRecipeData.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class ShapedRecipeData{
|
||||
/**
|
||||
* @required
|
||||
* @var string[]
|
||||
* @phpstan-var list<string>
|
||||
*/
|
||||
public array $shape;
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @var RecipeIngredientData[]
|
||||
* @phpstan-var array<string, RecipeIngredientData>
|
||||
*/
|
||||
public array $input;
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @var ItemStackData[]
|
||||
* @phpstan-var list<ItemStackData>
|
||||
*/
|
||||
public array $output;
|
||||
|
||||
/** @required */
|
||||
public string $block;
|
||||
|
||||
/** @required */
|
||||
public int $priority;
|
||||
|
||||
/**
|
||||
* TODO: convert this to use promoted properties - avoiding them for now since it would break JsonMapper
|
||||
*
|
||||
* @param string[] $shape
|
||||
* @param RecipeIngredientData[] $input
|
||||
* @param ItemStackData[] $output
|
||||
*
|
||||
* @phpstan-param list<string> $shape
|
||||
* @phpstan-param array<string, RecipeIngredientData> $input
|
||||
* @phpstan-param list<ItemStackData> $output
|
||||
*/
|
||||
public function __construct(array $shape, array $input, array $output, string $block, int $priority){
|
||||
$this->block = $block;
|
||||
$this->priority = $priority;
|
||||
$this->shape = $shape;
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
}
|
||||
}
|
61
src/crafting/json/ShapelessRecipeData.php
Normal file
61
src/crafting/json/ShapelessRecipeData.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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\crafting\json;
|
||||
|
||||
final class ShapelessRecipeData{
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @var RecipeIngredientData[]
|
||||
* @phpstan-var list<RecipeIngredientData>
|
||||
*/
|
||||
public array $input;
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @var ItemStackData[]
|
||||
* @phpstan-var list<ItemStackData>
|
||||
*/
|
||||
public array $output;
|
||||
|
||||
/** @required */
|
||||
public string $block;
|
||||
|
||||
/** @required */
|
||||
public int $priority;
|
||||
|
||||
/**
|
||||
* @param RecipeIngredientData[] $input
|
||||
* @param ItemStackData[] $output
|
||||
*
|
||||
* @phpstan-param list<RecipeIngredientData> $input
|
||||
* @phpstan-param list<ItemStackData> $output
|
||||
*/
|
||||
public function __construct(array $input, array $output, string $block, int $priority){
|
||||
$this->block = $block;
|
||||
$this->priority = $priority;
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use pocketmine\utils\Utils;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function array_search;
|
||||
use function array_flip;
|
||||
use function file_get_contents;
|
||||
use function is_array;
|
||||
use function json_decode;
|
||||
@ -52,20 +52,25 @@ final class BlockItemIdMap{
|
||||
return new self($map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @phpstan-var array<string, string>
|
||||
*/
|
||||
private array $itemToBlockId;
|
||||
|
||||
/**
|
||||
* @param string[] $blockToItemId
|
||||
* @phpstan-param array<string, string> $blockToItemId
|
||||
*/
|
||||
public function __construct(private array $blockToItemId){}
|
||||
public function __construct(private array $blockToItemId){
|
||||
$this->itemToBlockId = array_flip($this->blockToItemId);
|
||||
}
|
||||
|
||||
public function lookupItemId(string $blockId) : ?string{
|
||||
return $this->blockToItemId[$blockId] ?? null;
|
||||
}
|
||||
|
||||
public function lookupBlockId(string $itemId) : ?string{
|
||||
//we don't need this for any functionality, so we're not concerned about performance here
|
||||
//however, it might be nice to have for debugging
|
||||
$blockId = array_search($itemId, $this->blockToItemId, true);
|
||||
return $blockId !== false ? $blockId : null;
|
||||
return $this->itemToBlockId[$itemId] ?? null;
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\inventory;
|
||||
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\crafting\CraftingManagerFromDataHelper;
|
||||
use pocketmine\crafting\json\ItemStackData;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function file_get_contents;
|
||||
use function is_array;
|
||||
use function json_decode;
|
||||
|
||||
final class CreativeInventory{
|
||||
use SingletonTrait;
|
||||
@ -38,18 +36,13 @@ final class CreativeInventory{
|
||||
private array $creative = [];
|
||||
|
||||
private function __construct(){
|
||||
$creativeItems = json_decode(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "creativeitems.json")), true);
|
||||
if(!is_array($creativeItems)){
|
||||
throw new SavedDataLoadingException("Invalid creative items file, expected array as root type");
|
||||
}
|
||||
|
||||
$creativeItems = CraftingManagerFromDataHelper::loadJsonArrayOfObjectsFile(
|
||||
Path::join(\pocketmine\BEDROCK_DATA_PATH, "creativeitems.json"),
|
||||
ItemStackData::class
|
||||
);
|
||||
foreach($creativeItems as $data){
|
||||
if(!is_array($data)){
|
||||
throw new SavedDataLoadingException("Invalid creative items file, expected array as item type");
|
||||
}
|
||||
try{
|
||||
$item = Item::legacyJsonDeserialize($data);
|
||||
}catch(SavedDataLoadingException){
|
||||
$item = CraftingManagerFromDataHelper::deserializeItemStack($data);
|
||||
if($item === null){
|
||||
//unknown item
|
||||
continue;
|
||||
}
|
||||
|
6
src/network/mcpe/cache/CraftingDataCache.php
vendored
6
src/network/mcpe/cache/CraftingDataCache.php
vendored
@ -149,8 +149,8 @@ final class CraftingDataCache{
|
||||
|
||||
$potionTypeRecipes = [];
|
||||
foreach($manager->getPotionTypeRecipes() as $recipe){
|
||||
$input = $converter->coreItemStackToNet($recipe->getInput());
|
||||
$ingredient = $converter->coreItemStackToNet($recipe->getIngredient());
|
||||
$input = $converter->coreRecipeIngredientToNet($recipe->getInput());
|
||||
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient());
|
||||
$output = $converter->coreItemStackToNet($recipe->getOutput());
|
||||
$potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
|
||||
$input->getId(),
|
||||
@ -166,7 +166,7 @@ final class CraftingDataCache{
|
||||
$itemTypeDictionary = GlobalItemTypeDictionary::getInstance()->getDictionary();
|
||||
foreach($manager->getPotionContainerChangeRecipes() as $recipe){
|
||||
$input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
|
||||
$ingredient = $converter->coreItemStackToNet($recipe->getIngredient());
|
||||
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient());
|
||||
$output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
|
||||
$potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
|
||||
$input,
|
||||
|
@ -575,21 +575,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/inventory/CreativeInventory.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$data of static method pocketmine\\\\item\\\\Item\\:\\:jsonDeserialize\\(\\) expects array, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/inventory/CreativeInventory.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/inventory/CreativeInventory.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$recipe of class pocketmine\\\\event\\\\inventory\\\\CraftItemEvent constructor expects pocketmine\\\\crafting\\\\CraftingRecipe, pocketmine\\\\crafting\\\\CraftingRecipe\\|null given\\.$#"
|
||||
count: 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user