Jump to content

TrekkieCub314

Members
  • Posts

    68
  • Joined

  • Last visited

Converted

  • Gender
    Undisclosed
  • Personal Text
    I am new!

TrekkieCub314's Achievements

Stone Miner

Stone Miner (3/8)

-1

Reputation

  1. Hi, I've been trying to get back into modding, but I'm having some problems with some basic stuff. I'm trying to add an item and the item model is not rendering correctly. I've tried using some tutorials, but either they are wrong or (more likely) things have changed between versions and I failed to account for this. Here's my main class: package com.trekkiecub.oddsandends; import com.trekkiecub.oddsandends.init.ItemInit; import com.trekkiecub.oddsandends.proxy.CommonProxy; import com.trekkiecub.oddsandends.util.FUNC; import net.minecraft.init.Blocks; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; @Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION) public class Mod_OddsAndEnds { /// /// Instance and Proxies /// @Instance public static Mod_OddsAndEnds instance; @SidedProxy(serverSide = Reference.SERVER_PROXY, clientSide = Reference.CLIENT_PROXY) public static CommonProxy proxy; /// /// Initialization Events /// // Pre-Init Event @EventHandler public void preInit(FMLInitializationEvent event) { ItemInit.init(); ItemInit.register(); proxy.registerRenders(); FUNC.getLogger().info("Pre-Init Completed"); } // Init Event @EventHandler public void init(FMLInitializationEvent event) { // some example code System.out.println("DIRT BLOCK >> "+Blocks.DIRT.getUnlocalizedName()); } // Post-Init Event @EventHandler public void postInit(FMLInitializationEvent event) { } } ItemInit: package com.trekkiecub.oddsandends.init; import java.util.logging.Logger; import com.trekkiecub.oddsandends.Mod_OddsAndEnds; import com.trekkiecub.oddsandends.Reference; import com.trekkiecub.oddsandends.items.Item_Base; import com.trekkiecub.oddsandends.util.FUNC; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.common.registry.GameRegistry; import scala.actors.threadpool.helpers.Utils; public class ItemInit { public static Item beach_apple; public static void init() { beach_apple = new Item_Base("beach_apple", "beach_apple"); } public static void register() { registerItem(beach_apple); } public static void registerRenders() { registerRender(beach_apple); } public static void registerItem(Item item) { GameRegistry.register(item); } public static void registerRender(Item item) { ModelResourceLocation location = new ModelResourceLocation(item.getRegistryName(), "inventory"); ModelLoader.setCustomModelResourceLocation(item, 0, location); } } ItemBase: package com.trekkiecub.oddsandends.items; import com.trekkiecub.oddsandends.Reference; import net.minecraft.item.Item; public class Item_Base extends Item { public Item_Base(String UnlocName, String ResName) { this.setUnlocalizedName(UnlocName); this.setRegistryName(Reference.MODID, ResName); } } ClientProxy: package com.trekkiecub.oddsandends.proxy; import com.trekkiecub.oddsandends.init.ItemInit; public class ClientProxy extends CommonProxy { @Override public void registerRenders() { ItemInit.registerRenders(); } } beach_apple.json: { "parent": "item/generated", "textures": { "layer0": "tc_oddsandends:items/beach_apple" } } Assets directory as follows: assets ---tc_oddsandends ------lang ------models ---------item ------------beach_apple.json ------textures ---------items ------------beach_apple.png latest log: https://gist.github.com/anonymous/179b61dcc6fefaac340255b5e71ce1e5
  2. I actually have little experience with debugger tools. Most coding I've done in college has been through a text editor and a console, and when I do use an IDE, I use it for error detection and code consistency. What I usually do is I use text output to determine and isolate a problem. I've been looking at the code for the vanilla BlockPane, and it looks like my code should work. The only difference between BlockPane and Block_Chain was that getActualState was overriden in Block_Chain. Removing the override did not change the outcome. I'm doing some debugging now and it looks like BlockRendererDispatcher's renderBlock() is throwing an exception when it tries to set the state to the value returned from getActualBlockState(). This exception is caught and nothing happens afterward. I'm not sure what's causing this, but it looks like the code was designed to smother the exception rather than help figure out what's going wrong.
  3. I'm not sure how to step into the withProperty function of IBlockState in Eclipse (the option is grayed out, not sure what I'm supposed to do to fix this). isBottom() is returning the correct values. When I change the default value for the MID property, the block has the correct model and drops the correct item for the blockstate. It seems the problem is one where the block's state isn't changing when I add a new block below it. I thought the getActualState() function was supposed to let me do that, but it looks like I might need to do more to the block class. Does anyone know what I'm doing wrong?
  4. That didn't seem to help this issue, but I'm glad you spotted that.
  5. getActualState is running, but it appears the MID property is not being set or accessed correctly and I'm not sure what I'm doing wrong. It doesn't matter whether I use the isBottom function as-is or negate it.
  6. Sorry about that. What should be happening is a chain block should change how it renders based on whether the block above it is a chain block as well. So far, that's not working, and every chain block placed keeps its default block state and doesn't change when a new chain block is added.
  7. I have an item that is supposed to place a specific block when used. These blocks should be changing their texture based on whether the block above them is the same kind as itself. It seems I'm not doing this right, and I'm wondering if someone would be willing to help me out with this. I'm somewhat new to block states and how to use them correctly. [spoiler=Item] package com.trekkiecub.oddsandends.items; import java.util.List; import com.trekkiecub.oddsandends.blocks.Block_Chain; import com.trekkiecub.oddsandends.init.BlockInit; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class Item_Chain extends Item { @Override public EnumActionResult onItemUse(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.getBlockState(pos).getBlock() == BlockInit.chain) { Block_Chain chain = (Block_Chain)worldIn.getBlockState(pos).getBlock(); BlockPos nextChain = chain.canAddSegment(worldIn, pos); if (nextChain != null) { worldIn.setBlockState(nextChain, BlockInit.chain.getDefaultState()); stack.stackSize--; } } if (facing != null && facing == EnumFacing.DOWN) { if (playerIn.canPlayerEdit(pos, facing, stack)) { worldIn.setBlockState(pos.down(), BlockInit.chain.getDefaultState()); stack.stackSize--; } } return EnumActionResult.PASS; } @Override public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) { return new ActionResult(EnumActionResult.PASS, itemStackIn); } } [spoiler=Block] package com.trekkiecub.oddsandends.blocks; import java.util.Random; import com.trekkiecub.oddsandends.init.BlockInit; import com.trekkiecub.oddsandends.init.ItemInit; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class Block_Chain extends Block { public static final PropertyBool MID = PropertyBool.create("mid"); public Block_Chain(Material materialIn) { super(materialIn); this.setDefaultState(this.blockState.getBaseState().withProperty(MID, Boolean.valueOf(false))); } @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public boolean isFullCube(IBlockState state) { return false; } @SideOnly(Side.CLIENT) public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT; } @Override public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) { if (!this.canBlockStay(worldIn, pos)) { worldIn.destroyBlock(pos, true); } } @Override public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) { return state.withProperty(MID, isBottom((World) worldIn, pos)); } public boolean isBottom(World worldIn, BlockPos pos) { if (worldIn.getBlockState(pos.down()).getBlock() instanceof Block_Chain) { return false; } else { return true; } } @Override public boolean canSilkHarvest() { return false; } @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { boolean mid = state.getValue(MID); return (mid ? Items.APPLE : ItemInit.chain); } public boolean canBlockStay(World world, BlockPos pos) { if (world.getBlockState(pos.up()).getBlock() == BlockInit.chain) { return true; } else if (world.getBlockState(pos.up()).isSideSolid(world, pos, EnumFacing.DOWN)) { return true; } else { return false; } } public BlockPos canAddSegment(World worldIn, BlockPos pos) { if (worldIn.getBlockState(pos.down()).getBlock() == Blocks.AIR) { if (pos.down().getY() > 0) { return pos.down(); } else { return null; } } else if (worldIn.getBlockState(pos.down()).getBlock() instanceof Block_Chain) { return canAddSegment(worldIn, pos.down()); } else { return null; } } @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {MID}); } @Override public int getMetaFromState(IBlockState state) { return 0; } }
  8. Anyone? If I'm doing something stupid/noobish, please let me know so I can fix this.
  9. I found a tutorial that's gotten me nearly all of the way there. I just have one last problem and I'm not sure why it's happening. The problem I was having was that the block in the world was not getting updated when I modified the itemStacks in the inventory. I corrected that, or so I thought, because the tile entity correctly shows the new item when I add it. Problem is, when I remove the item, the tile entity still renders the previous item until I add a new item. It looks like the problem might be in the dropItems() function, but the code looks right to me. It's probably something simple, dumb, and/or easily overlooked, so I'm hoping someone spots what I did wrong. [spoiler=TileEntity] package com.trekkiecub.oddsandends.tileentity; import java.util.ArrayList; import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryHelper; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.DimensionManager; import com.trekkiecub.oddsandends.entity.Entity_PowerOrb; import com.trekkiecub.oddsandends.init.ItemInit; import com.trekkiecub.oddsandends.items.Item_HealingCrystal; import com.trekkiecub.oddsandends.util.OAE_Func; import com.trekkiecub.oddsandends.util.Type_CoordEntry; public class TileEntity_Sceptre extends TileEntity implements IPowerCrystal, ITickable, IInventory { private List<Type_CoordEntry> sources = new ArrayList<Type_CoordEntry>(); private List<Type_CoordEntry> destinations = new ArrayList<Type_CoordEntry>(); private ItemStack itemStacks[] = new ItemStack[1]; int cooldown = 0; int maxCooldown = 30; /** * Fetches the item to render * Null if N/A * @return The ItemStack to render */ public ItemStack getItem() { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return new ItemStack(ItemInit.gem_linarite); } else { return itemStacks[0].copy(); } } /** * Incoming Power Orb Handling */ public int getReceiverOrientation() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return Item_HealingCrystal.errorValue; } else { return ((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation(); } } /** * Outgoing Power Orb Handling */ // Positive return from this public int getPowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getItemDamage(); } } public int getInversePowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getMaxDamage(); } } private void transmitPower(Type_CoordEntry coords) { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { // do nothing } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal && itemStacks[0].getItemDamage() != itemStacks[0].getMaxDamage()) { // Only if tile entity is IPowerCrystal // powerRoom = getPowerRoom(); // If orientation is the same and we have room, send // If orientation is the same and don't have room, don't send // If orientation is opposite, send BlockPos targetPos = coords.getBlockPos(); TileEntity targetEntity = this.worldObj.getTileEntity(targetPos); if (targetEntity instanceof IPowerCrystal) { boolean canSend = false; int receiver = ((IPowerCrystal)targetEntity).getReceiverOrientation(); if (receiver == Item_HealingCrystal.errorValue) { // do nothing } // If we are able to send anything to this crystal // or the receiver is the same type as us else if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { int room = ((IPowerCrystal)targetEntity).getPowerRoom(); if (room != 0) { canSend = true; } } else { canSend = true; } if (canSend) { int energyTargetCanReceive = 0; // Restrict energy flow if needed. if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getPowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } else { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getInversePowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } int energyToSend = Math.min(energyTargetCanReceive, itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage()); // Moonstone default int orientation = 0; // Set orientation based on reciever's orientation if (this.getReceiverOrientation() == -1) { orientation = ((IPowerCrystal)targetEntity).getReceiverOrientation(); } // Set to sunstone if this is sunstone or receiver is also -1 if (this.getReceiverOrientation() == 1 || orientation == -1) { orientation = 1; } Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX() + 0.5, this.pos.getY() + 0.375, this.pos.getZ() + 0.5); entity.setOrientation(orientation); float speedMultiplier = ((Item_HealingCrystal)itemStacks[0].getItem()).getTier() * 1.5F; speedMultiplier += 1F; entity.setThrowableHeading(targetPos.getX() + 0.5 - entity.posX, targetPos.getY() + 0.375 - entity.posY, targetPos.getZ() + 0.5 - entity.posZ, 0.05F * speedMultiplier, 0); entity.setEnergy(energyToSend); entity.setDestination(targetPos); this.worldObj.spawnEntityInWorld(entity); itemStacks[0].attemptDamageItem(energyToSend, this.worldObj.rand); this.lockDest(coords.getDimension(), coords.getBlockPos()); this.markDirty(); } } } else { // Check for things like ender pearl and quantum-entangled pearls // Transmit instantly } } } /** * Update Entity */ public void updateEntity() { if (!this.worldObj.isRemote) { cooldown++; cooldown = cooldown%maxCooldown; if (cooldown == 0 && destinations.size() != 0) { // Add stuff like a power level check for (int i = 0; i < destinations.size(); i++) { if (!destinations.get(i).isLocked()) { transmitPower(destinations.get(i)); } } } markDirty(); } } /** * Clearing information */ public void dropItems() { InventoryHelper.dropInventoryItems(this.worldObj, this.pos, this); for (int i = 0; i < this.getInventoryStackLimit(); ++i) { this.setInventorySlotContents(i, null); } this.clearConnections(); } @Override public void clearConnections() { for (Type_CoordEntry entry : sources) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); } } for (Type_CoordEntry entry : destinations) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), true); } } this.sources = new ArrayList<Type_CoordEntry>(); this.destinations = new ArrayList<Type_CoordEntry>(); } /** * Source/Destination Manipulation * Possible Actions: * - Add source if it doesn't exist * - Remove source if it's in sources * - Move from destinations to sources, reversing direction */ @Override public boolean changeConnections(ItemStack linker) { boolean actionTaken = false; // Make sure the linker isn't empty if (linker.getTagCompound() != null) { // Again, make sure linker isn't empty if (linker.getTagCompound().hasKey("coords")) { // Get the coordinates in question NBTTagCompound nbt = (NBTTagCompound) linker.getTagCompound().getTag("coords"); Type_CoordEntry coords = new Type_CoordEntry(nbt); // Check if these are our own coordinates if (coords != this.getMyCoordEntry()) { TileEntity entity = this.worldObj.getTileEntity(coords.getBlockPos()); if (entity != null && entity instanceof IPowerCrystal) { // Check to see if the coordinates supplied are in the destinations // Meaning we're switching the flow direction if (destinations.contains(coords)) { // Make sure we can switch before we switch if (canWeSwitch((IPowerCrystal) entity)) { this.switchCoordFunc(coords); ((IPowerCrystal)entity).switchCoordFunc(this.getMyCoordEntry()); actionTaken = true; } } // We've repeated a previous action, so we're now undoing it else if (sources.contains(coords)) { this.removeCoords(coords, true); ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); actionTaken = true; } // We don't have these coords anywhere, this is a new connection else { this.addCoords(coords, true); ((IPowerCrystal)entity).addCoords(this.getMyCoordEntry(), false); actionTaken = true; } } } } } return actionTaken; } private boolean canWeSwitch(IPowerCrystal entity) { return this.canReceivePower() && entity.canSendPower(); } @Override public void switchCoordFunc(Type_CoordEntry coords) { if (this.destinations.contains(coords)) { destinations.remove(coords); sources.add(coords); } else { sources.remove(coords); destinations.add(coords); } markDirty(); } private Type_CoordEntry getMyCoordEntry() { return new Type_CoordEntry(this.worldObj.provider.getDimension(), this.getPos()); } public Type_CoordEntry getSourceEntry(int i) { if (i >= 0 && i < sources.size()) { return sources.get(i); } else { return null; } } public Type_CoordEntry getDestEntry(int i) { if (i >= 0 && i < destinations.size()) { return destinations.get(i); } else { return null; } } @Override public List<String> printInventory() { List<String> inventory = new ArrayList<String>(); for (int i = 0; i < this.getSizeInventory(); i++) { if (itemStacks[i] != null) { String line = "Slot " + i + ": " + itemStacks[i].getDisplayName(); inventory.add(line); } } return inventory; } @Override public List<String> printConnections() { List<String> connections = new ArrayList<String>(); if (this.canReceivePower()) { connections.add("Sources:"); for (Type_CoordEntry entry : sources) { connections.add(entry.printThis()); } } if (this.canSendPower()) { connections.add("Destinations:"); for (Type_CoordEntry entry : destinations) { connections.add(entry.printThis()); } } return connections; } @Override public boolean canSendPower() { return true; // false if empty } @Override public boolean canReceivePower() { return true; // false if empty } @Override public void removeCoords(Type_CoordEntry coords, boolean removeFromSource) { Type_CoordEntry locked = new Type_CoordEntry(coords, true); if (removeFromSource) { sources.remove(locked); sources.remove(coords); } else { destinations.remove(locked); destinations.remove(coords); } markDirty(); } @Override public void addCoords(Type_CoordEntry coords, boolean addToSource) { if (addToSource) { sources.add(coords); } else { destinations.add(coords); } markDirty(); } // // Merge the given item stack with the inventory slots either // until the stack is empty or the inventory runs out. public ItemStack mergeStack(ItemStack stack) { ItemStack returnThisStack = stack.copy(); for (int i = 0; i < getSizeInventory() && returnThisStack.stackSize > 0; i++) { // This is the maximum amount we can deposit into each slot // based on both this tile entity and the number of items // Number of items can't go above the item's max stack size // Will never be zero: First is hard-coded, second breaks loop int remainingSpace = OAE_Func.getMaxStackToAdd(this, returnThisStack, i); if (remainingSpace > 0) { if (itemStacks[i] == null) { setInventorySlotContents(i, returnThisStack.splitStack(remainingSpace)); } else if (OAE_Func.canWeStack(itemStacks[i], returnThisStack)) { itemStacks[i].stackSize += remainingSpace; returnThisStack.splitStack(remainingSpace); markDirty(); updateBlock(); } } } if (returnThisStack.stackSize == 0) { returnThisStack = null; } return returnThisStack; } @Override public void update() { updateEntity(); } @Override public String getName() { return null; } @Override public boolean hasCustomName() { return false; } @Override public int getSizeInventory() { return itemStacks.length; } @Override public ItemStack getStackInSlot(int slot) { if (slot < 0 || slot >= this.getSizeInventory()) { return null; } return this.itemStacks[slot]; } public boolean canAddPartial(ItemStack stack) { for (int i = 0; i < getSizeInventory(); i++) { if (OAE_Func.isStackEmpty(itemStacks[i])) { return true; } else if (OAE_Func.getMaxStackToAdd(this, stack, i) > 0) { return true; } } return false; } @Override public ItemStack decrStackSize(int slot, int amount) { ItemStack stack = getStackInSlot(slot); if (stack != null) { if (stack.stackSize <= amount) { setInventorySlotContents(slot, null); } else { stack = stack.splitStack(amount); if (stack.stackSize == 0) { setInventorySlotContents(slot, null); } } this.markDirty(); this.updateBlock(); } return stack; } @Override public ItemStack removeStackFromSlot(int index) { ItemStack stack = getStackInSlot(index); setInventorySlotContents(index, null); return stack; } @Override public void setInventorySlotContents(int index, ItemStack stack) { if (index >= 0 && index < this.itemStacks.length) { ItemStack newStack = null; if (!OAE_Func.isStackEmpty(stack)) { newStack = stack.copy(); if (stack.stackSize > getInventoryStackLimit()) { newStack.stackSize = getInventoryStackLimit(); } } itemStacks[index] = newStack; this.markDirty(); updateBlock(); } } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return false; } @Override public void openInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public void closeInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public boolean isItemValidForSlot(int index, ItemStack stack) { // TODO Auto-generated method stub return false; } @Override public int getField(int id) { // TODO Auto-generated method stub return 0; } @Override public void setField(int id, int value) { // TODO Auto-generated method stub } @Override public int getFieldCount() { // TODO Auto-generated method stub return 0; } @Override public void clear() { // TODO Auto-generated method stub } @Override public int acceptPower(int powerInPacket, int orientation) { // The energy left over after the orb transfers power int leftoverPower = powerInPacket; if (!this.canReceivePower()) { return leftoverPower; } // If we don't have an item to damage, don't bother trying if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return leftoverPower; } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal) { // Add a third case for orientation == -1 // If the orientation is the same, charge as much as possible if (((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation() == orientation) { int energyToTransfer = Math.min(powerInPacket, itemStacks[0].getItemDamage()); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() - energyToTransfer); this.markDirty(); leftoverPower = powerInPacket - energyToTransfer; } else // Drain energy from the stack { int remainingPossibleDamage = itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage(); int powerToDrain = Math.min(remainingPossibleDamage, powerInPacket); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() + powerToDrain); this.markDirty(); // Get how much energy we drained and subtract leftoverPower -= powerToDrain; // If we drained the crystal, break or flip orientation, then charge if (leftoverPower > 0) { // TODO Break if power crystal, flip and charge if other } } } return leftoverPower; } } @Override public void lockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis, true)); } this.markDirty(); } @Override public void unlockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos, true); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis)); } this.markDirty(); } /** * * Syncronization code * @return */ public void updateBlock() { this.worldObj.notifyBlockUpdate(this.pos, worldObj.getBlockState(pos), worldObj.getBlockState(pos), 3); } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); sources = new ArrayList<Type_CoordEntry>(); destinations = new ArrayList<Type_CoordEntry>(); if (compound.hasKey("sources")) { NBTTagList entryList = (NBTTagList) compound.getTag("sources"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); sources.add(entry); } entryList = (NBTTagList) compound.getTag("destinations"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); destinations.add(entry); } } this.cooldown = compound.getInteger("cooldown"); this.readInvFromNBT(compound); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { // Store sources under 'sources' NBTTagList entryList = new NBTTagList(); for (Type_CoordEntry entry : sources) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("sources", entryList); // Store destinations under 'destinations' entryList = new NBTTagList(); for (Type_CoordEntry entry : destinations) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("destinations", entryList); compound.setInteger("cooldown", this.cooldown); this.writeInvToNBT(compound); return super.writeToNBT(compound); } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeInvToNBT(tag); return new SPacketUpdateTileEntity(this.getPos(), 1, tag); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) { readInvFromNBT(packet.getNbtCompound()); } @Override public NBTTagCompound getUpdateTag() { NBTTagCompound tag = super.getUpdateTag(); readInvFromNBT(tag); /*( tag.setInteger("x", this.pos.getX()); tag.setInteger("y", this.pos.getY()); tag.setInteger("z", this.pos.getZ()); */ return super.getUpdateTag(); } @Override public void handleUpdateTag(NBTTagCompound tag) { super.handleUpdateTag(tag); this.readFromNBT(tag); } public void readInvFromNBT(NBTTagCompound compound) { NBTTagList entryList = (NBTTagList) compound.getTagList("Items", 10); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound stackTag = entryList.getCompoundTagAt(i); int slot = stackTag.getByte("Slot") & 255; setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(stackTag)); } } public void writeInvToNBT(NBTTagCompound compound) { // Store inventory NBTTagList tagList = new NBTTagList(); for (int i = 0; i < getSizeInventory(); i++) { if (getStackInSlot(i) != null) { NBTTagCompound slotTag = new NBTTagCompound(); slotTag.setByte("Slot", (byte)i); getStackInSlot(i).writeToNBT(slotTag); tagList.appendTag(slotTag); } } compound.setTag("Items", tagList); } }
  10. Should I put the tile entity question into a separate thread since it's sort of a separate issue?
  11. The document you referenced was somewhat helpful, but I'm still doing something wrong. Do you know of any examples or tutorials I can look at that are updated to 1.9? Better yet, can you see/explain to me what I'm doing wrong? This is my current TileEntity file. [spoiler=TileEntity] package com.trekkiecub.oddsandends.tileentity; import java.util.ArrayList; import java.util.List; 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.nbt.NBTTagList; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraftforge.common.DimensionManager; import com.trekkiecub.oddsandends.entity.Entity_PowerOrb; import com.trekkiecub.oddsandends.init.ItemInit; import com.trekkiecub.oddsandends.items.Item_HealingCrystal; import com.trekkiecub.oddsandends.util.OAE_Func; import com.trekkiecub.oddsandends.util.Type_CoordEntry; public class TileEntity_Sceptre extends TileEntity implements IPowerCrystal, ITickable, IInventory { private List<Type_CoordEntry> sources = new ArrayList<Type_CoordEntry>(); private List<Type_CoordEntry> destinations = new ArrayList<Type_CoordEntry>(); private ItemStack itemStacks[] = new ItemStack[1]; int cooldown = 0; int maxCooldown = 30; /** * Fetches the item to render * Null if N/A * @return The ItemStack to render */ @Override public NBTTagCompound getUpdateTag() { NBTTagCompound tag = super.getUpdateTag(); tag.setInteger("x", this.pos.getX()); tag.setInteger("y", this.pos.getY()); tag.setInteger("z", this.pos.getZ()); return this.writeToNBT(tag); } @Override public void handleUpdateTag(NBTTagCompound tag) { super.handleUpdateTag(tag); this.readFromNBT(tag); } public ItemStack getItem() { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return new ItemStack(ItemInit.gem_linarite); } else { return itemStacks[0].copy(); } } /** * Incoming Power Orb Handling */ public int getReceiverOrientation() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return Item_HealingCrystal.errorValue; } else { return ((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation(); } } /** * Outgoing Power Orb Handling */ // Positive return from this public int getPowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getItemDamage(); } } public int getInversePowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getMaxDamage(); } } private void transmitPower(Type_CoordEntry coords) { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { // do nothing } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal && itemStacks[0].getItemDamage() != itemStacks[0].getMaxDamage()) { // Only if tile entity is IPowerCrystal // powerRoom = getPowerRoom(); // If orientation is the same and we have room, send // If orientation is the same and don't have room, don't send // If orientation is opposite, send BlockPos targetPos = coords.getBlockPos(); TileEntity targetEntity = this.worldObj.getTileEntity(targetPos); if (targetEntity instanceof IPowerCrystal) { boolean canSend = false; int receiver = ((IPowerCrystal)targetEntity).getReceiverOrientation(); if (receiver == Item_HealingCrystal.errorValue) { // do nothing } // If we are able to send anything to this crystal // or the receiver is the same type as us else if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { int room = ((IPowerCrystal)targetEntity).getPowerRoom(); if (room != 0) { canSend = true; } } else { canSend = true; } if (canSend) { int energyTargetCanReceive = 0; // Restrict energy flow if needed. if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getPowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } else { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getInversePowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } int energyToSend = Math.min(energyTargetCanReceive, itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage()); // Moonstone default int orientation = 0; // Set orientation based on reciever's orientation if (this.getReceiverOrientation() == -1) { orientation = ((IPowerCrystal)targetEntity).getReceiverOrientation(); } // Set to sunstone if this is sunstone or receiver is also -1 if (this.getReceiverOrientation() == 1 || orientation == -1) { orientation = 1; } Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX() + 0.5, this.pos.getY() + 0.375, this.pos.getZ() + 0.5); entity.setOrientation(orientation); float speedMultiplier = ((Item_HealingCrystal)itemStacks[0].getItem()).getTier() * 1.5F; speedMultiplier += 1F; entity.setThrowableHeading(targetPos.getX() + 0.5 - entity.posX, targetPos.getY() + 0.375 - entity.posY, targetPos.getZ() + 0.5 - entity.posZ, 0.05F * speedMultiplier, 0); entity.setEnergy(energyToSend); entity.setDestination(targetPos); this.worldObj.spawnEntityInWorld(entity); itemStacks[0].attemptDamageItem(energyToSend, this.worldObj.rand); this.lockDest(coords.getDimension(), coords.getBlockPos()); } } } else { // Check for things like ender pearl and quantum-entangled pearls // Transmit instantly } } } /** * Update Entity */ public void updateEntity() { if (!this.worldObj.isRemote) { cooldown++; cooldown = cooldown%maxCooldown; if (cooldown == 0 && destinations.size() != 0) { // Add stuff like a power level check for (int i = 0; i < destinations.size(); i++) { if (!destinations.get(i).isLocked()) { transmitPower(destinations.get(i)); } } } markDirty(); } } /** * Clearing information * REPLACE dropItems functionality with InventoryHelper.drop */ public void dropItems() { if (!this.worldObj.isRemote) { for (int i = 0; i < this.getInventoryStackLimit(); ++i) { if (itemStacks[i] != null) { Vec3d center = OAE_Func.blockCenter(this.pos); EntityItem entity = new EntityItem(worldObj, center.xCoord, center.yCoord, center.zCoord, itemStacks[i].copy()); entity.motionY = 0; this.worldObj.spawnEntityInWorld(entity); this.setInventorySlotContents(i, null); this.clearConnections(); } } } } @Override public void clearConnections() { for (Type_CoordEntry entry : sources) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); } } for (Type_CoordEntry entry : destinations) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), true); } } this.sources = new ArrayList<Type_CoordEntry>(); this.destinations = new ArrayList<Type_CoordEntry>(); } /** * Source/Destination Manipulation * Possible Actions: * - Add source if it doesn't exist * - Remove source if it's in sources * - Move from destinations to sources, reversing direction */ @Override public boolean changeConnections(ItemStack linker) { boolean actionTaken = false; // Make sure the linker isn't empty if (linker.getTagCompound() != null) { // Again, make sure linker isn't empty if (linker.getTagCompound().hasKey("coords")) { // Get the coordinates in question NBTTagCompound nbt = (NBTTagCompound) linker.getTagCompound().getTag("coords"); Type_CoordEntry coords = new Type_CoordEntry(nbt); // Check if these are our own coordinates if (coords != this.getMyCoordEntry()) { TileEntity entity = this.worldObj.getTileEntity(coords.getBlockPos()); if (entity != null && entity instanceof IPowerCrystal) { // Check to see if the coordinates supplied are in the destinations // Meaning we're switching the flow direction if (destinations.contains(coords)) { // Make sure we can switch before we switch if (canWeSwitch((IPowerCrystal) entity)) { this.switchCoordFunc(coords); ((IPowerCrystal)entity).switchCoordFunc(this.getMyCoordEntry()); actionTaken = true; } } // We've repeated a previous action, so we're now undoing it else if (sources.contains(coords)) { this.removeCoords(coords, true); ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); actionTaken = true; } // We don't have these coords anywhere, this is a new connection else { this.addCoords(coords, true); ((IPowerCrystal)entity).addCoords(this.getMyCoordEntry(), false); actionTaken = true; } } } } } return actionTaken; } private boolean canWeSwitch(IPowerCrystal entity) { return this.canReceivePower() && entity.canSendPower(); } @Override public void switchCoordFunc(Type_CoordEntry coords) { if (this.destinations.contains(coords)) { destinations.remove(coords); sources.add(coords); } else { sources.remove(coords); destinations.add(coords); } } private Type_CoordEntry getMyCoordEntry() { return new Type_CoordEntry(this.worldObj.provider.getDimension(), this.getPos()); } public Type_CoordEntry getSourceEntry(int i) { if (i >= 0 && i < sources.size()) { return sources.get(i); } else { return null; } } public Type_CoordEntry getDestEntry(int i) { if (i >= 0 && i < destinations.size()) { return destinations.get(i); } else { return null; } } @Override public List<String> printInventory() { List<String> inventory = new ArrayList<String>(); for (int i = 0; i < this.getSizeInventory(); i++) { if (itemStacks[i] != null) { String line = "Slot " + i + ": " + itemStacks[i].getDisplayName(); inventory.add(line); } } return inventory; } @Override public List<String> printConnections() { List<String> connections = new ArrayList<String>(); if (this.canReceivePower()) { connections.add("Sources:"); for (Type_CoordEntry entry : sources) { connections.add(entry.printThis()); } } if (this.canSendPower()) { connections.add("Destinations:"); for (Type_CoordEntry entry : destinations) { connections.add(entry.printThis()); } } return connections; } @Override public boolean canSendPower() { return true; // false if empty } @Override public boolean canReceivePower() { return true; // false if empty } @Override public void removeCoords(Type_CoordEntry coords, boolean removeFromSource) { Type_CoordEntry locked = new Type_CoordEntry(coords, true); if (removeFromSource) { sources.remove(locked); sources.remove(coords); } else { destinations.remove(locked); destinations.remove(coords); } markDirty(); } @Override public void addCoords(Type_CoordEntry coords, boolean addToSource) { if (addToSource) { sources.add(coords); } else { destinations.add(coords); } markDirty(); } // // Merge the given item stack with the inventory slots either // until the stack is empty or the inventory runs out. public ItemStack mergeStack(ItemStack stack) { ItemStack returnThisStack = stack.copy(); for (int i = 0; i < getSizeInventory() && returnThisStack.stackSize > 0; i++) { // This is the maximum amount we can deposit into each slot // based on both this tile entity and the number of items // Number of items can't go above the item's max stack size // Will never be zero: First is hard-coded, second breaks loop int remainingSpace = OAE_Func.getMaxStackToAdd(this, returnThisStack, i); if (remainingSpace > 0) { if (itemStacks[i] == null) { setInventorySlotContents(i, returnThisStack.splitStack(remainingSpace)); } else if (OAE_Func.canWeStack(itemStacks[i], returnThisStack)) { itemStacks[i].stackSize += remainingSpace; returnThisStack.splitStack(remainingSpace); markDirty(); } } } if (returnThisStack.stackSize == 0) { returnThisStack = null; } return returnThisStack; } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); sources = new ArrayList<Type_CoordEntry>(); destinations = new ArrayList<Type_CoordEntry>(); if (compound.hasKey("sources")) { NBTTagList entryList = (NBTTagList) compound.getTag("sources"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); sources.add(entry); } entryList = (NBTTagList) compound.getTag("destinations"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); destinations.add(entry); } this.cooldown = compound.getInteger("cooldown"); entryList = (NBTTagList) compound.getTagList("Items", 10); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound stackTag = entryList.getCompoundTagAt(i); int slot = stackTag.getByte("Slot") & 255; setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(stackTag)); } } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { // Store sources under 'sources' NBTTagList entryList = new NBTTagList(); for (Type_CoordEntry entry : sources) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("sources", entryList); // Store destinations under 'destinations' entryList = new NBTTagList(); for (Type_CoordEntry entry : destinations) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("destinations", entryList); compound.setInteger("cooldown", this.cooldown); // Store inventory NBTTagList tagList = new NBTTagList(); for (int i = 0; i < getSizeInventory(); i++) { if (getStackInSlot(i) != null) { NBTTagCompound slotTag = new NBTTagCompound(); slotTag.setByte("Slot", (byte)i); getStackInSlot(i).writeToNBT(slotTag); tagList.appendTag(slotTag); } } compound.setTag("Items", tagList); return super.writeToNBT(compound); } @Override public void update() { updateEntity(); } @Override public String getName() { return null; } @Override public boolean hasCustomName() { return false; } @Override public int getSizeInventory() { return itemStacks.length; } @Override public ItemStack getStackInSlot(int slot) { if (slot < 0 || slot >= this.getSizeInventory()) { return null; } return this.itemStacks[slot]; } public boolean canAddPartial(ItemStack stack) { for (int i = 0; i < getSizeInventory(); i++) { if (OAE_Func.isStackEmpty(itemStacks[i])) { return true; } else if (OAE_Func.getMaxStackToAdd(this, stack, i) > 0) { return true; } } return false; } @Override public ItemStack decrStackSize(int slot, int amount) { ItemStack stack = getStackInSlot(slot); if (stack != null) { if (stack.stackSize <= amount) { setInventorySlotContents(slot, null); this.markDirty(); } else { stack = stack.splitStack(amount); if (stack.stackSize == 0) { setInventorySlotContents(slot, null); } this.markDirty(); } } return stack; } @Override public ItemStack removeStackFromSlot(int index) { ItemStack stack = getStackInSlot(index); setInventorySlotContents(index, null); return stack; } @Override public void setInventorySlotContents(int index, ItemStack stack) { if (index >= 0 && index < this.itemStacks.length) { ItemStack newStack = null; if (!OAE_Func.isStackEmpty(stack)) { newStack = stack.copy(); if (stack.stackSize > getInventoryStackLimit()) { newStack.stackSize = getInventoryStackLimit(); } } itemStacks[index] = newStack; this.markDirty(); } } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return false; } @Override public void openInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public void closeInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public boolean isItemValidForSlot(int index, ItemStack stack) { // TODO Auto-generated method stub return false; } @Override public int getField(int id) { // TODO Auto-generated method stub return 0; } @Override public void setField(int id, int value) { // TODO Auto-generated method stub } @Override public int getFieldCount() { // TODO Auto-generated method stub return 0; } @Override public void clear() { // TODO Auto-generated method stub } @Override public int acceptPower(int powerInPacket, int orientation) { // The energy left over after the orb transfers power int leftoverPower = powerInPacket; if (!this.canReceivePower()) { return leftoverPower; } // If we don't have an item to damage, don't bother trying if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return leftoverPower; } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal) { // Add a third case for orientation == -1 // If the orientation is the same, charge as much as possible if (((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation() == orientation) { int energyToTransfer = Math.min(powerInPacket, itemStacks[0].getItemDamage()); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() - energyToTransfer); leftoverPower = powerInPacket - energyToTransfer; } else // Drain energy from the stack { int remainingPossibleDamage = itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage(); int powerToDrain = Math.min(remainingPossibleDamage, powerInPacket); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() + powerToDrain); // Get how much energy we drained and subtract leftoverPower -= powerToDrain; // If we drained the crystal, break or flip orientation, then charge if (leftoverPower > 0) { // TODO Break if power crystal, flip and charge if other } } } return leftoverPower; } } @Override public void lockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis, true)); } } @Override public void unlockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos, true); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis)); } } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeToNBT(tag); return new SPacketUpdateTileEntity(this.getPos(), 1, tag); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) { this.readFromNBT(packet.getNbtCompound()); } }
  12. I've got this working almost perfectly. By that, I mean the process of rendering an item is now complete. The problem I'm having now smells like a client/server sync issue, but I'm not entirely sure. My render code runs a getItem() method in my tile entity, which should return the first item in the inventory. Even after right-clicking to add an item, it either still thinks the first item slot is empty or I'm not correctly updating the renderer when the item slot changes. I'm fairly sure the item slot is not empty as I can right-click to remove the item and the tile entities stop spawning power orbs when their item's damage hits is max damage value. Either somehow the entity stuff is working while the client and server aren't syncing or I'm failing to tell the renderer to update based on the tile entity's changed data. [spoiler=Renderer] package com.trekkiecub.oddsandends.render; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import com.trekkiecub.oddsandends.items.Item_Crystal; import com.trekkiecub.oddsandends.tileentity.TileEntity_Sceptre; public class RenderTileSceptre extends TileEntitySpecialRenderer<TileEntity_Sceptre> { private static final ResourceLocation TEX_SCEPTRE = new ResourceLocation("tc_oae:textures/blocks/sceptre_top.png"); private final Minecraft mc = Minecraft.getMinecraft(); private final ModelResourceLocation sceptreModel = new ModelResourceLocation("tc_oae:sceptre_top"); private final RenderItem itemRenderer; public RenderTileSceptre(RenderItem itemRend) { this.itemRenderer = itemRend; } @Override public void renderTileEntityAt(TileEntity_Sceptre te, double x, double y, double z, float partialTicks, int destroyStage) { GlStateManager.pushAttrib(); GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); GlStateManager.disableRescaleNormal(); this.renderItem(te, true); this.renderItem(te, false); GlStateManager.popMatrix(); GlStateManager.popAttrib(); } private void renderItem(TileEntity_Sceptre sceptre, boolean firstPass) { ItemStack stack = sceptre.getItem(); if (stack != null) { RenderHelper.enableStandardItemLighting(); GlStateManager.enableLighting(); GlStateManager.pushMatrix(); GlStateManager.translate(0.5, 0.5, 0.5); GlStateManager.scale(0.4f, 0.4f, 0.4f); if (firstPass) { GlStateManager.rotate(45, 0, 1, 0); } else { GlStateManager.rotate(-45, 0, 1, 0); } // Rotate Along X if needed if (stack.getItem() instanceof Item_Crystal) { if (((Item_Crystal)stack.getItem()).getRotate()) { GlStateManager.rotate(45,0,0,1); } } Minecraft.getMinecraft().getRenderItem().renderItem(stack, ItemCameraTransforms.TransformType.NONE); GlStateManager.popMatrix(); } } } [spoiler=Tile Entity] package com.trekkiecub.oddsandends.tileentity; import java.util.ArrayList; import java.util.List; 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.nbt.NBTTagList; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import com.trekkiecub.oddsandends.entity.Entity_PowerOrb; import com.trekkiecub.oddsandends.init.ItemInit; import com.trekkiecub.oddsandends.items.Item_Crystal; import com.trekkiecub.oddsandends.items.Item_HealingCrystal; import com.trekkiecub.oddsandends.util.OAE_Func; import com.trekkiecub.oddsandends.util.Type_CoordEntry; public class TileEntity_Sceptre extends TileEntity implements IPowerCrystal, ITickable, IInventory { private List<Type_CoordEntry> sources = new ArrayList<Type_CoordEntry>(); private List<Type_CoordEntry> destinations = new ArrayList<Type_CoordEntry>(); private ItemStack itemStacks[] = new ItemStack[1]; int cooldown = 0; int maxCooldown = 30; /** * Fetches the item to render * Null if N/A * @return The ItemStack to render */ public ItemStack getItem() { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return new ItemStack(ItemInit.gem_anatase); } else { return itemStacks[0].copy(); } } /** * Incoming Power Orb Handling */ public int getReceiverOrientation() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return Item_HealingCrystal.errorValue; } else { return ((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation(); } } /** * Outgoing Power Orb Handling */ // Positive return from this public int getPowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getItemDamage(); } } public int getInversePowerRoom() { if (this.itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return 0; } else { return itemStacks[0].getMaxDamage(); } } private void transmitPower(Type_CoordEntry coords) { if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { // do nothing } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal && itemStacks[0].getItemDamage() != itemStacks[0].getMaxDamage()) { // Only if tile entity is IPowerCrystal // powerRoom = getPowerRoom(); // If orientation is the same and we have room, send // If orientation is the same and don't have room, don't send // If orientation is opposite, send BlockPos targetPos = coords.getBlockPos(); TileEntity targetEntity = this.worldObj.getTileEntity(targetPos); if (targetEntity instanceof IPowerCrystal) { boolean canSend = false; int receiver = ((IPowerCrystal)targetEntity).getReceiverOrientation(); if (receiver == Item_HealingCrystal.errorValue) { // do nothing } // If we are able to send anything to this crystal // or the receiver is the same type as us else if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { int room = ((IPowerCrystal)targetEntity).getPowerRoom(); if (room != 0) { canSend = true; } } else { canSend = true; } if (canSend) { int energyTargetCanReceive = 0; // Restrict energy flow if needed. if (receiver == -1 || receiver-this.getReceiverOrientation() == 0) { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getPowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } else { energyTargetCanReceive = Math.min(((IPowerCrystal)targetEntity).getInversePowerRoom(), ((Item_HealingCrystal)itemStacks[0].getItem()).maxPacketSize()); } int energyToSend = Math.min(energyTargetCanReceive, itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage()); // Moonstone default int orientation = 0; // Set orientation based on reciever's orientation if (this.getReceiverOrientation() == -1) { orientation = ((IPowerCrystal)targetEntity).getReceiverOrientation(); } // Set to sunstone if this is sunstone or receiver is also -1 if (this.getReceiverOrientation() == 1 || orientation == -1) { orientation = 1; } Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX() + 0.5, this.pos.getY() + 0.375, this.pos.getZ() + 0.5); entity.setOrientation(orientation); float speedMultiplier = ((Item_HealingCrystal)itemStacks[0].getItem()).getTier() * 1.5F; speedMultiplier += 1F; entity.setThrowableHeading(targetPos.getX() + 0.5 - entity.posX, targetPos.getY() + 0.375 - entity.posY, targetPos.getZ() + 0.5 - entity.posZ, 0.05F * speedMultiplier, 0); entity.setEnergy(energyToSend); entity.setDestination(targetPos); this.worldObj.spawnEntityInWorld(entity); itemStacks[0].attemptDamageItem(energyToSend, this.worldObj.rand); this.lockDest(coords.getDimension(), coords.getBlockPos()); } } } else { // Check for things like ender pearl and quantum-entangled pearls // Transmit instantly } } } /** * Update Entity */ public void updateEntity() { if (!this.worldObj.isRemote) { cooldown++; cooldown = cooldown%maxCooldown; if (cooldown == 0 && destinations.size() != 0) { // Add stuff like a power level check for (int i = 0; i < destinations.size(); i++) { if (!destinations.get(i).isLocked()) { transmitPower(destinations.get(i)); } } } markDirty(); } } /** * Clearing information * REPLACE dropItems functionality with InventoryHelper.drop */ public void dropItems() { if (!this.worldObj.isRemote) { for (int i = 0; i < this.getInventoryStackLimit(); ++i) { if (itemStacks[i] != null) { Vec3d center = OAE_Func.blockCenter(this.pos); EntityItem entity = new EntityItem(worldObj, center.xCoord, center.yCoord, center.zCoord, itemStacks[i].copy()); entity.motionY = 0; this.worldObj.spawnEntityInWorld(entity); this.setInventorySlotContents(i, null); this.clearConnections(); } } } } @Override public void clearConnections() { for (Type_CoordEntry entry : sources) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); } } for (Type_CoordEntry entry : destinations) { TileEntity entity = DimensionManager.getWorld(entry.getDimension()).getTileEntity(entry.getBlockPos()); if (entity instanceof IPowerCrystal) { ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), true); } } this.sources = new ArrayList<Type_CoordEntry>(); this.destinations = new ArrayList<Type_CoordEntry>(); } /** * Source/Destination Manipulation * Possible Actions: * - Add source if it doesn't exist * - Remove source if it's in sources * - Move from destinations to sources, reversing direction */ @Override public boolean changeConnections(ItemStack linker) { boolean actionTaken = false; // Make sure the linker isn't empty if (linker.getTagCompound() != null) { // Again, make sure linker isn't empty if (linker.getTagCompound().hasKey("coords")) { // Get the coordinates in question NBTTagCompound nbt = (NBTTagCompound) linker.getTagCompound().getTag("coords"); Type_CoordEntry coords = new Type_CoordEntry(nbt); // Check if these are our own coordinates if (coords != this.getMyCoordEntry()) { TileEntity entity = this.worldObj.getTileEntity(coords.getBlockPos()); if (entity != null && entity instanceof IPowerCrystal) { // Check to see if the coordinates supplied are in the destinations // Meaning we're switching the flow direction if (destinations.contains(coords)) { // Make sure we can switch before we switch if (canWeSwitch((IPowerCrystal) entity)) { this.switchCoordFunc(coords); ((IPowerCrystal)entity).switchCoordFunc(this.getMyCoordEntry()); actionTaken = true; } } // We've repeated a previous action, so we're now undoing it else if (sources.contains(coords)) { this.removeCoords(coords, true); ((IPowerCrystal)entity).removeCoords(this.getMyCoordEntry(), false); actionTaken = true; } // We don't have these coords anywhere, this is a new connection else { this.addCoords(coords, true); ((IPowerCrystal)entity).addCoords(this.getMyCoordEntry(), false); actionTaken = true; } } } } } return actionTaken; } private boolean canWeSwitch(IPowerCrystal entity) { return this.canReceivePower() && entity.canSendPower(); } @Override public void switchCoordFunc(Type_CoordEntry coords) { if (this.destinations.contains(coords)) { destinations.remove(coords); sources.add(coords); } else { sources.remove(coords); destinations.add(coords); } } private Type_CoordEntry getMyCoordEntry() { return new Type_CoordEntry(this.worldObj.provider.getDimension(), this.getPos()); } public Type_CoordEntry getSourceEntry(int i) { if (i >= 0 && i < sources.size()) { return sources.get(i); } else { return null; } } public Type_CoordEntry getDestEntry(int i) { if (i >= 0 && i < destinations.size()) { return destinations.get(i); } else { return null; } } @Override public List<String> printInventory() { List<String> inventory = new ArrayList<String>(); for (int i = 0; i < this.getSizeInventory(); i++) { if (itemStacks[i] != null) { String line = "Slot " + i + ": " + itemStacks[i].getDisplayName(); inventory.add(line); } } return inventory; } @Override public List<String> printConnections() { List<String> connections = new ArrayList<String>(); if (this.canReceivePower()) { connections.add("Sources:"); for (Type_CoordEntry entry : sources) { connections.add(entry.printThis()); } } if (this.canSendPower()) { connections.add("Destinations:"); for (Type_CoordEntry entry : destinations) { connections.add(entry.printThis()); } } return connections; } @Override public boolean canSendPower() { return true; // false if empty } @Override public boolean canReceivePower() { return true; // false if empty } @Override public void removeCoords(Type_CoordEntry coords, boolean removeFromSource) { Type_CoordEntry locked = new Type_CoordEntry(coords, true); if (removeFromSource) { sources.remove(locked); sources.remove(coords); } else { destinations.remove(locked); destinations.remove(coords); } markDirty(); } @Override public void addCoords(Type_CoordEntry coords, boolean addToSource) { if (addToSource) { sources.add(coords); } else { destinations.add(coords); } markDirty(); } // // Merge the given item stack with the inventory slots either // until the stack is empty or the inventory runs out. public ItemStack mergeStack(ItemStack stack) { ItemStack returnThisStack = stack.copy(); for (int i = 0; i < getSizeInventory() && returnThisStack.stackSize > 0; i++) { // This is the maximum amount we can deposit into each slot // based on both this tile entity and the number of items // Number of items can't go above the item's max stack size // Will never be zero: First is hard-coded, second breaks loop int remainingSpace = OAE_Func.getMaxStackToAdd(this, returnThisStack, i); if (remainingSpace > 0) { if (itemStacks[i] == null) { setInventorySlotContents(i, returnThisStack.splitStack(remainingSpace)); } else if (OAE_Func.canWeStack(itemStacks[i], returnThisStack)) { itemStacks[i].stackSize += remainingSpace; returnThisStack.splitStack(remainingSpace); markDirty(); } } } if (returnThisStack.stackSize == 0) { returnThisStack = null; } return returnThisStack; } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); sources = new ArrayList<Type_CoordEntry>(); destinations = new ArrayList<Type_CoordEntry>(); if (compound.hasKey("sources")) { NBTTagList entryList = (NBTTagList) compound.getTag("sources"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); sources.add(entry); } entryList = (NBTTagList) compound.getTag("destinations"); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound entryCompound = entryList.getCompoundTagAt(i); Type_CoordEntry entry = Type_CoordEntry.readEntryFromNBT(entryCompound); destinations.add(entry); } this.cooldown = compound.getInteger("cooldown"); entryList = (NBTTagList) compound.getTagList("Items", 10); for (int i = 0; i < entryList.tagCount(); i++) { NBTTagCompound stackTag = entryList.getCompoundTagAt(i); int slot = stackTag.getByte("Slot") & 255; setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(stackTag)); } } } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { // Store sources under 'sources' NBTTagList entryList = new NBTTagList(); for (Type_CoordEntry entry : sources) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("sources", entryList); // Store destinations under 'destinations' entryList = new NBTTagList(); for (Type_CoordEntry entry : destinations) { NBTTagCompound entryCompound = new NBTTagCompound(); entry.writeToNBT(entryCompound); entryList.appendTag(entryCompound); } compound.setTag("destinations", entryList); compound.setInteger("cooldown", this.cooldown); // Store inventory NBTTagList tagList = new NBTTagList(); for (int i = 0; i < getSizeInventory(); i++) { if (getStackInSlot(i) != null) { NBTTagCompound slotTag = new NBTTagCompound(); slotTag.setByte("Slot", (byte)i); getStackInSlot(i).writeToNBT(slotTag); tagList.appendTag(slotTag); } } compound.setTag("Items", tagList); return super.writeToNBT(compound); } @Override public void update() { updateEntity(); } @Override public String getName() { return null; } @Override public boolean hasCustomName() { return false; } @Override public int getSizeInventory() { return itemStacks.length; } @Override public ItemStack getStackInSlot(int slot) { if (slot < 0 || slot >= this.getSizeInventory()) { return null; } return this.itemStacks[slot]; } public boolean canAddPartial(ItemStack stack) { for (int i = 0; i < getSizeInventory(); i++) { if (OAE_Func.isStackEmpty(itemStacks[i])) { return true; } else if (OAE_Func.getMaxStackToAdd(this, stack, i) > 0) { return true; } } return false; } @Override public ItemStack decrStackSize(int slot, int amount) { ItemStack stack = getStackInSlot(slot); if (stack != null) { if (stack.stackSize <= amount) { setInventorySlotContents(slot, null); this.markDirty(); } else { stack = stack.splitStack(amount); if (stack.stackSize == 0) { setInventorySlotContents(slot, null); } this.markDirty(); } } return stack; } @Override public ItemStack removeStackFromSlot(int index) { ItemStack stack = getStackInSlot(index); setInventorySlotContents(index, null); return stack; } @Override public void setInventorySlotContents(int index, ItemStack stack) { if (index >= 0 && index < this.itemStacks.length) { ItemStack newStack = null; if (!OAE_Func.isStackEmpty(stack)) { newStack = stack.copy(); if (stack.stackSize > getInventoryStackLimit()) { newStack.stackSize = getInventoryStackLimit(); } } itemStacks[index] = newStack; this.markDirty(); } } @Override public int getInventoryStackLimit() { return 1; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return false; } @Override public void openInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public void closeInventory(EntityPlayer player) { // TODO Auto-generated method stub } @Override public boolean isItemValidForSlot(int index, ItemStack stack) { // TODO Auto-generated method stub return false; } @Override public int getField(int id) { // TODO Auto-generated method stub return 0; } @Override public void setField(int id, int value) { // TODO Auto-generated method stub } @Override public int getFieldCount() { // TODO Auto-generated method stub return 0; } @Override public void clear() { // TODO Auto-generated method stub } @Override public int acceptPower(int powerInPacket, int orientation) { // The energy left over after the orb transfers power int leftoverPower = powerInPacket; if (!this.canReceivePower()) { return leftoverPower; } // If we don't have an item to damage, don't bother trying if (itemStacks == null || OAE_Func.isStackEmpty(itemStacks[0])) { return leftoverPower; } else { if (itemStacks[0].getItem() instanceof Item_HealingCrystal) { // Add a third case for orientation == -1 // If the orientation is the same, charge as much as possible if (((Item_HealingCrystal)itemStacks[0].getItem()).getOrientation() == orientation) { int energyToTransfer = Math.min(powerInPacket, itemStacks[0].getItemDamage()); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() - energyToTransfer); leftoverPower = powerInPacket - energyToTransfer; } else // Drain energy from the stack { int remainingPossibleDamage = itemStacks[0].getMaxDamage() - itemStacks[0].getItemDamage(); int powerToDrain = Math.min(remainingPossibleDamage, powerInPacket); itemStacks[0].setItemDamage(itemStacks[0].getItemDamage() + powerToDrain); // Get how much energy we drained and subtract leftoverPower -= powerToDrain; // If we drained the crystal, break or flip orientation, then charge if (leftoverPower > 0) { // TODO Break if power crystal, flip and charge if other } } } return leftoverPower; } } @Override public void lockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis, true)); } } @Override public void unlockDest(int dimension, BlockPos pos) { Type_CoordEntry findThis = new Type_CoordEntry(dimension, pos, true); int index = destinations.indexOf(findThis); if (index != -1) { destinations.set(index, new Type_CoordEntry(findThis)); } } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeToNBT(tag); return new SPacketUpdateTileEntity(this.getPos(), 1, tag); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) { this.readFromNBT(packet.getNbtCompound()); } }
  13. What I tried to do didn't work for the green textures, but then again, I have very little experience with OpenGL and I'm not sure what specific bit of code you were asking me to write. I noticed that the textures only flash green if I'm looking in front of me. If I'm looking down (less than a 45 degree angle from directly down), the texture usually shows up fine, even if I move around. Don't know if this will help or not.
  14. I used the line GlStateManager.color(1,1,1) and it didn't work. I'm guessing I misinterpreted what you were telling me to do. Also, was that suggestion to fix the items not showing up or the green textures?
×
×
  • Create New...

Important Information

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