mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-12 06:25:32 +00:00
continue refactoring, not finished, not tested
This is a bump from my workspace
This commit is contained in:
parent
a1695a52d5
commit
b4cb09fe5e
@ -39,20 +39,23 @@ final class AnvilHelper{
|
||||
public static function calculateResult(Player $player, Item $base, Item $material, ?string $customName = null) : ?AnvilCraftResult {
|
||||
|
||||
$recipe = Server::getInstance()->getCraftingManager()->matchAnvilRecipe($base, $material);
|
||||
if($recipe === null){
|
||||
return null;
|
||||
}
|
||||
$result = $recipe->getResultFor($base, $material);
|
||||
|
||||
if($result !== null){
|
||||
$resultItem = $result->getResult();
|
||||
$resultItem = $result->getOutput();
|
||||
$xpCost = $result->getXpCost();
|
||||
if(($customName === null || $customName === "") && $resultItem->hasCustomName()){
|
||||
$xpCost++;
|
||||
$resultItem->clearCustomName();
|
||||
}elseif($resultItem->getCustomName() !== $customName){
|
||||
}elseif($customName !== null && $resultItem->getCustomName() !== $customName){
|
||||
$xpCost++;
|
||||
$resultItem->setCustomName($customName);
|
||||
}
|
||||
|
||||
$result = new AnvilCraftResult($xpCost, $resultItem);
|
||||
$result = new AnvilCraftResult($xpCost, $resultItem, $result->getSacrificeResult());
|
||||
}
|
||||
|
||||
if($result === null || $result->getXpCost() <= 0 || ($result->getXpCost() > self::COST_LIMIT && !$player->isCreative())){
|
||||
|
@ -25,17 +25,44 @@ namespace pocketmine\crafting;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
/**
|
||||
* This class is here to hold the result of an anvil crafting process.
|
||||
*/
|
||||
class AnvilCraftResult{
|
||||
/**
|
||||
* @param int $xpCost
|
||||
* @param Item $output
|
||||
* @param Item|null $sacrificeResult If the given item is considered as null (count <= 0), the value will be set to null.
|
||||
*/
|
||||
public function __construct(
|
||||
private int $xpCost,
|
||||
private Item $result,
|
||||
){}
|
||||
private Item $output,
|
||||
private ?Item $sacrificeResult
|
||||
){
|
||||
if($this->sacrificeResult !== null && $this->sacrificeResult->isNull()){
|
||||
$this->sacrificeResult = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent the amount of experience points required to craft the output item.
|
||||
*/
|
||||
public function getXpCost() : int{
|
||||
return $this->xpCost;
|
||||
}
|
||||
|
||||
public function getResult() : Item{
|
||||
return $this->result;
|
||||
/**
|
||||
* Represent the item given as output of the crafting process.
|
||||
*/
|
||||
public function getOutput() : Item{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* This result has to be null if the sacrifice slot need to be emptied.
|
||||
* If not null, it represent the item that will be left in the sacrifice slot after the crafting process.
|
||||
*/
|
||||
public function getSacrificeResult() : ?Item{
|
||||
return $this->sacrificeResult;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,5 @@ namespace pocketmine\crafting;
|
||||
use pocketmine\item\Item;
|
||||
|
||||
interface AnvilRecipe{
|
||||
public function getXpCost() : int;
|
||||
|
||||
public function getResultFor(Item $input, Item $material) : ?AnvilCraftResult;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use function count;
|
||||
use function implode;
|
||||
use function ksort;
|
||||
use function spl_object_id;
|
||||
use function var_dump;
|
||||
use const SORT_STRING;
|
||||
|
||||
class CraftingManager{
|
||||
|
@ -31,8 +31,10 @@ 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\block\BlockTypeNames;
|
||||
use pocketmine\data\bedrock\item\BlockItemIdMap;
|
||||
use pocketmine\data\bedrock\item\ItemTypeDeserializeException;
|
||||
use pocketmine\data\bedrock\item\ItemTypeNames;
|
||||
use pocketmine\data\bedrock\item\SavedItemData;
|
||||
use pocketmine\data\bedrock\item\SavedItemStackData;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
@ -335,15 +337,13 @@ final class CraftingManagerFromDataHelper{
|
||||
}
|
||||
|
||||
$result->registerAnvilRecipe(new MaterialRepairRecipe(
|
||||
new ExactRecipeIngredient(VanillaItems::DIAMOND_PICKAXE()),
|
||||
new ExactRecipeIngredient(VanillaItems::DIAMOND()),
|
||||
VanillaItems::DIAMOND_PICKAXE()
|
||||
new MetaWildcardRecipeIngredient(ItemTypeNames::DIAMOND_PICKAXE),
|
||||
new ExactRecipeIngredient(VanillaItems::DIAMOND())
|
||||
));
|
||||
|
||||
$result->registerAnvilRecipe(new ItemCombineRecipe(
|
||||
new ExactRecipeIngredient(VanillaItems::DIAMOND_PICKAXE()),
|
||||
new ExactRecipeIngredient(VanillaItems::DIAMOND_PICKAXE()),
|
||||
VanillaItems::DIAMOND_PICKAXE()
|
||||
new MetaWildcardRecipeIngredient(ItemTypeNames::DIAMOND_PICKAXE),
|
||||
new MetaWildcardRecipeIngredient(ItemTypeNames::DIAMOND_PICKAXE)
|
||||
));
|
||||
|
||||
//TODO: smithing
|
||||
|
@ -40,8 +40,7 @@ use function min;
|
||||
class ItemCombineRecipe implements AnvilRecipe{
|
||||
public function __construct(
|
||||
private RecipeIngredient $input,
|
||||
private RecipeIngredient $material,
|
||||
private Item $result
|
||||
private RecipeIngredient $material
|
||||
){ }
|
||||
|
||||
public function getInput() : RecipeIngredient{
|
||||
@ -52,22 +51,14 @@ class ItemCombineRecipe implements AnvilRecipe{
|
||||
return $this->material;
|
||||
}
|
||||
|
||||
public function getResult() : Item{
|
||||
return clone $this->result;
|
||||
}
|
||||
|
||||
public function getXpCost() : int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getResultFor(Item $input, Item $material) : ?AnvilCraftResult{
|
||||
if($input->equals($this->input->getItem()) && $material->equals($this->material->getItem())){
|
||||
$result = $this->getResult();
|
||||
if($this->input->accepts($input) && $this->material->accepts($material)){
|
||||
$result = (clone $input);
|
||||
$xpCost = 0;
|
||||
if($input instanceof Durable && $material instanceof Durable){
|
||||
$damage = $input->getDamage();
|
||||
if($result instanceof Durable && $material instanceof Durable){
|
||||
$damage = $result->getDamage();
|
||||
if($damage !== 0){
|
||||
$baseMaxDurability = $input->getMaxDurability();
|
||||
$baseMaxDurability = $result->getMaxDurability();
|
||||
$baseDurability = $baseMaxDurability - $damage;
|
||||
$materialDurability = $material->getMaxDurability() - $material->getDamage();
|
||||
$addDurability = (int) ($baseMaxDurability * 12 / 100);
|
||||
@ -78,11 +69,6 @@ class ItemCombineRecipe implements AnvilRecipe{
|
||||
$xpCost = 2;
|
||||
}
|
||||
|
||||
// setting base enchantments to result
|
||||
foreach($input->getEnchantments() as $enchantment){
|
||||
$result->addEnchantment($enchantment);
|
||||
}
|
||||
|
||||
// combining enchantments
|
||||
foreach($material->getEnchantments() as $instance){
|
||||
$enchantment = $instance->getType();
|
||||
@ -131,7 +117,7 @@ class ItemCombineRecipe implements AnvilRecipe{
|
||||
);
|
||||
}
|
||||
|
||||
return new AnvilCraftResult($xpCost, $result);
|
||||
return new AnvilCraftResult($xpCost, $result, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -23,11 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\crafting;
|
||||
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use function ceil;
|
||||
use function floor;
|
||||
use function max;
|
||||
use function min;
|
||||
use function var_dump;
|
||||
|
||||
/**
|
||||
* Represent a recipe that repair an item with a material in an anvil.
|
||||
@ -35,8 +38,7 @@ use function min;
|
||||
class MaterialRepairRecipe implements AnvilRecipe{
|
||||
public function __construct(
|
||||
private RecipeIngredient $input,
|
||||
private RecipeIngredient $material,
|
||||
private Item $result
|
||||
private RecipeIngredient $material
|
||||
){ }
|
||||
|
||||
public function getInput() : RecipeIngredient{
|
||||
@ -47,16 +49,8 @@ class MaterialRepairRecipe implements AnvilRecipe{
|
||||
return $this->material;
|
||||
}
|
||||
|
||||
public function getResult() : Item{
|
||||
return clone $this->result;
|
||||
}
|
||||
|
||||
public function getXpCost() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getResultFor(Item $input, Item $material) : ?Item{
|
||||
if($this->input->accepts($input) && $this->material->accepts($material)){
|
||||
public function getResultFor(Item $input, Item $material) : ?AnvilCraftResult{
|
||||
if($this->input->accepts($input) && $this->material->accepts($material) && $input instanceof Durable){
|
||||
$damage = $input->getDamage();
|
||||
if($damage !== 0){
|
||||
$quarter = min($damage, (int) floor($input->getMaxDurability() / 4));
|
||||
@ -65,7 +59,11 @@ class MaterialRepairRecipe implements AnvilRecipe{
|
||||
// TODO: remove the material
|
||||
$damage -= $quarter * $numberRepair;
|
||||
}
|
||||
return $this->getResult()->setDamage(max(0, $damage));
|
||||
return new AnvilCraftResult(
|
||||
$numberRepair,
|
||||
(clone $input)->setDamage(max(0, $damage)),
|
||||
$material->pop($numberRepair)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ class AnvilTransaction extends InventoryTransaction{
|
||||
if($calculAttempt === null){
|
||||
return null;
|
||||
}
|
||||
$result = $calculAttempt->getResult();
|
||||
$result = $calculAttempt->getOutput();
|
||||
if(!$result->equalsExact($expectedOutput)){
|
||||
return null;
|
||||
}
|
||||
@ -119,7 +119,7 @@ class AnvilTransaction extends InventoryTransaction{
|
||||
parent::execute();
|
||||
|
||||
if($this->source->hasFiniteResources()){
|
||||
$this->source->getXpManager()->subtractXpLevels($this->expectedResult->getRepairCost());
|
||||
$this->source->getXpManager()->subtractXpLevels($this->expectedResult->getXpCost());
|
||||
}
|
||||
|
||||
$inventory = $this->source->getCurrentWindow();
|
||||
@ -148,9 +148,7 @@ class AnvilTransaction extends InventoryTransaction{
|
||||
throw new AssumptionFailedError("Expected that baseItem are not null before executing the event");
|
||||
}
|
||||
|
||||
$ev = new PlayerUseAnvilEvent($this->source, $this->baseItem, $this->materialItem, $this->expectedResult->getResult() ?? throw new \AssertionError(
|
||||
"Expected that the expected result is not null"
|
||||
), $this->customName, $this->expectedResult->getXpCost());
|
||||
$ev = new PlayerUseAnvilEvent($this->source, $this->baseItem, $this->materialItem, $this->expectedResult->getOutput(), $this->customName, $this->expectedResult->getXpCost());
|
||||
$ev->call();
|
||||
return !$ev->isCancelled();
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use pocketmine\utils\LegacyEnumShimTrait;
|
||||
* @method static ToolTier STONE()
|
||||
* @method static ToolTier WOOD()
|
||||
*
|
||||
* @phpstan-type TMetadata array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int[]}
|
||||
* @phpstan-type TMetadata array{0: int, 1: int, 2: int, 3: int, 4: int}
|
||||
*/
|
||||
enum ToolTier{
|
||||
use LegacyEnumShimTrait;
|
||||
|
@ -358,7 +358,7 @@ class ItemStackRequestExecutor{
|
||||
$result = AnvilHelper::calculateResult($this->player, $window->getInput(), $window->getMaterial(), $this->request->getFilterStrings()[0] ?? null);
|
||||
if($result !== null){
|
||||
$this->specialTransaction = new AnvilTransaction($this->player, $result, $this->request->getFilterStrings()[0] ?? null);
|
||||
$this->setNextCreatedItem($result->getResult());
|
||||
$this->setNextCreatedItem($result->getOutput());
|
||||
}
|
||||
}
|
||||
}elseif($action instanceof CraftingConsumeInputStackRequestAction){
|
||||
|
Loading…
x
Reference in New Issue
Block a user