Everything posted by wookiederk
-
Get Rid of Vanilla Inventory [Unsolved]
How will I do that?
-
Inventory Not Saving Blocks [SOlVED]
I have a custom inventory that stores blocks and items during the game. However, when I save and quit and come back on, all of the blocks in the inventory were gone! Any help appreciated. public class EventCustomInventory implements IExtendedEntityProperties, IInventory { private ItemStack[] inv; public ItemStack[] armorInventory = new ItemStack[4]; /** The index of the currently held item (0-. */ public int currentItem = 0; @SideOnly(Side.CLIENT) /** The current ItemStack. */ private ItemStack currentItemStack; /** The player whose inventory this is. */ public EntityPlayer player; private ItemStack itemStack; public EventCustomInventory() { inv = new ItemStack[48]; } @Override public void saveNBTData(NBTTagCompound compound) { NBTTagList itemList = new NBTTagList(); for (int i = 0; i < inv.length; i++) { ItemStack stack = inv[i]; if (stack != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setByte("Slot", (byte) i); stack.writeToNBT(tag); itemList.appendTag(tag); } } compound.setTag("Inventory", itemList); } @Override public void loadNBTData(NBTTagCompound compound) { NBTTagList tagList = compound.getTagList("Inventory"); for (int i = 0; i < tagList.tagCount(); i++) { NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i); byte slot = tag.getByte("Slot"); if (slot >= 0 && slot < inv.length) { inv[slot] = ItemStack.loadItemStackFromNBT(tag); } } } @Override public void init(Entity entity, World world) { } /** * Set true whenever the inventory changes. Nothing sets it false so you * will have to write your own code to check it and reset the value. */ public boolean inventoryChanged = false; /** * Returns the item stack currently held by the player. */ public ItemStack getCurrentItem() { return this.currentItem < 9 && this.currentItem >= 0 ? this.inv[this.currentItem] : null; } /** * Get the size of the player hotbar inventory */ public static int getHotbarSize() { return 9; } /** * Returns a slot index in main inventory containing a specific itemID */ private int getInventorySlotContainItem(int par1) { for (int j = 0; j < this.inv.length; ++j) { if (this.inv[j] != null && this.inv[j].itemID == par1) { return j; } } return -1; } @SideOnly(Side.CLIENT) private int getInventorySlotContainItemAndDamage(int par1, int par2) { for (int k = 0; k < this.inv.length; ++k) { if (this.inv[k] != null && this.inv[k].itemID == par1 && this.inv[k].getItemDamage() == par2) { return k; } } return -1; } /** * stores an itemstack in the users inventory */ private int storeItemStack(ItemStack par1ItemStack) { for (int i = 0; i < this.inv.length; ++i) { if (this.inv[i] != null && this.inv[i].itemID == par1ItemStack.itemID && this.inv[i].isStackable() && this.inv[i].stackSize < this.inv[i].getMaxStackSize() && this.inv[i].stackSize < this.getInventoryStackLimit() && (!this.inv[i].getHasSubtypes() || this.inv[i] .getItemDamage() == par1ItemStack.getItemDamage()) && ItemStack.areItemStackTagsEqual(this.inv[i], par1ItemStack)) { return i; } } return -1; } /** * Returns the first item stack that is empty. */ public int getFirstEmptyStack() { for (int i = 0; i < this.inv.length; ++i) { if (this.inv[i] == null) { return i; } } return -1; } @SideOnly(Side.CLIENT) /** * Sets a specific itemID as the current item being held (only if it exists on the hotbar) */ public void setCurrentItem(int par1, int par2, boolean par3, boolean par4) { boolean flag2 = true; this.currentItemStack = this.getCurrentItem(); int k; if (par3) { k = this.getInventorySlotContainItemAndDamage(par1, par2); } else { k = this.getInventorySlotContainItem(par1); } if (k >= 0 && k < 9) { this.currentItem = k; } else { if (par4 && par1 > 0) { int l = this.getFirstEmptyStack(); if (l >= 0 && l < 9) { this.currentItem = l; } this.func_70439_a(Item.itemsList[par1], par2); } } } @SideOnly(Side.CLIENT) /** * Switch the current item to the next one or the previous one */ public void changeCurrentItem(int par1) { if (par1 > 0) { par1 = 1; } if (par1 < 0) { par1 = -1; } for (this.currentItem -= par1; this.currentItem < 0; this.currentItem += 9) { ; } while (this.currentItem >= 9) { this.currentItem -= 9; } } /** * Clear this player's inventory, using the specified ID and metadata as * filters or -1 for no filter. */ public int clearInventory(int par1, int par2) { int k = 0; int l; ItemStack itemstack; for (l = 0; l < this.inv.length; ++l) { itemstack = this.inv[l]; if (itemstack != null && (par1 <= -1 || itemstack.itemID == par1) && (par2 <= -1 || itemstack.getItemDamage() == par2)) { k += itemstack.stackSize; this.inv[l] = null; } } for (l = 0; l < this.armorInventory.length; ++l) { itemstack = this.armorInventory[l]; if (itemstack != null && (par1 <= -1 || itemstack.itemID == par1) && (par2 <= -1 || itemstack.getItemDamage() == par2)) { k += itemstack.stackSize; this.armorInventory[l] = null; } } return k; } @SideOnly(Side.CLIENT) public void func_70439_a(Item par1Item, int par2) { if (par1Item != null) { int j = this.getInventorySlotContainItemAndDamage(par1Item.itemID, par2); if (j >= 0) { this.inv[j] = this.inv[this.currentItem]; } if (this.currentItemStack != null && this.currentItemStack.isItemEnchantable() && this.getInventorySlotContainItemAndDamage( this.currentItemStack.itemID, this.currentItemStack.getItemDamageForDisplay()) == this.currentItem) { return; } this.inv[this.currentItem] = new ItemStack( Item.itemsList[par1Item.itemID], 1, par2); } } /** * This function stores as many items of an ItemStack as possible in a * matching slot and returns the quantity of left over items. */ private int storePartialItemStack(ItemStack par1ItemStack) { int i = par1ItemStack.itemID; int j = par1ItemStack.stackSize; int k; if (par1ItemStack.getMaxStackSize() == 1) { k = this.getFirstEmptyStack(); if (k < 0) { return j; } else { if (this.inv[k] == null) { this.inv[k] = ItemStack.copyItemStack(par1ItemStack); } return 0; } } else { k = this.storeItemStack(par1ItemStack); if (k < 0) { k = this.getFirstEmptyStack(); } if (k < 0) { return j; } else { if (this.inv[k] == null) { this.inv[k] = new ItemStack(i, 0, par1ItemStack.getItemDamage()); if (par1ItemStack.hasTagCompound()) { this.inv[k] .setTagCompound((NBTTagCompound) par1ItemStack .getTagCompound().copy()); } } int l = j; if (j > this.inv[k].getMaxStackSize() - this.inv[k].stackSize) { l = this.inv[k].getMaxStackSize() - this.inv[k].stackSize; } if (l > this.getInventoryStackLimit() - this.inv[k].stackSize) { l = this.getInventoryStackLimit() - this.inv[k].stackSize; } if (l == 0) { return j; } else { j -= l; this.inv[k].stackSize += l; this.inv[k].animationsToGo = 5; return j; } } } } /** * Decrement the number of animations remaining. Only called on client side. * This is used to handle the animation of receiving a block. */ public void decrementAnimations() { for (int i = 0; i < this.inv.length; ++i) { if (this.inv[i] != null) { this.inv[i].updateAnimation(this.player.worldObj, this.player, i, this.currentItem == i); } } for (int i = 0; i < this.armorInventory.length; i++) { if (this.armorInventory[i] != null) { this.armorInventory[i].getItem().onArmorTickUpdate( this.player.worldObj, this.player, this.armorInventory[i]); } } } /** * removed one item of specified itemID from inventory (if it is in a stack, * the stack size will reduce with 1) */ public boolean consumeInventoryItem(int par1) { int j = this.getInventorySlotContainItem(par1); if (j < 0) { return false; } else { if (--this.inv[j].stackSize <= 0) { this.inv[j] = null; } return true; } } /** * Get if a specifiied item id is inside the inventory. */ public boolean hasItem(int par1) { int j = this.getInventorySlotContainItem(par1); return j >= 0; } /** * Adds the item stack to the inventory, returns false if it is impossible. */ public boolean addItemStackToInventory(ItemStack par1ItemStack) { if (par1ItemStack == null) { return false; } else { try { int i; if (par1ItemStack.isItemDamaged()) { i = this.getFirstEmptyStack(); if (i >= 0) { this.inv[i] = ItemStack.copyItemStack(par1ItemStack); this.inv[i].animationsToGo = 5; par1ItemStack.stackSize = 0; return true; } else { return false; } } else { do { i = par1ItemStack.stackSize; par1ItemStack.stackSize = this .storePartialItemStack(par1ItemStack); } while (par1ItemStack.stackSize > 0 && par1ItemStack.stackSize < i); } return par1ItemStack.stackSize < i; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.makeCrashReport( throwable, "Adding item to inventory"); CrashReportCategory crashreportcategory = crashreport .makeCategory("Item being added"); crashreportcategory.addCrashSection("Item ID", Integer.valueOf(par1ItemStack.itemID)); crashreportcategory.addCrashSection("Item data", Integer.valueOf(par1ItemStack.getItemDamage())); throw new ReportedException(crashreport); } } } /** * Removes from an inventory slot (first arg) up to a specified number * (second arg) of items and returns them in a new stack. */ public ItemStack decrStackSize(int par1, int par2) { ItemStack[] aitemstack = this.inv; if (par1 >= this.inv.length) { aitemstack = this.armorInventory; par1 -= this.inv.length; } if (aitemstack[par1] != null) { ItemStack itemstack; if (aitemstack[par1].stackSize <= par2) { itemstack = aitemstack[par1]; aitemstack[par1] = null; return itemstack; } else { itemstack = aitemstack[par1].splitStack(par2); if (aitemstack[par1].stackSize == 0) { aitemstack[par1] = null; } return itemstack; } } else { return null; } } /** * When some containers are closed they call this on each slot, then drop * whatever it returns as an EntityItem - like when you close a workbench * GUI. */ public ItemStack getStackInSlotOnClosing(int par1) { ItemStack[] aitemstack = this.inv; if (par1 >= this.inv.length) { aitemstack = this.armorInventory; par1 -= this.inv.length; } if (aitemstack[par1] != null) { ItemStack itemstack = aitemstack[par1]; aitemstack[par1] = null; return itemstack; } else { return null; } } /** * Sets the given item stack to the specified slot in the inventory (can be * crafting or armor sections). */ public void setInventorySlotContents(int par1, ItemStack par2ItemStack) { ItemStack[] aitemstack = this.inv; if (par1 >= aitemstack.length) { par1 -= aitemstack.length; aitemstack = this.armorInventory; } aitemstack[par1] = par2ItemStack; } /** * Gets the strength of the current item (tool) against the specified block, * 1.0f if not holding anything. */ public float getStrVsBlock(Block par1Block) { float f = 1.0F; if (this.inv[this.currentItem] != null) { f *= this.inv[this.currentItem].getStrVsBlock(par1Block); } return f; } /** * Returns the number of slots in the inventory. */ public int getSizeInventory() { return this.inv.length; } /** * Returns the stack in slot i */ public ItemStack getStackInSlot(int par1) { ItemStack[] aitemstack = this.inv; if (par1 >= aitemstack.length) { par1 -= aitemstack.length; aitemstack = this.armorInventory; } return aitemstack[par1]; } /** * Returns the name of the inventory. */ public String getInvName() { return "CustomInventory"; } /** * If this returns false, the inventory name will be used as an unlocalized * name, and translated into the player's language. Otherwise it will be * used directly. */ public boolean isInvNameLocalized() { return false; } /** * Returns the maximum stack size for a inventory slot. Seems to always be * 64, possibly will be extended. *Isn't this more of a set than a get?* */ public int getInventoryStackLimit() { return 64; } /** * Return damage vs an entity done by the current held weapon, or 1 if * nothing is held */ public int getDamageVsEntity(Entity par1Entity) { ItemStack itemstack = this.getStackInSlot(this.currentItem); return itemstack != null ? itemstack.getDamageVsEntity(par1Entity) : 1; } /** * Returns whether the current item (tool) can harvest from the specified * block (actually get a result). */ public boolean canHarvestBlock(Block par1Block) { if (par1Block.blockMaterial.isToolNotRequired()) { return true; } else { ItemStack itemstack = this.getStackInSlot(this.currentItem); return itemstack != null ? itemstack.canHarvestBlock(par1Block) : false; } } /** * returns a player armor item (as itemstack) contained in specified armor * slot. */ public ItemStack armorItemInSlot(int par1) { return this.armorInventory[par1]; } /** * Based on the damage values and maximum damage values of each armor item, * returns the current armor value. */ public int getTotalArmorValue() { int i = 0; for (int j = 0; j < this.armorInventory.length; ++j) { if (this.armorInventory[j] != null && this.armorInventory[j].getItem() instanceof ItemArmor) { int k = ((ItemArmor) this.armorInventory[j].getItem()).damageReduceAmount; i += k; } } return i; } /** * Damages armor in each slot by the specified amount. */ public void damageArmor(int par1) { par1 /= 4; if (par1 < 1) { par1 = 1; } for (int j = 0; j < this.armorInventory.length; ++j) { if (this.armorInventory[j] != null && this.armorInventory[j].getItem() instanceof ItemArmor) { this.armorInventory[j].damageItem(par1, this.player); if (this.armorInventory[j].stackSize == 0) { this.armorInventory[j] = null; } } } } /** * Drop all armor and main inventory items. */ public void dropAllItems() { int i; for (i = 0; i < this.inv.length; ++i) { if (this.inv[i] != null) { this.player.dropPlayerItemWithRandomChoice(this.inv[i], true); this.inv[i] = null; } } for (i = 0; i < this.armorInventory.length; ++i) { if (this.armorInventory[i] != null) { this.player.dropPlayerItemWithRandomChoice( this.armorInventory[i], true); this.armorInventory[i] = null; } } } /** * Called when an the contents of an Inventory change, usually */ public void onInventoryChanged() { this.inventoryChanged = true; } public void setItemStack(ItemStack par1ItemStack) { this.itemStack = par1ItemStack; } public ItemStack getItemStack() { return this.itemStack; } /** * Do not make give this method the name canInteractWith because it clashes * with Container */ public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) { return this.player.isDead ? false : par1EntityPlayer .getDistanceSqToEntity(this.player) <= 64.0D; } /** * Returns true if the specified ItemStack exists in the inventory. */ public boolean hasItemStack(ItemStack par1ItemStack) { int i; for (i = 0; i < this.armorInventory.length; ++i) { if (this.armorInventory[i] != null && this.armorInventory[i].isItemEqual(par1ItemStack)) { return true; } } for (i = 0; i < this.inv.length; ++i) { if (this.inv[i] != null && this.inv[i].isItemEqual(par1ItemStack)) { return true; } } return false; } public void openChest() { } public void closeChest() { } /** * Returns true if automation is allowed to insert the given stack (ignoring * stack size) into the given slot. */ public boolean isStackValidForSlot(int par1, ItemStack par2ItemStack) { return true; } /** * Copy the ItemStack contents from another InventoryPlayer instance */ public void copyInventory(EventCustomInventory par1InventoryPlayer) { int i; for (i = 0; i < this.inv.length; ++i) { this.inv[i] = ItemStack.copyItemStack(par1InventoryPlayer.inv[i]); } for (i = 0; i < this.armorInventory.length; ++i) { this.armorInventory[i] = ItemStack .copyItemStack(par1InventoryPlayer.armorInventory[i]); } this.currentItem = par1InventoryPlayer.currentItem; } } Edit: Found the Solution. The NBT tag names should be changed so they arent those of the vanilla inventory.
-
Get Rid of Vanilla Inventory [Unsolved]
Any way to make sure it does not render. Maybe the keybind could return null or something, i dont know how.
-
Get Rid of Vanilla Inventory [Unsolved]
Hey, how do you get rid of the player inventory? Basically is there a way to not render the player inventory gui when its called? Any Help appreciated.
-
Change player slot amount [Solved]
Hey, I'm trying to add more slots to the Player Inventory, but I don't know how to increase the amount of slots. Thanks for any help. Edit: Figured it out on my own.
-
Open Gui From Key Input Help [Solved]
That works, but the vanilla inventory overrides my custom one. How can you prevent the vanilla inventory gui from opening?
-
Slot Background (Icon) Not Working (Solved)
Thanks that worked!
-
Open Gui From Key Input Help [Solved]
Typing in chat
-
Slot Background (Icon) Not Working (Solved)
I thought it was icons, not Items or Blocks... Or if it is I have no idea what you mean to do.
-
Open Gui From Key Input Help [Solved]
Ok that prevents it from reopening while open... But It still opens while typing ;P
-
Slot Background (Icon) Not Working (Solved)
Disregard my last post. It just Says that, but it doesn't. But there are no logs and the icon isn't rendering! Help!
-
Slot Background (Icon) Not Working (Solved)
Nothing out of the ordinary, but this was definitely interesting: /** * Returns the icon index on items.png that is used as background image of the slot. */ It returns the icon index! (which I thought was outdated) That being said, how would I use it to properly load an Icon?
-
Slot Background (Icon) Not Working (Solved)
No crashes
-
Slot Background (Icon) Not Working (Solved)
public Icon getBackgroundIconIndex() { return armorIcon; } must return an Icon, so You cant just bind it directly....Any ideas of why the icon remains transparent?
-
Slot Background (Icon) Not Working (Solved)
Its transparent...So its not registering anything. And its not an item! Its just an icon for a slot.
-
Slot Background (Icon) Not Working (Solved)
I'm Trying to get an Icon to register for my custom slot. Heres My Code (simplified it below): Icon armorIcon; @SideOnly(Side.CLIENT) public void registerIcons(IconRegister par1IconRegister) { armorIcon = par1IconRegister.registerIcon("textures/items/slot_empty_boots.png"); } @SideOnly(Side.CLIENT) /** * Returns the icon index on items.png that is used as background image of the slot. */ public Icon getBackgroundIconIndex() { return armorIcon; } It turns out blank. Any help appreciated
-
Open Gui From Key Input Help [Solved]
All fixed Last few Questions, though..... Would this be ok for the keyHandler? static KeyBinding inventoryBinding = Minecraft.getMinecraft().gameSettings.keyBindInventory; public ExcelteorKeyHandler() { super(new KeyBinding[] { inventoryBinding }, new boolean[] { false }); } And Second: If I press the same key while in the screen, it will open again. If I press the key while in another gui, it will open the inventory. So, how would I check if the current screen is null?
-
Open Gui From Key Input Help [Solved]
Made some adjustments. 1. Instanceof code: @ForgeSubscribe public void EntityEvent(EntityConstructing event) { if (event.entity instanceof EntityPlayer) { EntityPlayer player = Minecraft.getMinecraft().thePlayer; player.registerExtendedProperties("main.custominventory", new EventCustomInventory()); } } 2. Packet Handler Part: private void openGui(Packet250CustomPayload packet) { EntityPlayer player = Minecraft.getMinecraft().thePlayer; World world = Minecraft.getMinecraft().theWorld; player.openGui(Main.instance, 0, world, 0, 0, 0); } 3. Key Handler Part: @Override public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat) { if (tickEnd) { Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "Excelteor"; PacketDispatcher.sendPacketToServer(packet); } } Thanks for all the help so far! After this, it somewhat works. Unless i open the actual inventory gui first, my custom one crashes. I think it is because the world is null. How would I fix that? In Addition: If I wanted to assign the "key down" to "Minecraft.gameSettings.keyBindInventory" how would I go about doing that? (Did not work when i replaced it with the KeyBoard key)
-
Open Gui From Key Input Help [Solved]
Almost there Is this any better for the first?: @ForgeSubscribe public void EntityEvent(EntityConstructing event) { if (event instanceof EntityEvent) { EntityPlayer player = (EntityPlayer) event.entity; player.registerExtendedProperties("main.custominventory", new EventCustomInventory()); } } Second, I Left the openGui part empty because I do not know what to put in, so I'l need some further help there: Lastly, for the third I now have this: @Override public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat) { Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "Excelteor"; PacketDispatcher.sendPacketToServer(packet); } Thanks in advance for the help
-
Open Gui From Key Input Help [Solved]
I can tell you that I've read java tutorials before. I can read them as many times as I want, but they will mean nothing to me unless I actually get the experience up front. Some people learn from experience rather than reading a book. Most can only learn from example...Anyway, I really have no idea what to do for that and a few other things. Again, I have no idea how to do check the instance (all of the following is competely off): @ForgeSubscribe public void EntityEvent(EntityConstructing event) { EntityPlayer player = (EntityPlayer) event.entity; if (event instanceof player) { player.registerExtendedProperties("main.custominventory", new EventCustomInventory()); } } Second, the actual open Gui Code after receiving the packet: @Override public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { if (packet.channel.equals("Excelteor")) { openGui(packet); } } private void openGui(Packet250CustomPayload packet) { } Lastly (and this should do it), writing the packet to send: @Override public void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat) { ByteArrayOutputStream bos = new ByteArrayOutputStream(; DataOutputStream outputStream = new DataOutputStream(bos); Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "Excelteor"; packet.data = bos.toByteArray(); packet.length = bos.size(); Side side = FMLCommonHandler.instance().getEffectiveSide(); if (side == Side.SERVER) { // We are on the server side. EntityPlayerMP player = (EntityPlayerMP) playerEntity; } else if (side == Side.CLIENT) { // We are on the client side. EntityClientPlayerMP player = (EntityClientPlayerMP) playerEntity; player.sendQueue.addToSendQueue(packet); } else { } } Any help greatly appreciated
-
Open Gui From Key Input Help [Solved]
I'l try to work on the packet system in a bit. But, I have updated my code to whats needed. Currently in my GuiHandler, I have That should be correct. Now, I'm having trouble with checking the entity is a player. Under my @Init I have my register lines (should be correct) NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler()); KeyBindingRegistry.registerKeyBinding(new ExcelteorKeyHandler()); MinecraftForge.EVENT_BUS.register(this); Outside of that method, I have @ForgeSubscribe public void EntityEvent(EntityConstructing event) { //EntityPlayer player = (EntityPlayer) player.isCreatureType(EnumCreatureType.creature, true); // if (event.entity == player) { // player.registerExtendedProperties("main.custominventory", new EventCustomInventory()); //} //} I tried playing around with it for a while, but could not find a working solution. How would I properly check if the entity is a player? (I know that the player.registerExtendedProperties must be EntityPlayer player)
-
Open Gui From Key Input Help [Solved]
Ok I've changed the Inventory Event Class. I've added this code to my main File: MinecraftForge.EVENT_BUS.register(new EventCustomInventory()); Now, I have updated my previous misnamed class into implementing IInventory and updating the code: Now, I have some trouble actually making it open. Under my main class, I have the code @ForgeSubscribe public void EntityEvent(EntityConstructing event, EntityPlayer player) { if (event.entity == player) { event.entity.registerExtendedProperties("main.custominventory", new EventCustomInventory()); ("idk what to put here!")player.getExtendedProperties("main.custominventory"); } } I am not sure if that is correct at all, most likely far off from what it should be. It is just me trying to do my best. I am still confused what to do for (YourDataClass)player.getExtendedProperties(Your_Identifier) Also, how would i incorporate the actual gui render class (GuiExcelteorInventory) and open it (packets T_T) ?
-
Open Gui From Key Input Help [Solved]
This is my current IIventory.class file: But I am confused about and Also, this particular code (YourDataClass)player.getExtendedProperties(Your_Identifier) would go under the keyDown event, right?
-
Open Gui From Key Input Help [Solved]
I would like to stay away from TileEntities and use the Entity data attached to players. See my post above, idk how to do it and need help
-
Open Gui From Key Input Help [Solved]
I've tried experimenting a bit myself but I have no idea what to do. What is IEntityAdditionalProperties....(I couldn't find it so maybe it is IExtendedEntityProperties)? How would I use it to render the inventory screen?
IPS spam blocked by CleanTalk.