cn.nukkit.inventory.transaction.CraftingTransaction Maven / Gradle / Ivy
package cn.nukkit.inventory.transaction;
import cn.nukkit.Player;
import cn.nukkit.api.DeprecationDetails;
import cn.nukkit.api.PowerNukkitDifference;
import cn.nukkit.api.PowerNukkitOnly;
import cn.nukkit.api.Since;
import cn.nukkit.event.inventory.CraftItemEvent;
import cn.nukkit.inventory.*;
import cn.nukkit.inventory.transaction.action.DamageAnvilAction;
import cn.nukkit.inventory.transaction.action.InventoryAction;
import cn.nukkit.inventory.transaction.action.SlotChangeAction;
import cn.nukkit.inventory.transaction.action.TakeLevelAction;
import cn.nukkit.item.Item;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @author CreeperFace
*/
public class CraftingTransaction extends InventoryTransaction {
protected int gridSize;
protected List- inputs;
protected List
- secondaryOutputs;
protected Item primaryOutput;
@Deprecated
@DeprecationDetails(since = "FUTURE", reason = "When the recipe is not a CraftingRecipe, this is set to null instead of the recipe",
by = "PowerNukkit", replaceWith = "getTransactionRecipe()")
@Nullable
@Since("FUTURE")
protected CraftingRecipe recipe;
private Recipe transactionRecipe;
@PowerNukkitOnly
protected int craftingType;
private boolean readyToExecute;
public CraftingTransaction(Player source, List
actions) {
super(source, actions, false);
this.craftingType = source.craftingType;
if (source.craftingType == Player.CRAFTING_STONECUTTER) {
this.gridSize = 1;
this.inputs = new ArrayList<>(1);
this.secondaryOutputs = new ArrayList<>(1);
} else {
this.gridSize = (source.getCraftingGrid() instanceof BigCraftingGrid) ? 3 : 2;
this.inputs = new ArrayList<>();
this.secondaryOutputs = new ArrayList<>();
}
init(source, actions);
}
public void setInput(Item item) {
if (inputs.size() < gridSize * gridSize) {
for (Item existingInput : this.inputs) {
if (existingInput.equals(item, item.hasMeta(), item.hasCompoundTag())) {
existingInput.setCount(existingInput.getCount() + item.getCount());
return;
}
}
inputs.add(item.clone());
} else {
throw new RuntimeException("Input list is full can't add " + item);
}
}
public List- getInputList() {
return inputs;
}
public void setExtraOutput(Item item) {
if (secondaryOutputs.size() < gridSize * gridSize) {
secondaryOutputs.add(item.clone());
} else {
throw new RuntimeException("Output list is full can't add " + item);
}
}
public Item getPrimaryOutput() {
return primaryOutput;
}
public void setPrimaryOutput(Item item) {
if (primaryOutput == null) {
primaryOutput = item.clone();
} else if (!primaryOutput.equals(item)) {
throw new RuntimeException("Primary result item has already been set and does not match the current item (expected " + primaryOutput + ", got " + item + ")");
}
}
@Deprecated
@DeprecationDetails(since = "FUTURE", reason = "When the recipe is not a CraftingRecipe, returns null instead of the recipe",
by = "PowerNukkit", replaceWith = "getTransactionRecipe()")
@Since("FUTURE")
@Nullable
public CraftingRecipe getRecipe() {
return recipe;
}
@PowerNukkitOnly
@Since("FUTURE")
public Recipe getTransactionRecipe() {
return transactionRecipe;
}
@PowerNukkitOnly
@Since("FUTURE")
protected void setTransactionRecipe(Recipe recipe) {
this.transactionRecipe = recipe;
this.recipe = (recipe instanceof CraftingRecipe)? (CraftingRecipe) recipe: null;
}
@Override
public boolean canExecute() {
CraftingManager craftingManager = source.getServer().getCraftingManager();
Inventory inventory;
switch (craftingType) {
case Player.CRAFTING_STONECUTTER:
setTransactionRecipe(craftingManager.matchStonecutterRecipe(this.primaryOutput));
break;
case Player.CRAFTING_CARTOGRAPHY:
setTransactionRecipe(craftingManager.matchCartographyRecipe(inputs, this.primaryOutput, this.secondaryOutputs));
break;
case Player.CRAFTING_SMITHING:
inventory = source.getWindowById(Player.SMITHING_WINDOW_ID);
if (inventory instanceof SmithingInventory) {
addInventory(inventory);
SmithingInventory smithingInventory = (SmithingInventory) inventory;
SmithingRecipe smithingRecipe = smithingInventory.matchRecipe();
if (smithingRecipe != null && this.primaryOutput.equals(smithingRecipe.getFinalResult(smithingInventory.getEquipment()), true, true)) {
setTransactionRecipe(smithingRecipe);
}
}
break;
case Player.CRAFTING_ANVIL:
inventory = source.getWindowById(Player.ANVIL_WINDOW_ID);
if (inventory instanceof AnvilInventory) {
AnvilInventory anvil = (AnvilInventory) inventory;
addInventory(anvil);
if (this.primaryOutput.equalsIgnoringEnchantmentOrder(anvil.getResult(), true)) {
actions.removeIf(action -> action instanceof TakeLevelAction);
TakeLevelAction takeLevel = new TakeLevelAction(anvil.getLevelCost());
addAction(takeLevel);
if (takeLevel.isValid(source)) {
setTransactionRecipe(new RepairRecipe(InventoryType.ANVIL, this.primaryOutput, this.inputs));
PlayerUIInventory uiInventory = source.getUIInventory();
actions.add(new DamageAnvilAction(anvil, !source.isCreative() && ThreadLocalRandom.current().nextFloat() < 0.12F, this));
actions.stream()
.filter(a -> a instanceof SlotChangeAction)
.map(a -> (SlotChangeAction) a)
.filter(a -> a.getInventory() == uiInventory)
.filter(a -> a.getSlot() == 50)
.findFirst()
.ifPresent(a -> {
// Move the set result action to the end, otherwise the result would be cleared too early
actions.remove(a);
actions.add(a);
});
}
}
}
if (getTransactionRecipe() == null) {
source.sendExperienceLevel();
}
source.getUIInventory().setItem(AnvilInventory.RESULT, Item.get(0), false);
break;
case Player.CRAFTING_GRINDSTONE:
inventory = source.getWindowById(Player.GRINDSTONE_WINDOW_ID);
if (inventory instanceof GrindstoneInventory) {
GrindstoneInventory grindstone = (GrindstoneInventory) inventory;
addInventory(grindstone);
if (grindstone.updateResult(false) && this.primaryOutput.equals(grindstone.getResult(), true, true)) {
setTransactionRecipe(new RepairRecipe(InventoryType.GRINDSTONE, this.primaryOutput, this.inputs));
grindstone.setResult(Item.get(0), false);
}
}
break;
default:
setTransactionRecipe(craftingManager.matchRecipe(inputs, this.primaryOutput, this.secondaryOutputs));
break;
}
return this.getTransactionRecipe() != null && super.canExecute();
}
@Override
protected boolean callExecuteEvent() {
CraftItemEvent ev;
this.source.getServer().getPluginManager().callEvent(ev = new CraftItemEvent(this));
return !ev.isCancelled();
}
@Override
@PowerNukkitDifference(since = "1.4.0.0-PN", info = "No longer closes the inventory")
protected void sendInventories() {
super.sendInventories();
}
@Override
public boolean execute() {
if (super.execute()) {
switch (this.primaryOutput.getId()) {
case Item.CRAFTING_TABLE:
source.awardAchievement("buildWorkBench");
break;
case Item.WOODEN_PICKAXE:
source.awardAchievement("buildPickaxe");
break;
case Item.FURNACE:
source.awardAchievement("buildFurnace");
break;
case Item.WOODEN_HOE:
source.awardAchievement("buildHoe");
break;
case Item.BREAD:
source.awardAchievement("makeBread");
break;
case Item.CAKE:
source.awardAchievement("bakeCake");
break;
case Item.STONE_PICKAXE:
case Item.GOLDEN_PICKAXE:
case Item.IRON_PICKAXE:
case Item.DIAMOND_PICKAXE:
source.awardAchievement("buildBetterPickaxe");
break;
case Item.WOODEN_SWORD:
source.awardAchievement("buildSword");
break;
case Item.DIAMOND:
source.awardAchievement("diamond");
break;
}
return true;
}
return false;
}
@Since("1.3.0.0-PN")
public boolean checkForCraftingPart(List
actions) {
for (InventoryAction action : actions) {
if (action instanceof SlotChangeAction) {
SlotChangeAction slotChangeAction = (SlotChangeAction) action;
if (slotChangeAction.getInventory().getType() == InventoryType.UI && slotChangeAction.getSlot() == 50 &&
!slotChangeAction.getSourceItem().equals(slotChangeAction.getTargetItem())) {
return true;
}
}
}
return false;
}
@PowerNukkitOnly
@Since("1.4.0.0-PN")
public void setReadyToExecute(boolean readyToExecute) {
this.readyToExecute = readyToExecute;
}
@PowerNukkitOnly
@Since("1.4.0.0-PN")
public boolean isReadyToExecute() {
return readyToExecute;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy