package com.thebrokenrail.sorcerycraft.gui; import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.spell.api.Spell; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry; import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.BasicInventory; import net.minecraft.inventory.CraftingResultInventory; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandlerContext; import net.minecraft.screen.ScreenHandlerType; import net.minecraft.screen.slot.Slot; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; public class CastingTableScreenHandler extends ScreenHandler { private final Inventory inventory; private final Inventory result; private final Spell[] spells; private final ScreenHandlerContext context; private int index = 0; public CastingTableScreenHandler(int syncId, PlayerInventory playerInventory, ScreenHandlerContext blockContext) { super(ScreenHandlerType.STONECUTTER, syncId); inventory = new BasicInventory(2) { public void markDirty() { super.markDirty(); CastingTableScreenHandler.this.onContentChanged(this); } }; context = blockContext; result = new CraftingResultInventory(); if (playerInventory.player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) { SpellPlayerEntity spellPlayer = (SpellPlayerEntity) playerInventory.player; Map spellsMap = spellPlayer.getDiscoveredSpells(); List spellsArray = new ArrayList<>(); Spell[] allSpells = SpellRegistry.getSpells(); for (Spell spell : allSpells) { if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) { spellsArray.add(spell); } } spells = spellsArray.toArray(new Spell[0]); } else { spells = SpellRegistry.getSpells(); } addSlot(new Slot(inventory, 0, 136, 37) { @Override public boolean canInsert(ItemStack stack) { return stack.getItem().equals(SorceryCraft.SPELL_ITEM); } @Override public int getMaxStackAmount() { return 1; } @Override public void onStackChanged(ItemStack originalItem, ItemStack itemStack) { super.onStackChanged(originalItem, itemStack); markDirty(); } }); addSlot(new Slot(inventory, 1, 162, 37) { @Override public void onStackChanged(ItemStack originalItem, ItemStack itemStack) { super.onStackChanged(originalItem, itemStack); markDirty(); } }); addSlot(new Slot(result, 2, 220, 37) { public boolean canInsert(ItemStack stack) { return false; } public boolean canTakeItems(PlayerEntity playerEntity) { return canTakeResult(playerEntity) && hasStack(); } public ItemStack onTakeItem(PlayerEntity player, ItemStack stack) { if (!player.isCreative()) { player.addExperienceLevels(-spells[index].getXPCost()); } context.run((world, blockPos) -> { SorceryCraft.playSpellSound(world, blockPos); if (!world.isClient()) { SorceryCraft.CREATE_SPELL_CRITERION.trigger((ServerPlayerEntity) player); } }); CastingTableScreenHandler.this.inventory.setInvStack(0, ItemStack.EMPTY); CastingTableScreenHandler.this.inventory.takeInvStack(1, spells[index].getItemCost().getCount()); return stack; } }); int k; for (k = 0; k < 3; ++k) { for (int j = 0; j < 9; ++j) { addSlot(new Slot(playerInventory, j + k * 9 + 9, 108 + j * 18, 84 + k * 18)); } } for (k = 0; k < 9; ++k) { addSlot(new Slot(playerInventory, k, 108 + k * 18, 142)); } } public boolean canTakeResult(PlayerEntity playerEntity) { return playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost(); } public void setIndex(int index) { this.index = index; onContentChanged(inventory); if (inventory.getInvStack(0).isEmpty() && inventory.getInvStack(1).isEmpty()) { ItemStack spellItem = new ItemStack(SorceryCraft.SPELL_ITEM); autoFill(0, spellItem, true); ItemStack paymentItem = getRecipes()[index].getItemCost(); autoFill(1, paymentItem, false); } } public ItemStack transferSlot(PlayerEntity player, int invSlot) { ItemStack itemStack = ItemStack.EMPTY; Slot slot = slots.get(invSlot); if (slot != null && slot.hasStack()) { ItemStack itemStack2 = slot.getStack(); itemStack = itemStack2.copy(); if (invSlot == 2) { if (!insertItem(itemStack2, 3, 39, true)) { return ItemStack.EMPTY; } slot.onStackChanged(itemStack2, itemStack); } else if (invSlot != 0 && invSlot != 1) { if (invSlot < 30) { if (!insertItem(itemStack2, 30, 39, false)) { return ItemStack.EMPTY; } } else if (invSlot < 39 && !insertItem(itemStack2, 3, 30, false)) { return ItemStack.EMPTY; } } else if (!insertItem(itemStack2, 3, 39, false)) { return ItemStack.EMPTY; } if (itemStack2.isEmpty()) { slot.setStack(ItemStack.EMPTY); } else { slot.markDirty(); } if (itemStack2.getCount() == itemStack.getCount()) { return ItemStack.EMPTY; } slot.onTakeItem(player, itemStack2); } return itemStack; } @Override public void close(PlayerEntity player) { super.close(player); context.run((BiConsumer) (world, blockPos) -> dropInventory(player, world, inventory)); } @Override public void onContentChanged(Inventory inventory) { super.onContentChanged(inventory); ItemStack item = inventory.getInvStack(0); ItemStack cost = inventory.getInvStack(1); if (inventory == this.inventory) { if (spells.length > 0 && !item.isEmpty() && cost.getItem() == spells[index].getItemCost().getItem() && cost.getCount() >= spells[index].getItemCost().getCount()) { ItemStack resultItem = item.copy(); Map resultSpells = SpellHelper.getSpells(resultItem); if (!resultSpells.containsKey(spells[index].getID()) || resultSpells.get(spells[index].getID()) <= spells[index].getLevel()) { resultSpells.put(spells[index].getID(), spells[index].getLevel()); } SpellHelper.setSpells(resultItem, resultSpells); result.setInvStack(2, resultItem); } else { result.setInvStack(2, ItemStack.EMPTY); } } } private void autoFill(int slot, ItemStack stack, boolean onlyOne) { if (!stack.isEmpty()) { for (int i = 3; i < 39; ++i) { ItemStack itemStack = slots.get(i).getStack(); if (!itemStack.isEmpty() && itemCompatible(stack, itemStack)) { ItemStack invSlot = inventory.getInvStack(slot); int count = invSlot.isEmpty() ? 0 : invSlot.getCount(); int requiredCount = Math.min((onlyOne ? 1 : stack.getMaxCount()) - count, itemStack.getCount()); ItemStack modifiedItem = itemStack.copy(); int totalCount = count + requiredCount; itemStack.decrement(requiredCount); modifiedItem.setCount(totalCount); inventory.setInvStack(slot, modifiedItem); if (totalCount >= stack.getMaxCount() || onlyOne) { break; } } } } } private boolean itemCompatible(ItemStack itemStack, ItemStack otherItemStack) { return itemStack.getItem() == otherItemStack.getItem(); } @Override public boolean canUse(PlayerEntity player) { return context.run((world, blockPos) -> world.getBlockState(blockPos).getBlock().equals(SorceryCraft.CASTING_TABLE_BLOCK) && player.squaredDistanceTo((double) blockPos.getX() + 0.5D, (double) blockPos.getY() + 0.5D, (double) blockPos.getZ() + 0.5D) <= 64.0D, true); } public Spell[] getRecipes() { return spells; } }