Jump to content

[1.12.2] Items don't drop when I break my custom chest [SOLVED]


Recommended Posts

Posted (edited)

Hello, I'm codding for only a week ago new, so I'm kind of nww for the moment :)

 

It's been 10 hours between yesterday and today that i don't succed to find out why I don't get the content of my custom chest (yes, I make my tests on blocks called FakeBlock first ^^) when I use BreakBlock.

 

Here is my block

Spoiler

package sunsigne.MyMod.blocks;

import java.util.Random;

import net.minecraft.block.BlockContainer;
import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.ItemStackHandler;
import sunsigne.MyMod.IHasModel;
import sunsigne.MyMod.MyMod;
import sunsigne.MyMod.Reference;
import sunsigne.MyMod.init.ModBlocks;
import sunsigne.MyMod.init.ModItems;
import sunsigne.MyMod.tileentity.FakeBlockTileEntity;

public class FakeBlock extends BlockContainer implements ITileEntityProvider, IHasModel
{
    public static final PropertyDirection FACING = BlockHorizontal.FACING;
    public static final int FAKE_BLOCK_GUI = 80;
    
    
    public FakeBlock(String name)
    {
    
        super(Material.ROCK);
        setUnlocalizedName(name);
        setRegistryName(name);
        setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
        
        setSoundType(SoundType.STONE);
        setHardness(3.5F);
        setResistance(17.5F);
        setHarvestLevel("pickaxe", 0);
        setLightLevel(0.0F);
        //setLightOpacity(1);
        //setBlockUnbreakable();
        
        ModBlocks.BLOCKS.add(this);
        ModItems.ITEMS.add(new ItemBlock(this).setRegistryName(this.getRegistryName()));
        this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
    }
    
    @Override
    public void registerModels()
    {
    
        MyMod.proxy.registerItemRenderer(Item.getItemFromBlock(this), 0, "inventory");
    }
    
    
    @SideOnly(Side.CLIENT)
    public void initModel() {
        ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0, new ModelResourceLocation(getRegistryName(), "inventory"));
    }
    
    @Override
    public boolean isFullBlock(IBlockState state) {
        return false;
    }
    
    
    @Override
    public boolean isFullCube(IBlockState state) {
        return false;
    }
    
    @Override
    public boolean isOpaqueCube(IBlockState state) {
        return false;
    }
    
    
//ALL the following part is to FACE the block    
    
    @Override
    public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) {
        if (!worldIn.isRemote)
        {
            IBlockState north = worldIn.getBlockState(pos.north());
            IBlockState south = worldIn.getBlockState(pos.south());
            IBlockState west = worldIn.getBlockState(pos.west());
            IBlockState east = worldIn.getBlockState(pos.east());
            EnumFacing face = (EnumFacing)state.getValue(FACING);
    
            if (face == EnumFacing.NORTH && north.isFullBlock() && !south.isFullBlock()) face = EnumFacing.SOUTH;
            else if (face == EnumFacing.SOUTH && south.isFullBlock() && !north.isFullBlock()) face = EnumFacing.NORTH;
            else if (face == EnumFacing.WEST && west.isFullBlock() && !east.isFullBlock()) face = EnumFacing.EAST;
            else if (face == EnumFacing.EAST && east.isFullBlock() && !west.isFullBlock()) face = EnumFacing.WEST;
            worldIn.setBlockState(pos, state.withProperty(FACING, face), 2);
        }
    }
    
    
    
    
    @Override
    public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand) {
        return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
                
    }
    
        
    @Override
    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.notifyBlockUpdate(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), state, 2);
    }
        
    
    
// This override is about how the block looks, don't forget to edit it if it has animation!
    @Override
    public EnumBlockRenderType getRenderType(IBlockState state) {
        return EnumBlockRenderType.MODEL;
    }
    
    

    @Override
    public IBlockState withRotation(IBlockState state, Rotation rot) {
        return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
    }
    
    @Override
    public IBlockState withMirror(IBlockState state, Mirror mirrorIn) {
        return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
    }
    
    
//I'm not sure why it is about container here ...
    @Override
    protected BlockStateContainer createBlockState() {
        return new BlockStateContainer(this, new IProperty[] {FACING});
    }
        
    @Override
    public IBlockState getStateFromMeta(int meta) {
        EnumFacing facing = EnumFacing.getFront(meta);
        if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
        return this.getDefaultState().withProperty(FACING, facing);
    }
    
    @Override
    public int getMetaFromState(IBlockState state) {
        return ((EnumFacing)state.getValue(FACING)).getIndex();
    }
    
// End of the FACING part
    
// Here is the CONTAINER (tileentity and gui) part
    
        
    @Override
    public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
       
        if (worldIn.isRemote) {
           return true;
        }
            
        playerIn.openGui(MyMod.instance, Reference.FAKE_BLOCK_GUI, worldIn, pos.getX(), pos.getY(), pos.getZ());
        
        return true;
    }
    
    @Override
    public boolean canDropFromExplosion(Explosion explosionIn) {
       
        return true;
    }
    
    @Override
    public TileEntity createNewTileEntity(World wolrdIn, int meta) {
        return new FakeBlockTileEntity();
    }
    
    
   @Override
   public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
   {
       FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos);

       if (tileentity != null)
       {
          InventoryHelper.dropInventoryItems(worldIn, pos, tileentity);
       }

       super.breakBlock(worldIn, pos, state);
       
    }
    
    
    

// End of the TILEENTITY part

    
    
    
    
}
 

 

Its TileEntity

Spoiler

package sunsigne.MyMod.tileentity;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityLockableLoot;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import sunsigne.MyMod.Reference;
import sunsigne.MyMod.container.FakeBlockContainer;

public class FakeBlockTileEntity extends TileEntityLockableLoot {

        
        private NonNullList<ItemStack> fakeblockConstents = NonNullList.<ItemStack>withSize(SIZE, ItemStack.EMPTY);
        public static final int SIZE = 8;
        
        @Override
        public String getName() {
            return null;
        }

        @Override
        public boolean hasCustomName() {
            return false;
        }        
        
        
        @Override
        public int getSizeInventory() {
            return 8;
        }
        
        @Override
        public int getInventoryStackLimit() {
            return 64;
        }
        
        @Override
        public boolean isEmpty()
        {
            for(ItemStack stack : this.fakeblockConstents)
        
                {
                    if(!stack.isEmpty()) return false;
                }
            return true;
        }
        
            
    
        private ItemStackHandler itemStackHandler = new ItemStackHandler(SIZE) {
            @Override
            protected void onContentsChanged(int slot) {
                FakeBlockTileEntity.this.markDirty();
            }
        };


        @Override
        public void readFromNBT(NBTTagCompound compound) {
            super.readFromNBT(compound);
            if (compound.hasKey("items")) {
                itemStackHandler.deserializeNBT((NBTTagCompound) compound.getTag("items"));
            }
        }
        
        

        @Override
        public NBTTagCompound writeToNBT(NBTTagCompound compound) {
            super.writeToNBT(compound);
            compound.setTag("items", itemStackHandler.serializeNBT());
            return compound;
        }        

        

        @Override
        public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
            if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
                return true;
            }
            return super.hasCapability(capability, facing);
        }

        @Override
        public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
            if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
                return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(itemStackHandler);
            }
            return super.getCapability(capability, facing);
        }

        public boolean canInteractWith(EntityPlayer playerIn) {
            return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
        }
        
        
        @Override
        public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) {
        return new FakeBlockContainer(playerInventory, this);
        }
        
        @Override
        public String getGuiID() {
            return Reference.MODID + ":fake_block";
        }
        

        @Override
        protected NonNullList<ItemStack> getItems() {
            return fakeblockConstents;
        }


        @Override
        public void openInventory(EntityPlayer player) {
    
        }

        @Override
        public void closeInventory(EntityPlayer player) {
            
        }


}
 

 

and its Container, even if I don't think the problem comes from it

Spoiler

package sunsigne.MyMod.container;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;
import sunsigne.MyMod.tileentity.FakeBlockTileEntity;

public class FakeBlockContainer extends Container
{

    
     
     private final FakeBlockTileEntity fakeblockInventory;

        public FakeBlockContainer(InventoryPlayer playerInventory, FakeBlockTileEntity fakeblockInventory)
        {
            this.fakeblockInventory = fakeblockInventory;

            addOwnSlots();
            addPlayerSlots(playerInventory);
            
        }

        private void addPlayerSlots(InventoryPlayer playerInventory)
        {
            // Slots for the main inventory
            for (int row = 0; row < 3; ++row)
            {
                for (int col = 0; col < 9; ++col)
                {
                    int x = 48 + col * 18;
                    int y = row * 18 + 84;
                    this.addSlotToContainer(new Slot(playerInventory, col + row * 9 + 10, x, y));
                }
            }

            // Slots for the hotbar
            for (int row = 0; row < 9; ++row)
            {
                int x = 48 + row * 18;
                int y = 58 + 84;
                this.addSlotToContainer(new Slot(playerInventory, row, x, y));
            }
        }

        // Here are the slots for the container itself !
        
        private void addOwnSlots()
        {
            IItemHandler itemHandler = this.fakeblockInventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
                          
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 0, 93, 17));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 1, 111, 17));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 2, 129, 17));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 3, 147, 17));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 4, 93, 48));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 5, 111, 48));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 6, 129, 48));
               this.addSlotToContainer(new SlotItemHandler(itemHandler, 7, 147, 48));
                
            
        }

        @Override
        public ItemStack transferStackInSlot(EntityPlayer playerIn, int index)
        {
            ItemStack itemstack = ItemStack.EMPTY;
            Slot slot = this.inventorySlots.get(index);

            if (slot != null && slot.getHasStack())
            {
                ItemStack itemstack1 = slot.getStack();
                itemstack = itemstack1.copy();

                if (index < FakeBlockTileEntity.SIZE)
                {
                    if (!this.mergeItemStack(itemstack1, FakeBlockTileEntity.SIZE, this.inventorySlots.size(), true))
                    {
                        return ItemStack.EMPTY;
                    }
                } 
                else if (!this.mergeItemStack(itemstack1, 0, FakeBlockTileEntity.SIZE, false))
                {
                    return ItemStack.EMPTY;
                }

                if (itemstack1.isEmpty())
                {
                    slot.putStack(ItemStack.EMPTY);
                } else
                {
                    slot.onSlotChanged();
                }
            }

            return itemstack;
        }


        @Override
        public boolean canInteractWith(EntityPlayer playerIn)
        {

            return fakeblockInventory.canInteractWith(playerIn);
        }
        
}

 

 

I'm almost sure the problem comes from the way i write my items in TileEntity, but whenever I try another method my items just disseapear when I log out ^^

 

if anyone can help me that would be nice :)

thank in advance ;)

Edited by sunsigne
solved
Posted
3 hours ago, sunsigne said:

private NonNullList<ItemStack> fakeblockConstents = NonNullList.<ItemStack>withSize(SIZE, ItemStack.EMPTY);
        public static final int SIZE = 8;

Use ItemStackHandler instead of this

3 hours ago, sunsigne said:

ITileEntityProvider, IHasModel

Don’t do this

3 hours ago, sunsigne said:

@Override
    public void registerModels()
    {
    
        MyMod.proxy.registerItemRenderer(Item.getItemFromBlock(this), 0, "inventory");
    }
    
    
    @SideOnly(Side.CLIENT)
    public void initModel() {
        ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0, new ModelResourceLocation(getRegistryName(), "inventory"));
    }

Don’t do this

3 hours ago, sunsigne said:

FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos);

       if (tileentity != null)
       {
          InventoryHelper.dropInventoryItems(worldIn, pos, tileentity);
       }

       super.breakBlock(worldIn, pos, state);

You should check for null before casting. What does InventoryHelper#dropInventoryItems do?

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Posted (edited)

 

3 hours ago, Cadiboo said:

Don’t do this

Don’t do this

You should check for null before casting

It's nice to try to help me :)

but has i spent 10 hours you can guess i already tried a lot of things and if you aren't more precise in your explanations i'll just revolve around the problem.

 

I deleted the parts you dislike, but if i remove NonNullList from my tile entity (and everything assiociated) i just get a new problem in my FakeBlock

 

TileEntity

Spoiler

package sunsigne.MyMod.tileentity;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityLockableLoot;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import sunsigne.MyMod.Reference;
import sunsigne.MyMod.container.FakeBlockContainer;

public class FakeBlockTileEntity extends TileEntity {

        

        public static final int SIZE = 8;

        private ItemStackHandler itemStackHandler = new ItemStackHandler(SIZE) {
            @Override
            protected void onContentsChanged(int slot) {
                FakeBlockTileEntity.this.markDirty();
            }
        };


        @Override
        public void readFromNBT(NBTTagCompound compound) {
            super.readFromNBT(compound);
            if (compound.hasKey("items")) {
                itemStackHandler.deserializeNBT((NBTTagCompound) compound.getTag("items"));
            }
        }
        
        

        @Override
        public NBTTagCompound writeToNBT(NBTTagCompound compound) {
            super.writeToNBT(compound);
            compound.setTag("items", itemStackHandler.serializeNBT());
            return compound;
        }        

        

        @Override
        public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
            if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
                return true;
            }
            return super.hasCapability(capability, facing);
        }

        @Override
        public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
            if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
                return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(itemStackHandler);
            }
            return super.getCapability(capability, facing);
        }

        public boolean canInteractWith(EntityPlayer playerIn) {
            return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
        }

}

 

FakeBlock : the problem is there

Spoiler

@Override
   public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
   {
       FakeBlockTileEntity tileentity = (FakeBlockTileEntity) worldIn.getTileEntity(pos);
       InventoryHelper.dropInventoryItems(worldIn, pos, tileentity);
       super.breakBlock(worldIn, pos, state);
       
    }

Now it says "The method dropInventoryItems(World, BlockPos IInventory) in the type InventoryHelper is not applicable for the arguments (World, BlockPos, FakeBlockTileEntity).

That's why I used NonNullList in the first case.

Edited by sunsigne
More precision
Posted

In the breakBlock method, loop through the inventory's slots. Create a new EntityItem in the for loop and then call spawnAsEntity. I think InventoryHelper#dropInventoryItems wants an IInventory, which probably won't work in your case. This is somewhat how I did it, and I use ItemStackHandler.

  • Thanks 1
Posted (edited)
2 hours ago, Siqhter said:

In the breakBlock method, loop through the inventory's slots. Create a new EntityItem in the for loop and then call spawnAsEntity. I think InventoryHelper#dropInventoryItems wants an IInventory, which probably won't work in your case. This is somewhat how I did it, and I use ItemStackHandler.

 

You are my HERO ! It worked !

 

for curious people, here is the new BreakBlock part :

Spoiler

@Override
    public void breakBlock(World world, BlockPos pos, IBlockState state)
    {
        FakeBlockTileEntity te = (FakeBlockTileEntity) world.getTileEntity(pos);
        IItemHandler cap = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);

        for (int i = 0; i < cap.getSlots(); ++i)
        {
            ItemStack itemstack = cap.getStackInSlot(i);

            if (!itemstack.isEmpty())
            {
                InventoryHelper.spawnItemStack(world, pos.getX(), pos.getY(), pos.getZ(), itemstack);
            }
        }

        super.breakBlock(world, pos, state);
    }
    

 

I guess i'll never know why "dropitem" didn't work, but as lon as my items still "dropped" i don't really care ^^

 

Have a nice day ;)

 

 

 

 

A little (maybe stupid) question. How do i mark a topic as "solved" ? It's been 20 minutes i'm searching but not finding ^^

Edited by sunsigne
How to solve a topic ?
Posted

You can edit your original post and add “[SOLVED] “ to the title.

 

Here is an example of how I drop my items https://github.com/Cadiboo/WIPTechAlpha/blob/fb5883e9d76ef0361ec1ebbcb9c508611dd2ef6b/src/main/java/cadiboo/wiptech/capability/inventory/ModItemStackHandler.java#L23-L35

You still need to

- Not use ITileEntityProvider: It is legacy vanilla code, simply override hasTileEntity and createTileEntity.

- Not use IHasModel: It is a stupid way of registering things that makes you write the exact same lines of code for ever class, it is unneeded and a better result can be achieved with 1 single line of code.

- Check for null before using the tile entity you get from world#getTileEntity

- Check that the tile entity you get from world#getTileEntity actually is an instance of your tile entity before you cast it (when the block is replaced, a structure is loaded on top of it, commands like /fill, /clone or /setblock are used, or even if the server is just overloaded, it might not be an instance of your tile entity)

  • Like 1

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.