GrindstoneContainerRe.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package com.hexdragon.enchrebirth.block;
  2. import com.hexdragon.enchrebirth.reg.Registry;
  3. import net.minecraft.block.Blocks;
  4. import net.minecraft.enchantment.Enchantment;
  5. import net.minecraft.enchantment.EnchantmentHelper;
  6. import net.minecraft.entity.player.PlayerEntity;
  7. import net.minecraft.entity.player.PlayerInventory;
  8. import net.minecraft.inventory.IInventory;
  9. import net.minecraft.inventory.Inventory;
  10. import net.minecraft.inventory.container.Container;
  11. import net.minecraft.inventory.container.RepairContainer;
  12. import net.minecraft.inventory.container.Slot;
  13. import net.minecraft.item.ItemStack;
  14. import net.minecraft.item.Items;
  15. import net.minecraft.util.IWorldPosCallable;
  16. import java.util.Map;
  17. import java.util.stream.Collectors;
  18. public class GrindstoneContainerRe extends Container {
  19. // 输入与输出物品槽
  20. private final IInventory inputInventory = new Inventory(1) {
  21. public void markDirty() {
  22. super.markDirty();
  23. GrindstoneContainerRe.this.onCraftMatrixChanged(this);
  24. }
  25. };
  26. private final IInventory outputInventory = new Inventory(2);
  27. // 构造页面槽位
  28. private void Constuct(int windowIdIn, PlayerInventory playerInventoryIn, final IWorldPosCallable worldPosCallableIn) {
  29. this.addSlot(new Slot(this.inputInventory, 0, 49, 19) {
  30. // 检查物品是否能输入:没有没拿走的输出,且接受输入
  31. public boolean isItemValid(ItemStack stack) {
  32. return !(inputInventory.isEmpty() && !outputInventory.isEmpty()) &&
  33. stack.getCount() == 1 && stack.isDamageable() && stack.isEnchanted();
  34. }
  35. });
  36. this.addSlot(new Slot(this.outputInventory, 0, 129, 34) {
  37. // 禁止将物品放在输出格
  38. public boolean isItemValid(ItemStack stack) {
  39. return false;
  40. }
  41. // 从输出格拿走物品时清空输入格
  42. public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) {
  43. GrindstoneContainerRe.this.inputInventory.setInventorySlotContents(0, ItemStack.EMPTY);
  44. return stack;
  45. }
  46. });
  47. this.addSlot(new Slot(this.outputInventory, 1, 129 + 18, 34) {
  48. // 禁止将物品放在输出格
  49. public boolean isItemValid(ItemStack stack) {
  50. return false;
  51. }
  52. // 从输出格拿走物品时清空输入格
  53. public ItemStack onTake(PlayerEntity thePlayer, ItemStack stack) {
  54. GrindstoneContainerRe.this.inputInventory.setInventorySlotContents(0, ItemStack.EMPTY);
  55. return stack;
  56. }
  57. });
  58. // 增加物品栏与快捷栏槽位
  59. int yPositionStart = 84;
  60. for (int i = 0; i < 3; ++i) {
  61. for (int j = 0; j < 9; ++j) {
  62. this.addSlot(new Slot(playerInventoryIn, j + i * 9 + 9, 8 + j * 18, yPositionStart + i * 18));
  63. }
  64. }
  65. for (int k = 0; k < 9; ++k) {
  66. this.addSlot(new Slot(playerInventoryIn, k, 8 + k * 18, 58 + yPositionStart));
  67. }
  68. }
  69. // 当输入物品改变时更新输出
  70. private void updateRecipeOutput() {
  71. // 获取输入
  72. ItemStack itemInput = this.inputInventory.getStackInSlot(0);
  73. ItemStack itemOutput1 = ItemStack.EMPTY;
  74. ItemStack itemOutput2 = ItemStack.EMPTY;
  75. // 判断输出
  76. if (inputInventory.isEmpty() && outputInventory.isEmpty()) {
  77. // 输入输出均为空:保持清空
  78. } else if (inputInventory.isEmpty() && !outputInventory.isEmpty()) {
  79. // 输入为空,输出不为空
  80. if (outputInventory.getStackInSlot(0).isEmpty() || outputInventory.getStackInSlot(1).isEmpty()) {
  81. // 刚拿走一个输出物品:输出保持不变
  82. itemOutput1 = outputInventory.getStackInSlot(0);
  83. itemOutput2 = outputInventory.getStackInSlot(1);
  84. } else {
  85. // 刚拿走输入物品:清空输出
  86. }
  87. } else {
  88. // 输入不为空,输出为空:更换了一个新的输入物品,更新输出
  89. // 输入不为空,输出为空:更新输出
  90. if (itemInput.getCount() == 1 && itemInput.isDamageable() && itemInput.isEnchanted()) {
  91. // 要求输入为 1 个可损坏的有附魔物品
  92. itemOutput1 = this.prepareNewItem(itemInput, itemInput.getDamage());
  93. itemOutput2 = new ItemStack(Items.LAPIS_LAZULI, 3);
  94. }
  95. }
  96. // 设置物品并提交更改
  97. this.outputInventory.setInventorySlotContents(0, itemOutput1);
  98. this.outputInventory.setInventorySlotContents(1, itemOutput2);
  99. this.detectAndSendChanges();
  100. }
  101. // 对砂轮的单个物品进行预处理:例如移除非诅咒附魔等
  102. private ItemStack prepareNewItem(ItemStack stack, int damage) {
  103. ItemStack itemstack = stack.copy();
  104. itemstack.removeChildTag("Enchantments");
  105. itemstack.removeChildTag("StoredEnchantments");
  106. if (damage > 0) {
  107. itemstack.setDamage(damage);
  108. } else {
  109. itemstack.removeChildTag("Damage");
  110. }
  111. itemstack.setCount(1);
  112. Map<Enchantment, Integer> map = EnchantmentHelper.getEnchantments(stack).entrySet().stream().filter((p_217012_0_) -> p_217012_0_.getKey().isCurse()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  113. EnchantmentHelper.setEnchantments(map, itemstack);
  114. itemstack.setRepairCost(0);
  115. for (int i = 0; i < map.size(); ++i) {
  116. itemstack.setRepairCost(RepairContainer.getNewRepairCost(itemstack.getRepairCost()));
  117. }
  118. return itemstack;
  119. }
  120. // 接口: 当页面关闭时触发,尝试返还物品
  121. public void onContainerClosed(PlayerEntity playerIn) {
  122. super.onContainerClosed(playerIn);
  123. // 如果输入为空则返还输出,如果输出为空则返还输入
  124. this.worldPosCallable.consume((p_217009_2_, p_217009_3_) -> this.clearContainer(playerIn, p_217009_2_,
  125. this.inputInventory.isEmpty() ? this.outputInventory : this.inputInventory));
  126. }
  127. /*
  128. * --------------------------------------------------------------
  129. * 以下方法直接使用原本的代码,不需要也未曾进行过修改
  130. * --------------------------------------------------------------
  131. */
  132. // 构造函数
  133. private final IWorldPosCallable worldPosCallable;
  134. public GrindstoneContainerRe(int windowIdIn, PlayerInventory playerInventoryIn) {
  135. this(windowIdIn, playerInventoryIn, IWorldPosCallable.DUMMY);
  136. }
  137. public GrindstoneContainerRe(int windowIdIn, PlayerInventory playerInventoryIn, final IWorldPosCallable worldPosCallableIn) {
  138. super(Registry.containerGrindstone.get(), windowIdIn);
  139. this.worldPosCallable = worldPosCallableIn;
  140. Constuct(windowIdIn, playerInventoryIn, worldPosCallableIn);
  141. }
  142. // 接口: 决定玩家是否可以使用该方块
  143. public boolean canInteractWith(PlayerEntity playerIn) {
  144. return isWithinUsableDistance(this.worldPosCallable, playerIn, Blocks.GRINDSTONE);
  145. }
  146. // 接口: 当输入物品改变时触发更新
  147. public void onCraftMatrixChanged(IInventory inventoryIn) {
  148. super.onCraftMatrixChanged(inventoryIn);
  149. if (inventoryIn == this.inputInventory) {
  150. this.updateRecipeOutput();
  151. }
  152. }
  153. // 接口: 当玩家使用 Shift+左键 快速转移物品时触发,需要尝试转移物品
  154. public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
  155. ItemStack itemstack = ItemStack.EMPTY;
  156. Slot slot = this.inventorySlots.get(index);
  157. if (slot != null && slot.getHasStack()) {
  158. ItemStack itemstack1 = slot.getStack();
  159. itemstack = itemstack1.copy();
  160. ItemStack itemstack2 = this.inputInventory.getStackInSlot(0);
  161. if (index == 2) {
  162. if (!this.mergeItemStack(itemstack1, 3, 39, true)) {
  163. return ItemStack.EMPTY;
  164. }
  165. slot.onSlotChange(itemstack1, itemstack);
  166. } else if (index != 0 && index != 1) {
  167. if (!this.mergeItemStack(itemstack1, 0, 2, false)) {
  168. return ItemStack.EMPTY;
  169. }
  170. } else if (!this.mergeItemStack(itemstack1, 3, 39, false)) {
  171. return ItemStack.EMPTY;
  172. }
  173. if (itemstack1.isEmpty()) {
  174. slot.putStack(ItemStack.EMPTY);
  175. } else {
  176. slot.onSlotChanged();
  177. }
  178. if (itemstack1.getCount() == itemstack.getCount()) {
  179. return ItemStack.EMPTY;
  180. }
  181. slot.onTake(playerIn, itemstack1);
  182. }
  183. return itemstack;
  184. }
  185. }