I know there are other tutorials on this, but I've seen some people struggling with this on the forums (myself included, for a while) and thought I'd chip in my 2 cents. Hope it helps!
Be sure to check the spoiler at the end for a more elegant solution! I'll try to update this tutorial soon.
First off, in your custom Container class you define your slots:
public static final int INPUT_1 = 0, INPUT_2 = 1, FUEL = 2, OUTPUT = 3;
Use as many or few slots as you need, but keep the slots in numerical order and grouped according to function. Be sure you start at zero. This step isn't really necessary, but it will make it easier to read and help keep the transferItemInSlot method comprehensible.
Second, add your custom slots and the player's inventory slots to your Container's constructor.
Note that the player's inventory and action bar don't need a specified index when adding to your Container's inventory; addSlotToContainer will append the new slot to the next index automatically.
// CUSTOM SLOTS
this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, INPUT_1, 20, 17));
this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, INPUT_2, 56, 17));
this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, FUEL, 56, 53));
this.addSlotToContainer(new SlotArcaneInfuser(inventoryPlayer.player, par2TileEntityArcaneInfuser, OUTPUT, 116, 35));
int i;
// PLAYER'S INVENTORY (3*9 = 27 slots added here with index starting at OUTPUT+1 and ending at OUTPUT+27)
for (i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
// ACTION BAR (9 more slots added here, index starts at OUTPUT+27+1 and ends at OUTPUT+27+1+9)
for (i = 0; i < 9; ++i) {
this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142));
}
To summarize slot indices:
0-3 = custom slots (4 total slots)
4-30 = player inventory (27 total slots)
31-39 = action bar (9 total slots)
So our slot index must always be less than 40, or rather OUTPUT+27+9+1 (OUTPUT+37)
Note that you could switch the order in which the action bar and inventory are added, if you really want to.
Finally, override the transferStackInSlot method.
Here's a working example from a double-input custom furnace, with comments:
/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
*/
public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
{
ItemStack itemstack = null;
Slot slot = (Slot)this.inventorySlots.get(par2);
if (slot != null && slot.getHasStack())
{
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
// If itemstack is in Output stack
if (par2 == OUTPUT)
{
// try to place in player inventory / action bar; add 36+1 because mergeItemStack uses < index,
// so the last slot in the inventory won't get checked if you don't add 1
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, true))
{
return null;
}
slot.onSlotChange(itemstack1, itemstack);
}
// itemstack is in player inventory, try to place in appropriate furnace slot
else if (par2 != FUEL && par2 != INPUT_1 && par2 != INPUT_2)
{
// if it can be smelted, place in the input slots
if (ArcaneInfuserRecipes.infusing().getInfusingResult(itemstack1) != null)
{
// try to place in either Input slot; add 1 to final input slot because mergeItemStack uses < index
if (!this.mergeItemStack(itemstack1, INPUT_1, INPUT_2+1, false))
{
return null;
}
}
// if it's an energy source, place in Fuel slot
else if (TileEntityArcaneInfuser.isItemFuel(itemstack1))
{
if (!this.mergeItemStack(itemstack1, FUEL, FUEL+1, false))
{
return null;
}
}
// item in player's inventory, but not in action bar
else if (par2 >= OUTPUT+1 && par2 < OUTPUT+28)
{
// place in action bar
if (!this.mergeItemStack(itemstack1, OUTPUT+28, OUTPUT+37, false))
{
return null;
}
}
// item in action bar - place in player inventory
else if (par2 >= OUTPUT+28 && par2 < OUTPUT+37 && !this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+28, false))
{
return null;
}
}
// In one of the infuser slots; try to place in player inventory / action bar
else if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+37, false))
{
return null;
}
if (itemstack1.stackSize == 0)
{
slot.putStack((ItemStack)null);
}
else
{
slot.onSlotChanged();
}
if (itemstack1.stackSize == itemstack.stackSize)
{
return null;
}
slot.onPickupFromSlot(par1EntityPlayer, itemstack1);
}
return itemstack;
}
}
A final note: Be sure that your affiliated custom TileEntity has the appropriate sized ItemStack[] to match the number of slots in your Container, or you WILL crash when you activate your block.
UPDATE:
While helping some guys out on a mod, I came up with an even snazzier way of auto-adjusting all the values so you don't need to worry so much about what slots index is what and crashing your game. Check this out:
public class ContainerEye extends Container
{
public IInventory inventory;
private final EntityPlayer player;
// For this particular case, there are only 2 slots in the custom inventory, plus a slot that is 'active'
// but not able to interact with (like an active spell slot that doesn't really contain an item)
static final int ACTIVE_SLOT = 2;
// Note how these all back-reference themselves, so all you need to do is change the initial value and the
// rest are automatically adjusted! Just swap ACTIVE_SLOT with your inventory index like the above tut
private static final int ARMOR_START = ACTIVE_SLOT+1, ARMOR_END = ARMOR_START+3, INV_START = ARMOR_END+1, INV_END = INV_START+26, HOTBAR_START = INV_END+1, HOTBAR_END = HOTBAR_START+8;
public ContainerEye(EntityPlayer parPlayer, InventoryPlayer inventoryPlayer, InventoryEye inventoryEye)
{
this.inventory = inventoryEye;
this.player = parPlayer;
int i;
// CUSTOM INVENTORY SLOTS
this.addSlotToContainer(new SlotEye(inventory, 0, 80, 8));
this.addSlotToContainer(new SlotEye(inventory, 1, 80, 26));
this.addSlotToContainer(new SlotEyeActive(inventory, ACTIVE_SLOT, 116, 26));
// ARMOR SLOTS (note I had to make my own custom SlotArmor, as vanilla version is not public)
for (i = 0; i < 4; ++i)
{
this.addSlotToContainer(new SlotArmor(this.player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 8, 8 + i * 18, i));
}
// PLAYER INVENTORY SLOTS
for (i = 0; i < 3; ++i)
{
for (int j = 0; j < 9; ++j)
{
this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
// PLAYER ACTION BAR SLOTS
for (i = 0; i < 9; ++i)
{
this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142));
}
}
@Override
public boolean canInteractWith(EntityPlayer entityplayer)
{
return true;
}
/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
*/
public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
{
ItemStack itemstack = null;
Slot slot = (Slot)this.inventorySlots.get(par2);
if (slot != null && slot.getHasStack())
{
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
// Either armor or sharingan eye
if (par2 < ARMOR_END + 1 && par2 != ACTIVE_SLOT)
{
// try to place in player inventory / action bar
if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true))
{
return null;
}
slot.onSlotChange(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place either in eye or armor slots
else
{
// if item is a sharingan eye
if (itemstack1.getItem() instanceof ItemScroll)
{
if (!this.mergeItemStack(itemstack1, 0, ACTIVE_SLOT, false))
{
return null;
}
}
// if item is armor
else if (itemstack1.getItem() instanceof ItemArmor) {
int type = ((ItemArmor) itemstack1.getItem()).armorType;
if (!this.mergeItemStack(itemstack1, ARMOR_START + type, ARMOR_START + type + 1, false))
{
return null;
}
}
// item in player's inventory, but not in action bar
else if (par2 >= INV_START && par2 < HOTBAR_START)
{
// place in action bar
if (!this.mergeItemStack(itemstack1, HOTBAR_START, HOTBAR_START + 1, false))
{
return null;
}
}
// item in action bar - place in player inventory
else if (par2 >= HOTBAR_START && par2 < HOTBAR_END + 1)
{
if (!this.mergeItemStack(itemstack1, INV_START, INV_END + 1, false))
{
return null;
}
}
}
if (itemstack1.stackSize == 0)
{
slot.putStack((ItemStack)null);
}
else
{
slot.onSlotChanged();
}
if (itemstack1.stackSize == itemstack.stackSize)
{
return null;
}
slot.onPickupFromSlot(par1EntityPlayer, itemstack1);
}
return itemstack;
}
}
Be sure to check out my other tutorials - they are all on github here or follow the forum links below:
@MinecraftPlaye - Looks like you found yourself in an infinite loop, and I suspect it's because of the way you added the slots. You add the lower chest, upper chest, and the the player's hot bar slots, but you give the player's hot bar slots the upper chest inventory rather than the player's inventory (unless it is a player's inventory, but I can't tell from here).
Anyway, I would carefully compare your code to the vanilla double-chest, if that's what you're going for, or the single-chest, if that is.
Sorry to bump and old post. I am trying to do a similar thing but with a crafting table in 1.8 but running into problems. In my case it is a 1x5 input with a single result. There are three problems.
1. whenever I shift-click in the recipe result box, it goes into what appears to be an infinite loop or crashes (because of the loop?). I can shift-click out of the inputs and the all around in the inventory and the hotbar/action bar.
2. If I have a stack of items (qty >1) in the input slots, and just left click to pull out the recipe result item, the stacks all decrement to zero, meaning the items still show in the slots, but with a red zero (vs just decrementing by one). The excess stack quantity is returned to the player inventory.
3. If there is no stack (qty =1), i.e. just single items, I can take the recipe result item out, but it does not disappear, nor do the items in the input slots so I can take infinite number of them.
I was hoping someone has seen similar behavior in their attempts. Below is my container with the transferStackInSlot method. As you can see it is very similar to vanilla crafting table, and the above approach. I would very much appreciate any input you might have. Thanks in advance.
/** The crafting matrix inventory (1x5). */
public InventoryCrafting craftMatrix =new InventoryCrafting(this,1,5);
public IInventory craftResult = new InventoryCraftResult();
private final World worldObj;
private BlockPos pos;
public int posX = 0;
public int posY = 0;
public int posZ = 0;
public static final int
INPUT_1 = 0,
INPUT_2 = 1,
INPUT_3 = 2,
INPUT_4 = 3,
INPUT_5 = 4,
OUTPUT = 5;
public ContainerPot(InventoryPlayer invPlayer, World parWorld, BlockPos parPos) {
//** Player Inventory
for (int i = 0; i < 3; i++) {
for(int k = 0; k < 9; k++) {
this.addSlotToContainer(new Slot(invPlayer, k + i * 9 + 9, 8 + k * 18, 102 + i * 18));
}
}
//** Hotbar
for (int i = 0; i < 9; i++) {
this.addSlotToContainer(new Slot(invPlayer, i, 8 + i * 18, 160));
}
this.onCraftMatrixChanged(this.craftMatrix);
}
@Override
public void onCraftMatrixChanged(IInventory parInventory)
{
// DEBUG
System.out.println("Something changed in the Matrix! : " );
@Override
public void onContainerClosed(EntityPlayer parPlayer)
{
super.onContainerClosed(parPlayer);
if(!this.worldObj.isRemote)
{
for (int i = 0; i < 5; ++i) // slots 0-4 craftMatrix
{
ItemStack itemStack = this.craftMatrix.getStackInSlotOnClosing(i);
if(itemStack != null)
{
parPlayer.dropPlayerItemWithRandomChoice(itemStack, false);
}
}
}
}
/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
*/
// Shift Clicking out of slots
public ItemStack transferStackInSlot(EntityPlayer playerIn, int invIndex)
{
ItemStack itemstack = null;
Slot slot = (Slot)this.inventorySlots.get(invIndex);
// If there is something in the stack to pick up
if (slot != null && slot.getHasStack())
{
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
// Results Slot Shifting to player inventory or hotbar
if (invIndex == OUTPUT)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, true))
{
return null;
}
slot.onSlotChange(itemstack1, itemstack);
//debug
System.out.println("End of Results Block : " + invIndex);
}
// Player Inventory shifting to Hotbar
else if (invIndex >= OUTPUT+1 && invIndex < OUTPUT+27)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+27, OUTPUT+36+1, false))
{
return null;
}
//debug
System.out.println("End of Player Inventory : " + invIndex);
}
//Hot bar shifting in to player inventory
else if (invIndex >= OUTPUT+27 && invIndex < OUTPUT+36)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+27+1, false))
{
return null;
}
//debug
System.out.println("End of HotBar : " + invIndex);
}
//CraftMatrix shifting into player inventory or hotbar
else if (invIndex >= INPUT_1 && invIndex <= INPUT_5)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, false))
{
return null;
}
System.out.println("End of CraftMatrix : " + invIndex);
}
// Not sure why I need this other than to catch-all shift into player inventory somewhere
else if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, false))
{
return null;
}
//this seems to be true after any slot is emptied
if (itemstack1.stackSize == 0)
{
slot.putStack((ItemStack)null); // once stack is empty, set to null to blank grid?
System.out.println("Nulled Stack!");
}
else
{
slot.onSlotChanged(); //marks the slot dirty??
}
// This doesn't seem to run at all
if (itemstack1.stackSize == itemstack.stackSize)
{
System.out.println("Don't forget me!");
return null;
}
slot.onPickupFromSlot(playerIn, itemstack1);
}
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumBe sure to check the spoiler at the end for a more elegant solution! I'll try to update this tutorial soon.
First off, in your custom Container class you define your slots:
Use as many or few slots as you need, but keep the slots in numerical order and grouped according to function. Be sure you start at zero. This step isn't really necessary, but it will make it easier to read and help keep the transferItemInSlot method comprehensible.
Second, add your custom slots and the player's inventory slots to your Container's constructor.
Note that the player's inventory and action bar don't need a specified index when adding to your Container's inventory; addSlotToContainer will append the new slot to the next index automatically.
// CUSTOM SLOTS this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, INPUT_1, 20, 17)); this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, INPUT_2, 56, 17)); this.addSlotToContainer(new Slot(par2TileEntityArcaneInfuser, FUEL, 56, 53)); this.addSlotToContainer(new SlotArcaneInfuser(inventoryPlayer.player, par2TileEntityArcaneInfuser, OUTPUT, 116, 35)); int i; // PLAYER'S INVENTORY (3*9 = 27 slots added here with index starting at OUTPUT+1 and ending at OUTPUT+27) for (i = 0; i < 3; ++i) { for (int j = 0; j < 9; ++j) { this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); } } // ACTION BAR (9 more slots added here, index starts at OUTPUT+27+1 and ends at OUTPUT+27+1+9) for (i = 0; i < 9; ++i) { this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142)); }To summarize slot indices:
0-3 = custom slots (4 total slots)
4-30 = player inventory (27 total slots)
31-39 = action bar (9 total slots)
So our slot index must always be less than 40, or rather OUTPUT+27+9+1 (OUTPUT+37)
Note that you could switch the order in which the action bar and inventory are added, if you really want to.
Finally, override the transferStackInSlot method.
Here's a working example from a double-input custom furnace, with comments:
/** * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that. */ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) { ItemStack itemstack = null; Slot slot = (Slot)this.inventorySlots.get(par2); if (slot != null && slot.getHasStack()) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); // If itemstack is in Output stack if (par2 == OUTPUT) { // try to place in player inventory / action bar; add 36+1 because mergeItemStack uses < index, // so the last slot in the inventory won't get checked if you don't add 1 if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, true)) { return null; } slot.onSlotChange(itemstack1, itemstack); } // itemstack is in player inventory, try to place in appropriate furnace slot else if (par2 != FUEL && par2 != INPUT_1 && par2 != INPUT_2) { // if it can be smelted, place in the input slots if (ArcaneInfuserRecipes.infusing().getInfusingResult(itemstack1) != null) { // try to place in either Input slot; add 1 to final input slot because mergeItemStack uses < index if (!this.mergeItemStack(itemstack1, INPUT_1, INPUT_2+1, false)) { return null; } } // if it's an energy source, place in Fuel slot else if (TileEntityArcaneInfuser.isItemFuel(itemstack1)) { if (!this.mergeItemStack(itemstack1, FUEL, FUEL+1, false)) { return null; } } // item in player's inventory, but not in action bar else if (par2 >= OUTPUT+1 && par2 < OUTPUT+28) { // place in action bar if (!this.mergeItemStack(itemstack1, OUTPUT+28, OUTPUT+37, false)) { return null; } } // item in action bar - place in player inventory else if (par2 >= OUTPUT+28 && par2 < OUTPUT+37 && !this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+28, false)) { return null; } } // In one of the infuser slots; try to place in player inventory / action bar else if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+37, false)) { return null; } if (itemstack1.stackSize == 0) { slot.putStack((ItemStack)null); } else { slot.onSlotChanged(); } if (itemstack1.stackSize == itemstack.stackSize) { return null; } slot.onPickupFromSlot(par1EntityPlayer, itemstack1); } return itemstack; } }A final note: Be sure that your affiliated custom TileEntity has the appropriate sized ItemStack[] to match the number of slots in your Container, or you WILL crash when you activate your block.
UPDATE:
While helping some guys out on a mod, I came up with an even snazzier way of auto-adjusting all the values so you don't need to worry so much about what slots index is what and crashing your game. Check this out:
public class ContainerEye extends Container { public IInventory inventory; private final EntityPlayer player; // For this particular case, there are only 2 slots in the custom inventory, plus a slot that is 'active' // but not able to interact with (like an active spell slot that doesn't really contain an item) static final int ACTIVE_SLOT = 2; // Note how these all back-reference themselves, so all you need to do is change the initial value and the // rest are automatically adjusted! Just swap ACTIVE_SLOT with your inventory index like the above tut private static final int ARMOR_START = ACTIVE_SLOT+1, ARMOR_END = ARMOR_START+3, INV_START = ARMOR_END+1, INV_END = INV_START+26, HOTBAR_START = INV_END+1, HOTBAR_END = HOTBAR_START+8; public ContainerEye(EntityPlayer parPlayer, InventoryPlayer inventoryPlayer, InventoryEye inventoryEye) { this.inventory = inventoryEye; this.player = parPlayer; int i; // CUSTOM INVENTORY SLOTS this.addSlotToContainer(new SlotEye(inventory, 0, 80, 8)); this.addSlotToContainer(new SlotEye(inventory, 1, 80, 26)); this.addSlotToContainer(new SlotEyeActive(inventory, ACTIVE_SLOT, 116, 26)); // ARMOR SLOTS (note I had to make my own custom SlotArmor, as vanilla version is not public) for (i = 0; i < 4; ++i) { this.addSlotToContainer(new SlotArmor(this.player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 8, 8 + i * 18, i)); } // PLAYER INVENTORY SLOTS for (i = 0; i < 3; ++i) { for (int j = 0; j < 9; ++j) { this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18)); } } // PLAYER ACTION BAR SLOTS for (i = 0; i < 9; ++i) { this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142)); } } @Override public boolean canInteractWith(EntityPlayer entityplayer) { return true; } /** * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that. */ public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) { ItemStack itemstack = null; Slot slot = (Slot)this.inventorySlots.get(par2); if (slot != null && slot.getHasStack()) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); // Either armor or sharingan eye if (par2 < ARMOR_END + 1 && par2 != ACTIVE_SLOT) { // try to place in player inventory / action bar if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true)) { return null; } slot.onSlotChange(itemstack1, itemstack); } // Item is in inventory / hotbar, try to place either in eye or armor slots else { // if item is a sharingan eye if (itemstack1.getItem() instanceof ItemScroll) { if (!this.mergeItemStack(itemstack1, 0, ACTIVE_SLOT, false)) { return null; } } // if item is armor else if (itemstack1.getItem() instanceof ItemArmor) { int type = ((ItemArmor) itemstack1.getItem()).armorType; if (!this.mergeItemStack(itemstack1, ARMOR_START + type, ARMOR_START + type + 1, false)) { return null; } } // item in player's inventory, but not in action bar else if (par2 >= INV_START && par2 < HOTBAR_START) { // place in action bar if (!this.mergeItemStack(itemstack1, HOTBAR_START, HOTBAR_START + 1, false)) { return null; } } // item in action bar - place in player inventory else if (par2 >= HOTBAR_START && par2 < HOTBAR_END + 1) { if (!this.mergeItemStack(itemstack1, INV_START, INV_END + 1, false)) { return null; } } } if (itemstack1.stackSize == 0) { slot.putStack((ItemStack)null); } else { slot.onSlotChanged(); } if (itemstack1.stackSize == itemstack.stackSize) { return null; } slot.onPickupFromSlot(par1EntityPlayer, itemstack1); } return itemstack; } }Be sure to check out my other tutorials - they are all on github here or follow the forum links below:
- EventHandler and IExtendedEntityProperties: http://www.minecraft...e-explanations/
- Custom Inventories in Items and Players: http://www.minecraft...s-an-inventory/
- Rendering a custom item texture: http://www.minecraft...m-item-texture/
- Using potions in crafting recipes: http://www.minecraft...afting-recipes/
- Enchanted Book Crafting Recipes: http://www.minecraft...-tag-compounds/
- See Mazetar's List for the best Minecraft tutorials from around the web!
Lastly, don't forget to up the green arrow on any posts that help you!
-
View User Profile
-
View Posts
-
Send Message
Curse Premium-sorash67 || Skorpio
http://www.minecraftforum.net/topic/1839245-1615-forge-sspsmp-skorpios-notonlymoreores-mod-the-crossbow-update/
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumHa, so it is! My bad! How do I go about moving it?
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumJust click report on the OP and explain it should be moved to "Mapping and Modding Tutorials" section and the moderators will take care of it!
-sorash67 || Skorpio
http://www.minecraftforum.net/topic/1839245-1615-forge-sspsmp-skorpios-notonlymoreores-mod-the-crossbow-update/
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumDone and done. Thanks for pointing that out.
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumGlad i could help! Nice tutorial btw!
-sorash67 || Skorpio
http://www.minecraftforum.net/topic/1839245-1615-forge-sspsmp-skorpios-notonlymoreores-mod-the-crossbow-update/
lolz fixed it
It's great that you took time to share your findings and help out others!
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumGlad you like it! I just added an even better way of doing it at the end
-
View User Profile
-
View Posts
-
Send Message
Curse PremiumAnyway, I would carefully compare your code to the vanilla double-chest, if that's what you're going for, or the single-chest, if that is.
Sorry to bump and old post. I am trying to do a similar thing but with a crafting table in 1.8 but running into problems. In my case it is a 1x5 input with a single result. There are three problems.
1. whenever I shift-click in the recipe result box, it goes into what appears to be an infinite loop or crashes (because of the loop?). I can shift-click out of the inputs and the all around in the inventory and the hotbar/action bar.
2. If I have a stack of items (qty >1) in the input slots, and just left click to pull out the recipe result item, the stacks all decrement to zero, meaning the items still show in the slots, but with a red zero (vs just decrementing by one). The excess stack quantity is returned to the player inventory.
3. If there is no stack (qty =1), i.e. just single items, I can take the recipe result item out, but it does not disappear, nor do the items in the input slots so I can take infinite number of them.
I was hoping someone has seen similar behavior in their attempts. Below is my container with the transferStackInSlot method. As you can see it is very similar to vanilla crafting table, and the above approach. I would very much appreciate any input you might have. Thanks in advance.
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCraftResult;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.inventory.Slot;
import net.minecraft.inventory.SlotCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
public class ContainerPot extends Container {
/** The crafting matrix inventory (1x5). */
public InventoryCrafting craftMatrix =new InventoryCrafting(this,1,5);
public IInventory craftResult = new InventoryCraftResult();
private final World worldObj;
private BlockPos pos;
public int posX = 0;
public int posY = 0;
public int posZ = 0;
public static final int
INPUT_1 = 0,
INPUT_2 = 1,
INPUT_3 = 2,
INPUT_4 = 3,
INPUT_5 = 4,
OUTPUT = 5;
public ContainerPot(InventoryPlayer invPlayer, World parWorld, BlockPos parPos) {
this.worldObj = parWorld;
this.pos = parPos;
posX = pos.getX();
posY = pos.getY();
posZ = pos.getZ();
// CUSTOM SLOTS
this.addSlotToContainer(new Slot(craftMatrix, INPUT_1, 45, 5));
this.addSlotToContainer(new Slot(craftMatrix, INPUT_2, 45, 23));
this.addSlotToContainer(new Slot(craftMatrix, INPUT_3, 45, 41));
this.addSlotToContainer(new Slot(craftMatrix, INPUT_4, 45, 59));
this.addSlotToContainer(new Slot(craftMatrix, INPUT_5, 45, 77));
this.addSlotToContainer(new SlotCrafting(invPlayer.player, this.craftMatrix,this.craftResult, OUTPUT, 124, 40));
//** Player Inventory
for (int i = 0; i < 3; i++) {
for(int k = 0; k < 9; k++) {
this.addSlotToContainer(new Slot(invPlayer, k + i * 9 + 9, 8 + k * 18, 102 + i * 18));
}
}
//** Hotbar
for (int i = 0; i < 9; i++) {
this.addSlotToContainer(new Slot(invPlayer, i, 8 + i * 18, 160));
}
this.onCraftMatrixChanged(this.craftMatrix);
}
@Override
public void onCraftMatrixChanged(IInventory parInventory)
{
// DEBUG
System.out.println("Something changed in the Matrix! : " );
this.craftResult.setInventorySlotContents(0, PotCraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj));
}
@Override
public boolean canInteractWith(EntityPlayer player)
{
return this.worldObj.getBlockState(this.pos).getBlock() != Main.pot ? false : player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) <= 64.0D;
}
@Override
public void onContainerClosed(EntityPlayer parPlayer)
{
super.onContainerClosed(parPlayer);
if(!this.worldObj.isRemote)
{
for (int i = 0; i < 5; ++i) // slots 0-4 craftMatrix
{
ItemStack itemStack = this.craftMatrix.getStackInSlotOnClosing(i);
if(itemStack != null)
{
parPlayer.dropPlayerItemWithRandomChoice(itemStack, false);
}
}
}
}
/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
*/
// Shift Clicking out of slots
public ItemStack transferStackInSlot(EntityPlayer playerIn, int invIndex)
{
ItemStack itemstack = null;
Slot slot = (Slot)this.inventorySlots.get(invIndex);
// If there is something in the stack to pick up
if (slot != null && slot.getHasStack())
{
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
// Results Slot Shifting to player inventory or hotbar
if (invIndex == OUTPUT)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, true))
{
return null;
}
slot.onSlotChange(itemstack1, itemstack);
//debug
System.out.println("End of Results Block : " + invIndex);
}
// Player Inventory shifting to Hotbar
else if (invIndex >= OUTPUT+1 && invIndex < OUTPUT+27)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+27, OUTPUT+36+1, false))
{
return null;
}
//debug
System.out.println("End of Player Inventory : " + invIndex);
}
//Hot bar shifting in to player inventory
else if (invIndex >= OUTPUT+27 && invIndex < OUTPUT+36)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+27+1, false))
{
return null;
}
//debug
System.out.println("End of HotBar : " + invIndex);
}
//CraftMatrix shifting into player inventory or hotbar
else if (invIndex >= INPUT_1 && invIndex <= INPUT_5)
{
if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, false))
{
return null;
}
System.out.println("End of CraftMatrix : " + invIndex);
}
// Not sure why I need this other than to catch-all shift into player inventory somewhere
else if (!this.mergeItemStack(itemstack1, OUTPUT+1, OUTPUT+36+1, false))
{
return null;
}
//this seems to be true after any slot is emptied
if (itemstack1.stackSize == 0)
{
slot.putStack((ItemStack)null); // once stack is empty, set to null to blank grid?
System.out.println("Nulled Stack!");
}
else
{
slot.onSlotChanged(); //marks the slot dirty??
}
// This doesn't seem to run at all
if (itemstack1.stackSize == itemstack.stackSize)
{
System.out.println("Don't forget me!");
return null;
}
slot.onPickupFromSlot(playerIn, itemstack1);
}
return itemstack;
}
// @Override
// public boolean canMergeSlot(ItemStack parItemStack, Slot parSlot)
// {
// return !parSlot.inventory.equals(craftMatrix);
// }
@Override
public boolean canMergeSlot(ItemStack parItemStack, Slot parSlot)
{
return parSlot.inventory != this.craftResult && super.canMergeSlot(parItemStack, parSlot);
}
@Override
public Slot getSlot(int parSlotIndex)
{
if(parSlotIndex >= inventorySlots.size())
parSlotIndex = inventorySlots.size()-1;
return super.getSlot(parSlotIndex);
}
}