Jump to content

TrekkieCub314

Members
  • Posts

    68
  • Joined

  • Last visited

Everything posted by TrekkieCub314

  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?
  15. After looking at the rendering code for the item frame, I think I'm close to getting this to work. The problem I'm having right now is the textures for the tile entity look green most of the time (they occasionally show up correctly, but if I move the cursor or the player, it usually reverts to the solid green look). Also, my items aren't showing up. Can anyone tell me what I might need to do? [spoiler=Renderer] package com.trekkiecub.oddsandends.render; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BlockRendererDispatcher; 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.IBakedModel; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ModelManager; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import com.trekkiecub.oddsandends.tileentity.TileEntity_Sceptre; public class RenderTileSceptre extends TileEntitySpecialRenderer { 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 te, double x, double y, double z, float partialTick, int destroyStage) { GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); // Bind texture //this.rendererDispatcher.renderEngine.bindTexture(TEX_SCEPTRE); BlockRendererDispatcher blockrendererdispatcher = this.mc.getBlockRendererDispatcher(); ModelManager modelmanager = blockrendererdispatcher.getBlockModelShapes().getModelManager(); // Get the model from the ModelLocation IBakedModel ibakedmodel = modelmanager.getModel(this.sceptreModel); TileEntity_Sceptre powerTile = (TileEntity_Sceptre)te; // Translation, not sure why GlStateManager.pushMatrix(); //GlStateManager.translate(-0.5, -0.5, -0.5); // Render the block model blockrendererdispatcher.getBlockModelRenderer().renderModelBrightnessColor(ibakedmodel, 1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.popMatrix(); this.renderItem(powerTile); GlStateManager.popMatrix(); } private void renderItem(TileEntity_Sceptre sceptre) { ItemStack stack = sceptre.getItem(); if (stack != null) { EntityItem entityitem = new EntityItem(sceptre.getWorld(), sceptre.getPos().getX(), sceptre.getPos().getY(), sceptre.getPos().getZ(), stack); Item item = entityitem.getEntityItem().getItem(); entityitem.getEntityItem().stackSize = 1; entityitem.hoverStart = 0; GlStateManager.pushMatrix(); GlStateManager.disableLighting(); // Actual rendering codeish GlStateManager.scale(0.5, 0.5, 0.5); GlStateManager.pushAttrib(); RenderHelper.enableStandardItemLighting(); this.itemRenderer.renderItem(entityitem.getEntityItem(), ItemCameraTransforms.TransformType.FIXED); RenderHelper.disableStandardItemLighting(); GlStateManager.popAttrib(); // Reset Stuff GlStateManager.enableLighting(); GlStateManager.popMatrix(); } } }
  16. Depends on what you're trying to do with the block. Will this be a regular block (doesn't store items or have changing textures) with an item overlaid on the block or are you wanting something more complex?
  17. My first attempt at manually rendering a block was a massive fail. I'm trying to look at the vanilla model and renderer classes to figure out if there's some way to use json models to do what I'm wanting.
  18. OpenGL coding is something I've had very little experience with. Maybe if I let you know exactly what I'm trying to do, I can be pointed in the right direction. I have a block whose model has block/cross as its parent. What I'm trying to do is change the texture of the block such that the texture of the item is overlaid on the block texture, then the new texture is rendered in the form of a cross. I *might* have been able to figure out how to do this in 1.7.2, but exactly how models are used and rendering in general is confusing for me. Can anyone either explain how I can accomplish what I want or point me to a tutorial that can help me? I know I could theoretically accomplish something similar with an entity, but if I can change how the block renders rather than spawning a new entity, I'd prefer that.
  19. I have a block with a tile entity that can store an item. I'd like to update the texture of the block so that it will overlay a shrunken-down and possibly rotated image of the item stored in its tile entity. I think I knew how to do this in 1.7. Does anyone know how I would go about doing so in 1.10?
  20. I've got a block where, upon right-clicking it with the right kind of item, is supposed to store one of said item in an internal inventory. If I right-click it with an empty hand, however, it's supposed to drop the item into the world and clear the internal inventory. The problem I'm having is when I right-click on the block, the item is immediately ejected from the tile entity. I tried wrapping the guts of the onBlockActivated in a !world.isRemote check, but that doesn't seem to have helped. Can anyone see what I might be doing wrong? [spoiler=block] package com.trekkiecub.oddsandends.blocks; import java.util.Random; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import com.trekkiecub.oddsandends.init.BlockInit; import com.trekkiecub.oddsandends.init.ItemInit; import com.trekkiecub.oddsandends.items.Item_HealingCrystal; import com.trekkiecub.oddsandends.tileentity.TileEntity_Sceptre; import com.trekkiecub.oddsandends.util.OAE_Func; public class Block_Sceptre_Top extends Block_BeamPowered implements ITileEntityProvider { protected static final AxisAlignedBB CACTUS_AABB = new AxisAlignedBB(0.375, 0.0D, 0.375D, 0.625D, .75D, 0.625D); protected static final AxisAlignedBB CACTUS_COLLISION_AABB = new AxisAlignedBB(0.375, 0.0D, 0.375D, 0.625D, .75D, 0.625D); public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, World worldIn, BlockPos pos) { return CACTUS_AABB; } @SideOnly(Side.CLIENT) public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World worldIn, BlockPos pos) { return CACTUS_COLLISION_AABB.offset(pos); } public Block_Sceptre_Top() { super(Material.CIRCUITS); } @Override public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntity tile = worldIn.getTileEntity(pos); if (tile != null && tile instanceof TileEntity_Sceptre) { ((TileEntity_Sceptre)tile).dropItems(); } } public boolean isOpaqueCube(IBlockState state) { return false; } @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, @Nullable ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) { TileEntity_Sceptre thisTile = (TileEntity_Sceptre) worldIn.getTileEntity(pos); if (thisTile != null) { if (!OAE_Func.isStackEmpty(heldItem)) { if (heldItem.getItem() instanceof Item_HealingCrystal) { if (thisTile.canAddPartial(heldItem)) { ItemStack remaining = thisTile.mergeStack(heldItem.copy()); playerIn.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, remaining); OAE_Func.chatAtPlayer(playerIn, "Can Add"); return true; } } } else { thisTile.dropItems(); } } } return false; } public boolean isFullCube(IBlockState state) { return false; } @SideOnly(Side.CLIENT) public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT; } public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn) { if (!this.canBlockStay(worldIn, pos)) { worldIn.destroyBlock(pos, true); } } public boolean canBlockStay(World world, BlockPos pos) { if (world.getBlockState(pos.down()) == BlockInit.sceptre_bottom.getDefaultState()) { return true; } else { return false; } } public Item getItemDropped(IBlockState state, Random rand, int fortune) { return ItemInit.sceptre; } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntity_Sceptre(); } } [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.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import com.trekkiecub.oddsandends.entity.Entity_PowerOrb; 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; public void updateEntity() { if (!this.worldObj.isRemote) { cooldown++; cooldown = cooldown%maxCooldown; if (cooldown == 0 && destinations.size() != 0) { BlockPos targetPos; for (int i = 0; i < destinations.size(); i++) { targetPos = destinations.get(i).getBlockPos(); Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX()+.5, this.pos.getY()+.375, this.pos.getZ()+.5); entity.setOrientation(this.worldObj.rand.nextInt(2)); entity.setThrowableHeading(targetPos.getX() + .5 - entity.posX, targetPos.getY() + .375 - entity.posY, targetPos.getZ() + .5 - entity.posZ, 0.05F, 0); this.worldObj.spawnEntityInWorld(entity); } } markDirty(); } } public void doThings(int orientation) { if (orientation == 1) { Vec3d center = OAE_Func.blockCenter(this.pos); EntityItem entity = new EntityItem(worldObj, center.xCoord, center.yCoord, center.zCoord, new ItemStack(Items.APPLE)); this.worldObj.spawnEntityInWorld(entity); } } 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()); this.worldObj.spawnEntityInWorld(entity); this.setInventorySlotContents(i, null); } } } } /* Bringing in new source coordinates Possible Actions: -- Add source, if it doesn't exist -- Remove source, if it's in sources -- Move from destinations to sources, to switch flow */ @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; } } // On deletion of tile entity, tell all source entries to delete our coordinates // from their destination lists // Tell all destination entries to delete our coordinates in the sources list @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) { if (removeFromSource) { sources.remove(coords); } else { destinations.remove(coords); } } @Override public void addCoords(Type_CoordEntry coords, boolean addToSource) { if (addToSource) { sources.add(coords); } else { destinations.add(coords); } } // // 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 } } [spoiler=helper functions] package com.trekkiecub.oddsandends.util; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; import net.minecraft.util.text.TextComponentString; public class OAE_Func { public static String truncUL(Object object) { if (object instanceof Block) { return ((Block) object).getUnlocalizedName().substring(5); } else { return ((Item) object).getUnlocalizedName().substring(5); } } public static void chatAtPlayer(EntityPlayer player, String text) { player.addChatComponentMessage(new TextComponentString(text)); } public static String printPos(BlockPos pos) { return pos.getX() + ", " + pos.getY() + ", " + pos.getZ(); } public static Vec3d blockCenter(BlockPos pos) { pos.getX(); Vec3d returnThis = new Vec3d(pos.getX()+0.5, pos.getY()+0.5, pos.getZ()+0.5); return returnThis; } public static int getMaxStackToAdd(IInventory inventory, ItemStack stack, int slot) { // Determine whether the inventory stack limit or the stack size is smaller int stacksize = 0; int slotStackSize = 0; if (!isStackEmpty(stack)) { stacksize = stack.stackSize; } if (slot >= 0 && slot < inventory.getSizeInventory()) { ItemStack stackInSlot = inventory.getStackInSlot(slot); if (!isStackEmpty(stackInSlot)) { slotStackSize = stackInSlot.stackSize; } } // Max stack size if slot is empty int minBound = Math.min(inventory.getInventoryStackLimit(), stacksize); int remainingItemSpace = Math.max(0, minBound - slotStackSize); return remainingItemSpace; } public static boolean isStackEmpty(ItemStack stack) { return (stack == null || stack.getItem() == null || stack.stackSize <= 0); } public static boolean canWeStack(ItemStack one, ItemStack two) { if (one == null || two == null) { return false; } else if (one.getItem() == two.getItem()) { if (one.isStackable()) { if (one.getItemDamage() == two.getItemDamage()) { return true; } else { return false; } } else { return false; } } else { return false; } } }
  21. The IEntityAdditionalSpawnData idea seems to be working so far. Thanks!
  22. Do you know of any tutorials I can follow to figure out how to use the two functions that interface imported?
  23. The constructor I'm using is a custom one for the entity itself. You can find the constructor in the code I supplied. I'm trying to set values that will change from instance to instance of this entity. How am I supposed to set said values without using a constructor (btw, a setter isn't working either)?
  24. The renderer code does not modify anything in the entity class, just pull information from it. As I said, the renderer works fine if I change the orientation value in the entity class itself. The problem is that the constructor is not setting the value for the orientation when supplied via constructor. I'll include the renderer code in my original post if something is wrong there. I was also looking at my renderer code and noticed I was overriding the doRender function, and I'm not sure if I'm supposed to do that as I call the super class's doRender function. Whether I overrode the parent function didn't change the outcome.
×
×
  • Create New...

Important Information

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