17 мгновений краша

Статус
В этой теме нельзя размещать новые ответы.
10
0
Здраствуйте!
Ох, оптимистичное начало тут ни к чему... Я уже 2 дня долблюсь над одной и той же проблемой...
Код:
[01:15:35] [Client thread/FATAL]: Unreported exception thrown!
java.lang.ArrayIndexOutOfBoundsException: 3
    at alexsocol.osm.blocks.tileentity.ChronodialProcessorTileEntity.setInventorySlotContents(ChronodialProcessorTileEntity.java:92) ~[ChronodialProcessorTileEntity.class:?]
    at net.minecraft.inventory.Slot.putStack(Slot.java:104) ~[Slot.class:?]
    at net.minecraft.inventory.Container.putStacksInSlots(Container.java:558) ~[Container.class:?]
    at net.minecraft.client.network.NetHandlerPlayClient.handleWindowItems(NetHandlerPlayClient.java:1202) ~[NetHandlerPlayClient.class:?]
    at net.minecraft.network.play.server.S30PacketWindowItems.processPacket(S30PacketWindowItems.java:70) ~[S30PacketWindowItems.class:?]
    at net.minecraft.network.play.server.S30PacketWindowItems.processPacket(S30PacketWindowItems.java:78) ~[S30PacketWindowItems.class:?]
    at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) ~[NetworkManager.class:?]
    at net.minecraft.client.multiplayer.PlayerControllerMP.updateController(PlayerControllerMP.java:317) ~[PlayerControllerMP.class:?]
[...]
Суть в том что это кароч как печка но не печка. Блок процессинга.
Скажите что делать а то я уже почти отчаялся...
Сорцы:
ChronodialProcessor.java
Код:
import java.util.Random;

import alexsocol.osm.ModInfo;
import alexsocol.osm.OSMMain;
import alexsocol.osm.blocks.tileentity.ChronodialProcessorTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public class ChronodialProcessor extends BlockContainer {
    private static boolean hasTileEntity;
    private final Random rnd = new Random();
    private final boolean work;
    private static boolean isActive;

    public ChronodialProcessor() {
        super(Material.iron);
        this.setBlockName("ChronodialProcessor");
        this.setBlockTextureName(ModInfo.MODID + ":ChronodialProcessorIcon");
        this.setCreativeTab(OSMMain.osmTab);
        this.setHardness(1.0F);
        this.setHarvestLevel("pickaxe", 2);
        this.setLightLevel(15.0F);
        this.setLightOpacity(1);
        this.setResistance(6000.F);
        this.setStepSound(soundTypeMetal);
        this.blockParticleGravity = 1.0F;
        this.slipperiness = 0.6F;
        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        this.lightOpacity = 20;
        this.setTickRandomly(false);
        this.useNeighborBrightness = false;
        this.isActive = false;
        this.work = isActive;
    }

    @Override
    public void breakBlock(World par1World, int par2, int par3, int par4, Block par5, int par6) {
        dropItemsOnBlockBreak(par1World, par2, par3, par4, par5, par6);
        ChronodialProcessorTileEntity table = (ChronodialProcessorTileEntity) par1World.getTileEntity(par2, par3, par4);
        super.breakBlock(par1World, par2, par3, par4, par5, par6);
    }

    public static void dropItemsOnBlockBreak(World par1World, int par2, int par3, int par4, Block par5, int par6) {
        try {
            IInventory inv = (IInventory) par1World.getTileEntity(par2, par3, par4);

            if (inv != null) {
                for (int j1 = 0; j1 < inv.getSizeInventory(); ++j1) {
                    ItemStack itemstack = inv.getStackInSlot(j1);

                    if (itemstack != null) {
                        float f = par1World.rand.nextFloat() * 0.8F + 0.1F;
                        float f1 = par1World.rand.nextFloat() * 0.8F + 0.1F;
                        float f2 = par1World.rand.nextFloat() * 0.8F + 0.1F;

                        while (itemstack.stackSize > 0) {
                            int k1 = par1World.rand.nextInt(21) + 10;

                            if (k1 > itemstack.stackSize) {
                                k1 = itemstack.stackSize;
                            }

                            itemstack.stackSize -= k1;
                            EntityItem entityitem = new EntityItem(par1World, (double) ((float) par2 + f),
                                    (double) ((float) par3 + f1), (double) ((float) par4 + f2),
                                    new ItemStack(itemstack.getItem(), k1, itemstack.getItemDamage()));

                            if (itemstack.hasTagCompound()) {
                                entityitem.getEntityItem()
                                        .setTagCompound((NBTTagCompound) itemstack.getTagCompound().copy());
                            }

                            float f3 = 0.05F;
                            entityitem.motionX = (double) ((float) par1World.rand.nextGaussian() * f3);
                            entityitem.motionY = (double) ((float) par1World.rand.nextGaussian() * f3 + 0.2F);
                            entityitem.motionZ = (double) ((float) par1World.rand.nextGaussian() * f3);
                            par1World.spawnEntityInWorld(entityitem);
                        }
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return;
        }
    }

    @Override
    public int getRenderBlockPass() {
        return 0;
    }

    @Override
    public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer,
            int par6, float par7, float par8, float par9) {
        if (par1World.isRemote) {
            return true;
        } else {
            if (!par5EntityPlayer.isSneaking()) {
                ItemStack currentItem = par5EntityPlayer.getCurrentEquippedItem();
                par5EntityPlayer.openGui(OSMMain.instance, 0, par1World, par2, par3, par4);
                return true;
            } else {
                ChronodialProcessorTileEntity table = (ChronodialProcessorTileEntity) par1World.getTileEntity(par2,
                        par3, par4);
                return false;
            }
        }
    }

    @Override
    public int getRenderType() {
        return 2634;
    }

    @Override
    public boolean isOpaqueCube() {
        return false;
    }

    @Override
    public boolean renderAsNormalBlock() {
        return false;
    }

    @Override
    public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) {
        return new ChronodialProcessorTileEntity();
    }
}
ChronodialProcessorTileEntity.java
Код:
import alexsocol.osm.crafting.ProcessorRecipes;
import alexsocol.osm.proxy.CommonProxy;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFurnace;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;

public class ChronodialProcessorTileEntity extends TileEntity implements ISidedInventory {
    private static final int[] slotsTop = new int[] { 0 };
    private static final int[] slotsBottom = new int[] { 2, 1 };
    private static final int[] slotsSides = new int[] { 1 };
    /**
     * The ItemStacks that hold the items currently being used in the furnace
     */
    private ItemStack[] itemStacks = new ItemStack[3];
    /**
     * The number of ticks that a fresh copy of the currently-burning item would
     * keep the furnace burning for
     */
    public int currentItemProcessingTime;
    /** The number of ticks that the current item has been cooking for */
    public int processingTime = 0;
    public int completedTime = 1;
    private String name;

    public int getSizeInventory() {
        return this.itemStacks.length;
    }

    public ItemStack getStackInSlot(int slot) {
        return this.itemStacks[slot];
    }

    public ItemStack decrStackSize(int slot, int amount) {
        if (this.itemStacks[slot] != null) {
            ItemStack itemstack;

            if (this.itemStacks[slot].stackSize <= amount) {
                itemstack = this.itemStacks[slot];
                this.itemStacks[slot] = null;
                return itemstack;
            } else {
                itemstack = this.itemStacks[slot].splitStack(amount);

                if (this.itemStacks[slot].stackSize == 0) {
                    this.itemStacks[slot] = 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 slot) {
        if (this.itemStacks[slot] != null) {
            ItemStack itemstack = this.itemStacks[slot];
            this.itemStacks[slot] = 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 slot, ItemStack stack) {
        this.itemStacks[slot] = stack;

        if (stack != null && stack.stackSize > this.getInventoryStackLimit()) {
            stack.stackSize = this.getInventoryStackLimit();
        }
    }

    /**
     * Returns the name of the inventory
     */
    public String getInventoryName() {
        return this.hasCustomInventoryName() ? this.name : "container.processor";
    }

    /**
     * Returns if the inventory is named
     */
    public boolean hasCustomInventoryName() {
        return this.name != null && this.name.length() > 0;
    }

    public void getName(String str) {
        this.name = str;
    }

    public void readFromNBT(NBTTagCompound tag) {
        super.readFromNBT(tag);
        NBTTagList nbttaglist = tag.getTagList("Items", 10);
        this.itemStacks = new ItemStack[this.getSizeInventory()];

        for (int i = 0; i < nbttaglist.tagCount(); ++i) {
            NBTTagCompound nbttagcompound1 = nbttaglist.getCompoundTagAt(i);
            byte b0 = nbttagcompound1.getByte("Slot");

            if (b0 >= 0 && b0 < this.itemStacks.length) {
                this.itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbttagcompound1);
            }
        }

        this.processingTime = tag.getShort("ProcessingTime");
        this.currentItemProcessingTime = getItemWorkTime(this.itemStacks[1]);

        if (tag.hasKey("CustomName", 8)) {
            this.name = tag.getString("CustomName");
        }
    }

    public void writeToNBT(NBTTagCompound tag) {
        super.writeToNBT(tag);
        tag.setShort("ProcessingTime", (short) this.processingTime);
        NBTTagList nbttaglist = new NBTTagList();

        for (int i = 0; i < this.itemStacks.length; ++i) {
            if (this.itemStacks[i] != null) {
                NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                nbttagcompound1.setByte("Slot", (byte) i);
                this.itemStacks[i].writeToNBT(nbttagcompound1);
                nbttaglist.appendTag(nbttagcompound1);
            }
        }

        tag.setTag("Items", nbttaglist);

        if (this.hasCustomInventoryName()) {
            tag.setString("CustomName", this.name);
        }
    }

    /**
     * Returns the maximum stack size for a inventory slot.
     */
    public int getInventoryStackLimit() {
        return 64;
    }

    /**
     * Returns an integer between 0 and the passed value representing how close
     * the current item is to being completely cooked
     */
    @SideOnly(Side.CLIENT)
    public int getCookProgressScaled(int time) {
        return this.processingTime * time / 200;
    }

    /**
     * Returns an integer between 0 and the passed value representing how much
     * burn time is left on the current fuel item, where 0 means that the item
     * is exhausted and the passed value means that the item is fresh
     */
    @SideOnly(Side.CLIENT)
    public int getBurnTimeRemainingScaled(int time) {
        if (this.currentItemProcessingTime == 0) {
            this.currentItemProcessingTime = 200;
        }

        return this.processingTime * time / this.currentItemProcessingTime;
    }

    public boolean isProcessing() {
        return this.processingTime > 0;
    }

    public void updateEntity() {
        boolean flag = this.processingTime > 0;
        boolean flag1 = false;

        if (this.processingTime > 0) {
            --this.processingTime;
        }

        if (!this.worldObj.isRemote) {
            if (this.processingTime != 0 || this.itemStacks[1] != null && this.itemStacks[0] != null) {
                if (this.processingTime == 0 && this.canProcess()) {
                    this.currentItemProcessingTime = this.processingTime = getItemWorkTime(this.itemStacks[1]);
                    if (this.processingTime > 0) {
                        flag1 = true;

                        if (this.itemStacks[1] != null) {
                            --this.itemStacks[1].stackSize;

                            if (this.itemStacks[1].stackSize == 0) {
                                this.itemStacks[1] = itemStacks[1].getItem().getContainerItem(itemStacks[1]);
                            }
                        }
                    }
                }

                if (this.isProcessing() && this.canProcess()) {
                    ++this.completedTime;

                    if (this.completedTime == currentItemProcessingTime) {
                        this.completedTime = 0;
                        this.processItem();
                        flag1 = true;
                    }
                } else {
                    this.completedTime = 0;
                }
            }

            if (flag != this.processingTime > 0) {
                flag1 = true;
                BlockFurnace.updateFurnaceBlockState(this.processingTime > 0, this.worldObj, this.xCoord, this.yCoord,
                        this.zCoord);
            }
        }

        if (flag1) {
            this.markDirty();
        }
    }

    private boolean canProcess() {
        if (this.itemStacks[0] == null) {
            return false;
        } else {
            ItemStack itemstack = ProcessorRecipes.processing().getProcessingResult(this.itemStacks[0]);
            if (itemstack == null)
                return false;
            if (this.itemStacks[2] == null)
                return true;
            if (!this.itemStacks[2].isItemEqual(itemstack))
                return false;
            int result = itemStacks[2].stackSize + itemstack.stackSize;
            return result <= getInventoryStackLimit() && result <= this.itemStacks[2].getMaxStackSize();
        }
    }

    public void processItem() {
        if (this.canProcess()) {
            ItemStack itemstack = ProcessorRecipes.processing().getProcessingResult(this.itemStacks[0]);

            if (this.itemStacks[2] == null) {
                this.itemStacks[2] = itemstack.copy();
            } else if (this.itemStacks[2].getItem() == itemstack.getItem()) {
                this.itemStacks[2].stackSize += itemstack.stackSize;
            }

            --this.itemStacks[0].stackSize;

            if (this.itemStacks[0].stackSize <= 0) {
                this.itemStacks[0] = null;
            }
        }
    }

    public static int getItemWorkTime(ItemStack stack) {
        if (stack.getItem() == CommonProxy.strangeMatter) {
            return 800;
        }
        return 0;
    }

    public static boolean isItemFuel(ItemStack stack) {
        return getItemWorkTime(stack) > 0;
    }

    /**
     * Do not make give this method the name canInteractWith because it clashes
     * with Container
     */
    public boolean isUseableByPlayer(EntityPlayer player) {
        return this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false
                : player.getDistanceSq((double) this.xCoord + 0.5D, (double) this.yCoord + 0.5D,
                        (double) this.zCoord + 0.5D) <= 64.0D;
    }

    public void openInventory() {
    }

    public void closeInventory() {
    }

    /**
     * Returns true if automation is allowed to insert the given stack (ignoring
     * stack size) into the given slot.
     */
    public boolean isItemValidForSlot(int slot, ItemStack stack) {
        return slot == 2 ? false : (slot == 1 ? isItemFuel(stack) : true);
    }

    /**
     * Returns an array containing the indices of the slots that can be accessed
     * by automation on the given side of this block.
     */
    public int[] getAccessibleSlotsFromSide(int slot) {
        return slot == 0 ? slotsBottom : (slot == 1 ? slotsTop : slotsSides);
    }

    /**
     * Returns true if automation can insert the given item in the given slot
     * from the given side. Args: Slot, item, side
     */
    public boolean canInsertItem(int par1, ItemStack stack, int par3) {
        return this.isItemValidForSlot(par1, stack);
    }

    /**
     * Returns true if automation can extract the given item in the given slot
     * from the given side. Args: Slot, item, side
     */
    public boolean canExtractItem(int par1, ItemStack stack, int par3) {
        return par3 != 0 || par1 != 1 || stack.getItem() == Items.bucket;
    }
}
[merge_posts_bbcode]Добавлено: 30.12.2015 02:47:19[/merge_posts_bbcode]

(Продолжение)
ChronodialConatiner.java
Код:
import alexsocol.osm.blocks.tileentity.ChronodialProcessorTileEntity;
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;

public class ChronodialContainer extends Container {
    protected ChronodialProcessorTileEntity te;

    public ChronodialContainer(InventoryPlayer ip, ChronodialProcessorTileEntity tile) {
        te = tile;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                addSlotToContainer(new Slot(te, j + i * 3, 62 + j * 18, 17 + i * 18));
            }
        }
        bindPlayerInventory(ip);
    }

    @Override
    public boolean canInteractWith(EntityPlayer player) {
        return te.isUseableByPlayer(player);
    }

    protected void bindPlayerInventory(InventoryPlayer ip) {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 9; j++) {
                addSlotToContainer(new Slot(ip, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
            }
        }
        for(int i = 0; i < 9; i++) {
            addSlotToContainer(new Slot(ip, i, 8 + i * 18, 142));
        }
    }

    @Override
    public ItemStack transferStackInSlot(EntityPlayer player, int slot) {
        ItemStack stack = null;
        Slot slotObject = (Slot) inventorySlots.get(slot);
        if (slotObject != null && slotObject.getHasStack()) {
            ItemStack stackInSlot = slotObject.getStack();
            stack = stackInSlot.copy();
            if (slot < te.getSizeInventory()) {
                if (!this.mergeItemStack(stackInSlot, te.getSizeInventory(), 36 + te.getSizeInventory(), true)) {
                    return null;
                }
            } else if (!this.mergeItemStack(stackInSlot, 0, te.getSizeInventory(), false)) {
                return null;
            }
            
            if(stackInSlot.stackSize == 0) {
                slotObject.putStack(null);
            } else {
                slotObject.onSlotChanged();
            }
            if(stackInSlot.stackSize == stack.stackSize) {
                return null;
            }
            slotObject.onPickupFromSlot(player,  stackInSlot);
        }
        return stack;
    }
}
GuiChronodial.java
Код:
import org.lwjgl.opengl.GL11;

import alexsocol.osm.blocks.container.ChronodialContainer;
import alexsocol.osm.blocks.tileentity.ChronodialProcessorTileEntity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;


@SideOnly(Side.CLIENT)
public class GuiChronodial extends GuiContainer
{
    private static final ResourceLocation furnaceGuiTextures = new ResourceLocation("textures/gui/container/furnace.png");
    private ChronodialProcessorTileEntity tileProcessor;

    public GuiChronodial(InventoryPlayer p_i1091_1_, ChronodialProcessorTileEntity p_i1091_2_)
    {
        super(new ChronodialContainer(p_i1091_1_, p_i1091_2_));
        this.tileProcessor = p_i1091_2_;
    }

    protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_)
    {
        String s = this.tileProcessor.hasCustomInventoryName() ? this.tileProcessor.getInventoryName() : I18n.format(this.tileProcessor.getInventoryName(), new Object[0]);
        this.fontRendererObj.drawString(s, this.xSize / 2 - this.fontRendererObj.getStringWidth(s) / 2, 6, 4210752);
        this.fontRendererObj.drawString(I18n.format("container.inventory", new Object[0]), 8, this.ySize - 96 + 2, 4210752);
    }

    protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_)
    {
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.mc.getTextureManager().bindTexture(furnaceGuiTextures);
        int k = (this.width - this.xSize) / 2;
        int l = (this.height - this.ySize) / 2;
        this.drawTexturedModalRect(k, l, 0, 0, this.xSize, this.ySize);

        if (this.tileProcessor.isProcessing())
        {
            int i1 = this.tileProcessor.getBurnTimeRemainingScaled(13);
            this.drawTexturedModalRect(k + 56, l + 36 + 12 - i1, 176, 12 - i1, 14, i1 + 1);
            i1 = this.tileProcessor.getCookProgressScaled(24);
            this.drawTexturedModalRect(k + 79, l + 34, 176, 14, i1 + 1, 16);
        }
    }
}
GuiHandler.java
Код:
import alexsocol.osm.blocks.container.ChronodialContainer;
import alexsocol.osm.blocks.tileentity.ChronodialProcessorTileEntity;
import alexsocol.osm.gui.GuiChronodial;
import cpw.mods.fml.common.network.IGuiHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public class GuiHandler implements IGuiHandler {
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
        TileEntity te = world.getTileEntity(x, y, z);
        if(te instanceof ChronodialProcessorTileEntity) {
            return new ChronodialContainer(player.inventory, (ChronodialProcessorTileEntity) te);
        }
        return null;
    }
    
    public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
        TileEntity te = world.getTileEntity(x,  y,  z);
        if(te instanceof ChronodialProcessorTileEntity) {
            return new GuiChronodial(player.inventory, (ChronodialProcessorTileEntity) te);
        }
        return null;
    }
}

[merge_posts_bbcode]Добавлено: 30.12.2015 02:50:54[/merge_posts_bbcode]

(Продолжение 2)
Регистрация хандлера (на крайняк)
Код:
NetworkRegistry.INSTANCE.registerGuiHandler(this, new GuiHandler());
Я уверен на 100500% что проблема именно в ChronodialConatiner.java, я ж не глупый и вижу, но как его написать правильно? Может можно готовый вариант?
 
У тебя массив слотов одним элементом длиной, хотя в контейнере ты юзаешь не один слот. Учись читать краши
 
svk написал(а):
Не хочу обижать, но ты в java ещё глупый :D
Да не, я просто люблю кодить в 2 часа ночи
[merge_posts_bbcode]Добавлено: 30.12.2015 14:24:04[/merge_posts_bbcode]

Dragon2488 написал(а):
У тебя массив слотов одним элементом длиной, хотя в контейнере ты юзаешь не один слот. Учись читать краши
Краш то я понял, но теперь скажите откуда там 1 елемент если массив длиной в 3 єлемента же? што?
и есть ли какое-то "практическое пособие" по написанию контейнеров? а то я не въехаль :с
 
Всё, раздолбался... И правда надо прекращать кодить в 2 часа ночи...
Тему можно закрывать.
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху