Jump to content

TileEntity readFromNBT called more often than writeToNBT.


Raycoms

Recommended Posts

We got a pretty strange problem.

The readFromNBT method is called twice on start for every of our special tileEntities and is also called on blockUpdate.

on the other side the writeToNBT isn't called again, which causes consistency problems since some of our variables haven't been set again.

 

package com.minecolonies.tileentities;

import com.minecolonies.colony.Colony;
import com.minecolonies.colony.ColonyManager;
import com.minecolonies.colony.ColonyView;
import com.minecolonies.colony.buildings.AbstractBuilding;
import com.minecolonies.colony.materials.MaterialSystem;
import com.minecolonies.colony.permissions.Permissions;
import com.sun.istack.internal.NotNull;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.math.BlockPos;

/**
* Class which handles the tileEntity of our colonyBuildings.
*/
public class TileEntityColonyBuilding extends TileEntityChest
{
    private final static String TAG_COLONY = "colony";
    private              int    colonyId   = 0;
    private Colony           colony;
    private AbstractBuilding building;

    /**
     * Empty standard constructor.
     */
    public TileEntityColonyBuilding()
    {
        /**
         * Intentionally left empty.
         */
    }

    @Override
    public SPacketUpdateTileEntity getUpdatePacket()
    {
        NBTTagCompound compound = new NBTTagCompound();
        compound.setInteger(TAG_COLONY, colonyId);
        return new SPacketUpdateTileEntity(this.getPosition(), 0, compound);
    }

    @Override
    public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet)
    {
        NBTTagCompound compound = packet.getNbtCompound();
        colonyId = compound.getInteger(TAG_COLONY);
    }

    @Override
    public void update()
    {
        super.update();

        if (!worldObj.isRemote)
        {
            if (colonyId == 0)
            {
                throw new IllegalStateException(String.format("TileEntityColonyBuilding at %s:[%d,%d,%d] has no colonyId",
                  worldObj.getWorldInfo().getWorldName(),
                  pos.getX(),
                  pos.getY(),
                  pos.getZ()));
            }
        }
    }

    @Override
    public void onChunkUnload()
    {
        if (building != null)
        {
            building.setTileEntity(null);
        }
    }

    /**
     * Returns the position of the tile entity
     *
     * @return Block Coordinates of the tile entity
     */
    public BlockPos getPosition()
    {
        return pos;
    }

    /**
     * Synchronises colony references from the tile entity
     */
    private void updateColonyReferences()
    {
        if (colony == null)
        {
            if (colonyId != 0)
            {
                colony = ColonyManager.getColony(colonyId);
            }
            else
            {
                throw new IllegalStateException(String.format("TileEntityColonyBuilding at %s:[%d,%d,%d] has no colonyId",
                  worldObj.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ()));
            }

//            else if (worldObj != null)
//            {
//                throw new IllegalStateException(String.format("TileEntityColonyBuilding at %s:[%d,%d,%d] has no colonyId",
//                        worldObj.getWorldInfo().getWorldName(), xCoord, yCoord, zCoord));
//
//                colony = ColonyManager.getColony(worldObj, xCoord, yCoord, zCoord);
//
//                if (colony != null)
//                {
//                    colonyId = colony.getID();
//                }
//            }
        }

        if (building == null && colony != null)
        {
            building = colony.getBuilding(getPosition());
            if (building != null)
            {
                building.setTileEntity(this);
            }
        }
    }

    /**
     * Returns the colony ID
     *
     * @return ID of the colony
     */
    public int getColonyId()
    {
        return colonyId;
    }

    /**
     * Returns the colony of the tile entity
     *
     * @return Colony of the tile entity
     */
    public Colony getColony()
    {
        if (colony == null)
        {
            updateColonyReferences();
        }
        return colony;
    }

    /**
     * Sets the colony of the tile entity
     *
     * @param c Colony to set in references
     */
    public void setColony(Colony c)
    {
        colony = c;
        colonyId = c.getID();
        markDirty();
    }

    //todo something goes wrong on colony loading
    @Override
    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        if (!compound.hasKey(TAG_COLONY))
        {
            throw new IllegalStateException(String.format("TileEntityColonyBuilding at %s:[%d,%d,%d] missing COLONY tag.",
              worldObj.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ()));
        }
        colonyId = compound.getInteger(TAG_COLONY);
        updateColonyReferences();
    }

    /**
     * Returns the building associated with the tile entity
     *
     * @return {@link AbstractBuilding} associated with the tile entity
     */
    public AbstractBuilding getBuilding()
    {
        if (building == null)
        {
            updateColonyReferences();
        }
        return building;
    }

    /**
     * Sets the building associated with the tile entity
     *
     * @param b {@link AbstractBuilding} to associate with the tile entity
     */
    public void setBuilding(AbstractBuilding b)
    {
        building = b;
    }

    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);
        if (colonyId == 0)
        {
            throw new IllegalStateException(String.format("TileEntityColonyBuilding at %s:[%d,%d,%d] has no colonyId; %s colony reference.",
              worldObj.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(),
              colony == null ? "NO" : "valid"));
        }
        compound.setInteger(TAG_COLONY, colonyId);
        return compound;
    }

    /**
     * Returns the view of the building associated with the tile entity
     *
     * @return {@link AbstractBuilding.View} the tile entity is associated with
     */
    public AbstractBuilding.View getBuildingView()
    {
        ColonyView c = ColonyManager.getColonyView(colonyId);
        return c != null ? c.getBuilding(getPosition()) : null;
    }

    @Override
    public boolean isUseableByPlayer(@NotNull EntityPlayer player)
    {
        return super.isUseableByPlayer(player) && this.hasAccessPermission(player);
    }

    /**
     * Checks if the player has permission to access the hut
     *
     * @param player Player to check permission of
     * @return True when player has access, or building doesn't exist, otherwise false.
     */
    public boolean hasAccessPermission(EntityPlayer player)//TODO This is called every tick the GUI is open. Is that bad?
    {
        return building == null || building.getColony().getPermissions().hasPermission(player, Permissions.Action.ACCESS_HUTS);
    }

    //-----------------------------Material Handling--------------------------------

    /**
     * Makes sure ItemStacks inside of the inventory aren't affected by changes to the returned stack.
     */
    @Override
    public ItemStack getStackInSlot(int index)
    {
        ItemStack stack = super.getStackInSlot(index);
        if (stack == null)
        {
            return null;
        }
        return stack.copy();
    }

    @Override
    public ItemStack decrStackSize(int index, int quantity)
    {
        ItemStack removed = super.decrStackSize(index, quantity);

        removeStackFromMaterialStore(removed);

        return removed;
    }

    @Override
    public ItemStack removeStackFromSlot(int index)
    {
        ItemStack removed = super.removeStackFromSlot(index);

        removeStackFromMaterialStore(removed);

        return removed;
    }

    @Override
    public void setInventorySlotContents(int index, ItemStack stack)
    {
        ItemStack previous = getStackInSlot(index);
        removeStackFromMaterialStore(previous);

        super.setInventorySlotContents(index, stack);

        addStackToMaterialStore(stack);
    }

    private void addStackToMaterialStore(ItemStack stack)
    {
        if (stack == null)
        {
            return;
        }

        if (MaterialSystem.isEnabled)
        {
            building.getMaterialStore().addMaterial(stack.getItem(), stack.stackSize);
        }
    }

    private void removeStackFromMaterialStore(ItemStack stack)
    {
        if (stack == null)
        {
            return;
        }

        if (MaterialSystem.isEnabled)
        {
            building.getMaterialStore().removeMaterial(stack.getItem(), stack.stackSize);
        }
    }
}

Link to comment
Share on other sites

I don't see an override of shouldRefresh in your TE class. Will the default behavior (replacing your whole TE whenever the state changes) do what you want?

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

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.



×
×
  • Create New...

Important Information

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