Jump to content

T-10a

Members
  • Posts

    59
  • Joined

  • Last visited

Everything posted by T-10a

  1. Okay then. When I finish that up, I'll simply start a new post. Thanks for the link. If any admin wants to lock this, feel free to do so.
  2. I followed the Codecademy tutorial, so I know basics. Minecraft modding is also my first foray into serious programming outside of Bash scripts & high school Visual Basic programs a year or two ago. (please don't ban me for this D:) This is also my first-ish attempt at extending my modding skills beyond simply "adding custom tools to the game", and yes, I did watch MrCrayFish's tutorials (though before that, I watched Pahimar's tutorials)
  3. Got that. It doesn't crash the game now when I load the world OR place a new block down. Thing is, I can't exactly extract an item from stack 0, while I could definitely insert a stack. Not sure where I goofed, as I'm telling the game if heldItem == null (as in the empty hand), it'll run stackHandler.extractItem(0, 1, false); . Here's the code for the block: [spoiler=Newer BlockBonfire.class] package com.t10a.crystalflask.blocks; import com.t10a.crystalflask.Reference; import com.t10a.crystalflask.init.ModItems; import com.t10a.crystalflask.tileentity.TileEntityBonfire; import com.t10a.crystalflask.tileentity.TileEntityBonfire.StackHandler; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; 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; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; import java.util.List; import java.util.Random; public class BlockBonfire extends Block { //private static final AxisAlignedBB BOUNDING_BOX = new AxisAlignedBB(x1, y1, z1, x2, y2, z2); //This sets the hitbox for this block, private static final AxisAlignedBB BOUNDING_BOX = new AxisAlignedBB(0.0625 * 3, 0, 0.0625 * 4, 0.0625 * 12, 0.0625 * 15, 0.0625 * 12); public BlockBonfire(String name, CreativeTabs tabs) { super(Material.ROCK); //It's a good idea to put the modid into the block's unlocalised name, to prevent conflicts in the en_US.lang. setUnlocalizedName(Reference.MOD_ID + "." + name); setRegistryName(Reference.MOD_ID, name); setCreativeTab(tabs); this.setLightLevel(5.0F); } /* * The following are obvious. isFullCube checks if this is a full cube (it isn't), isOpaqueCube checks if this cube is opaque (it isn't a cube, so no), * getBlockLayer returns this block is solid, getBoundingBox tells the game the hitbox we defined earlier(?), and addCollisionBoxToList registers the hitbox(?). */ @Override public boolean isFullCube(IBlockState state) { return false; } @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.SOLID; } @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return BOUNDING_BOX; } @Override public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn) { super.addCollisionBoxToList(pos, entityBox, collidingBoxes, BOUNDING_BOX); } //WIP. Pretty much is responsible for the particle effects this block emits. //TODO: Make this emit special particles based on what item is contained. @SideOnly(Side.CLIENT) public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { double d0 = (double)pos.getX() + 0.5D; double d1 = (double)pos.getY() + rand.nextDouble() * 6.0D / 16.0D; double d2 = (double)pos.getZ() + 0.5D; double d3 = rand.nextDouble() * 0.6D - 0.3D; if (rand.nextDouble() < 0.3D) { worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, SoundEvents.BLOCK_FIRE_AMBIENT, SoundCategory.BLOCKS, 1.0F, 1.0F, false); } worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); /* if(worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if (tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; if(bonfire.stack.getItem() == ModItems.estus_shard) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.CRIT, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } else if(bonfire.stack.getItem() == ModItems.estus_ash) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_LARGE, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } else if(bonfire.stack.getItem() == Items.BLAZE_ROD) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); if(rand.nextDouble() > 0.3D) { worldIn.spawnParticle(EnumParticleTypes.LAVA, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } else { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } } */ } //This pretty much tells the TileEntity class what to do based on what's right-clicking it. @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { if(!worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if(tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; TileEntityBonfire.StackHandler stackHandler = (StackHandler) new TileEntityBonfire.StackHandler(); if(heldItem != null) { if (heldItem.getItem() == ModItems.estus_shard || heldItem.getItem() == ModItems.estus_ash || heldItem.getItem() == Items.BLAZE_ROD) { stackHandler.insertItem(0, heldItem, false); heldItem.stackSize--; return true; } else if (heldItem.getItem() == ModItems.estus_flask) { bonfire.estusRestock(heldItem); return true; } else if(heldItem.getItem() == Items.PRISMARINE_SHARD || (heldItem.getItem() == Items.SKULL && heldItem.getMetadata() == 1)) { bonfire.bonfireCraft(heldItem); return true; } } stackHandler.extractItem(0, 1, false); return true; } } return false; } //Tells the game this has a TileEntity @Override public boolean hasTileEntity(IBlockState state) { return true; } //Tells the game what tile entity to create when placed @Override public TileEntity createTileEntity(World world, IBlockState state) { return new TileEntityBonfire(); } } Also, how would I check what's in Slot 0, so I can do things with the item? And would I be able to simply 'delete' the item in stack 0?
  4. Ok, (I think) I fixed the StackHandler by initialising it as TileEntityBonfire.StackHandler stackHandler = (StackHandler) new TileEntityBonfire.StackHandler(); . I also got rid of the override, and fixed up the simulate boolean, by returning simulate in both of the supers. How would I handle writeUpdateTag being null?
  5. Hmm... I'll go for the second one. Actually, I got a crash here when I placed it in the world. Here's the log: [spoiler=Crash Log] OpenJDK 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release [16:25:15] [main/INFO] [GradleStart]: Extra: [] [16:25:15] [main/INFO] [GradleStart]: Running with arguments: [--userProperties, {}, --assetsDir, /home/thomas/.gradle/caches/minecraft/assets, --assetIndex, 1.10, --accessToken{REDACTED}, --version, 1.10.2, --tweakClass, net.minecraftforge.fml.common.launcher.FMLTweaker, --tweakClass, net.minecraftforge.gradle.tweakers.CoremodTweaker] [16:25:15] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Using primary tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.gradle.tweakers.CoremodTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLTweaker [16:25:15] [main/INFO] [FML]: Forge Mod Loader version 12.18.1.2011 for Minecraft 1.10.2 loading [16:25:15] [main/INFO] [FML]: Java is OpenJDK 64-Bit Server VM, version 1.8.0_102, running on Linux:amd64:4.7.2-1-ARCH, installed at /usr/lib/jvm/java-8-openjdk/jre [16:25:15] [main/INFO] [FML]: Managed to load a deobfuscated Minecraft name- we are in a deobfuscated environment. Skipping runtime deobfuscation [16:25:15] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.gradle.tweakers.CoremodTweaker [16:25:15] [main/INFO] [GradleStart]: Injecting location in coremod net.minecraftforge.fml.relauncher.FMLCorePlugin [16:25:15] [main/INFO] [GradleStart]: Injecting location in coremod net.minecraftforge.classloading.FMLForgePlugin [16:25:15] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLDeobfTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.gradle.tweakers.AccessTransformerTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker [16:25:15] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper [16:25:15] [main/ERROR] [FML]: The binary patch set is missing. Either you are in a development environment, or things are not going to work! [16:25:16] [main/ERROR] [FML]: FML appears to be missing any signature data. This is not a good thing [16:25:16] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper [16:25:16] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLDeobfTweaker [16:25:16] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.gradle.tweakers.AccessTransformerTweaker [16:25:16] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.TerminalTweaker [16:25:16] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.TerminalTweaker [16:25:16] [main/INFO] [LaunchWrapper]: Launching wrapped minecraft {net.minecraft.client.main.Main} [16:25:17] [Client thread/INFO]: Setting user: Player948 [16:25:19] [Client thread/INFO]: LWJGL Version: 2.9.4 ATTENTION: default value of option vblank_mode overridden by environment. [16:25:19] [Client thread/INFO] [FML]: Could not load splash.properties, will create a default one [16:25:19] [Client thread/INFO] [sTDOUT]: [net.minecraftforge.fml.client.SplashProgress:start:221]: ---- Minecraft Crash Report ---- // You're mean. Time: 2/09/16 4:25 PM Description: Loading screen debug info This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- System Details -- Details: Minecraft Version: 1.10.2 Operating System: Linux (amd64) version 4.7.2-1-ARCH Java Version: 1.8.0_102, Oracle Corporation Java VM Version: OpenJDK 64-Bit Server VM (mixed mode), Oracle Corporation Memory: 661000712 bytes (630 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB) JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0 FML: Loaded coremods (and transformers): GL info: ' Vendor: 'X.Org' Version: '3.0 Mesa 12.0.1' Renderer: 'Gallium 0.4 on AMD HAWAII (DRM 2.45.0 / 4.7.2-1-ARCH, LLVM 3.8.1)' [16:25:19] [Client thread/INFO] [FML]: MinecraftForge v12.18.1.2011 Initialized [16:25:19] [Client thread/INFO] [FML]: Replaced 233 ore recipes [16:25:20] [Client thread/INFO] [FML]: Found 0 mods from the command line. Injecting into mod discoverer [16:25:20] [Client thread/INFO] [FML]: Searching /drv/Data/Content/Minecraft/Mods/1.10.2/CrystalFlask/run/mods for mods [16:25:20] [Client thread/INFO] [FML]: Forge Mod Loader has identified 4 mods to load [16:25:20] [Client thread/INFO] [FML]: Attempting connection with missing mods [mcp, FML, Forge, crystalflask] at CLIENT [16:25:20] [Client thread/INFO] [FML]: Attempting connection with missing mods [mcp, FML, Forge, crystalflask] at SERVER [16:25:21] [Client thread/INFO]: Reloading ResourceManager: Default, FMLFileResourcePack:Forge Mod Loader, FMLFileResourcePack:Minecraft Forge, FMLFileResourcePack:Crystal Flask [16:25:21] [Client thread/INFO] [FML]: Processing ObjectHolder annotations [16:25:21] [Client thread/INFO] [FML]: Found 423 ObjectHolder annotations [16:25:21] [Client thread/INFO] [FML]: Identifying ItemStackHolder annotations [16:25:21] [Client thread/INFO] [FML]: Found 0 ItemStackHolder annotations [16:25:21] [Client thread/INFO] [FML]: Configured a dormant chunk cache size of 0 [16:25:21] [Forge Version Check/INFO] [ForgeVersionCheck]: [Forge] Starting version check at http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json [16:25:21] [Client thread/INFO] [FML]: Applying holder lookups [16:25:21] [Client thread/INFO] [FML]: Holder lookups applied [16:25:21] [Client thread/INFO] [FML]: Injecting itemstacks [16:25:21] [Client thread/INFO] [FML]: Itemstack injection complete [16:25:21] [sound Library Loader/INFO]: Starting up SoundSystem... [16:25:21] [Forge Version Check/INFO] [ForgeVersionCheck]: [Forge] Found status: UP_TO_DATE Target: null [16:25:22] [Thread-6/INFO]: Initializing LWJGL OpenAL [16:25:22] [Thread-6/INFO]: (The LWJGL binding of OpenAL. For more information, see http://www.lwjgl.org) [16:25:22] [Thread-6/INFO]: OpenAL initialized. [16:25:22] [sound Library Loader/INFO]: Sound engine started [16:25:23] [Client thread/INFO] [FML]: Max texture size: 16384 [16:25:23] [Client thread/INFO]: Created: 16x16 textures-atlas [16:25:24] [Client thread/INFO] [FML]: Injecting itemstacks [16:25:24] [Client thread/INFO] [FML]: Itemstack injection complete [16:25:24] [Client thread/INFO] [FML]: Forge Mod Loader has successfully loaded 4 mods [16:25:24] [Client thread/INFO]: Reloading ResourceManager: Default, FMLFileResourcePack:Forge Mod Loader, FMLFileResourcePack:Minecraft Forge, FMLFileResourcePack:Crystal Flask [16:25:24] [Client thread/INFO]: SoundSystem shutting down... [16:25:24] [Client thread/WARN]: Author: Paul Lamb, www.paulscode.com [16:25:24] [sound Library Loader/INFO]: Starting up SoundSystem... [16:25:24] [Thread-8/INFO]: Initializing LWJGL OpenAL [16:25:24] [Thread-8/INFO]: (The LWJGL binding of OpenAL. For more information, see http://www.lwjgl.org) [16:25:24] [Thread-8/INFO]: OpenAL initialized. [16:25:25] [sound Library Loader/INFO]: Sound engine started [16:25:25] [Client thread/INFO] [FML]: Max texture size: 16384 [16:25:25] [Client thread/INFO]: Created: 1024x512 textures-atlas [16:25:27] [Realms Notification Availability checker #1/INFO]: Could not authorize you against Realms server: Invalid session id [16:25:33] [server thread/INFO]: Starting integrated minecraft server version 1.10.2 [16:25:33] [server thread/INFO]: Generating keypair [16:25:33] [server thread/INFO] [FML]: Injecting existing block and item data into this server instance [16:25:33] [server thread/INFO] [FML]: Applying holder lookups [16:25:33] [server thread/INFO] [FML]: Holder lookups applied [16:25:33] [server thread/INFO] [FML]: Loading dimension 0 (New World) (net.minecraft.server.integrated.IntegratedServer@3795c8c6) [16:25:33] [server thread/WARN]: Unable to find spawn biome [16:25:35] [server thread/INFO] [FML]: Loading dimension 1 (New World) (net.minecraft.server.integrated.IntegratedServer@3795c8c6) [16:25:35] [server thread/INFO] [FML]: Loading dimension -1 (New World) (net.minecraft.server.integrated.IntegratedServer@3795c8c6) [16:25:35] [server thread/INFO]: Preparing start region for level 0 [16:25:36] [server thread/INFO]: Preparing spawn area: 15% [16:25:37] [server thread/INFO]: Preparing spawn area: 31% [16:25:38] [server thread/INFO]: Preparing spawn area: 48% [16:25:39] [server thread/INFO]: Preparing spawn area: 64% [16:25:40] [server thread/INFO]: Preparing spawn area: 85% [16:25:41] [server thread/INFO]: Changing view distance to 12, from 10 [16:25:42] [Netty Local Client IO #0/INFO] [FML]: Server protocol version 2 [16:25:42] [Netty Server IO #1/INFO] [FML]: Client protocol version 2 [16:25:42] [Netty Server IO #1/INFO] [FML]: Client attempting to join with 4 mods : [email protected],[email protected],[email protected],[email protected] [16:25:42] [Netty Local Client IO #0/INFO] [FML]: [Netty Local Client IO #0] Client side modded connection established [16:25:42] [server thread/INFO] [FML]: [server thread] Server side modded connection established [16:25:42] [server thread/INFO]: Player948[local:E:2ffd9c11] logged in with entity id 1156 at (-493.5, 68.0, -812.5) [16:25:42] [server thread/INFO]: Player948 joined the game [16:25:43] [pool-2-thread-1/WARN]: Couldn't look up profile properties for com.mojang.authlib.GameProfile@6b9c0e72[id=2dd1d9e7-57ae-36c4-8b90-c235b1bdb90f,name=Player948,properties={},legacy=false] com.mojang.authlib.exceptions.AuthenticationException: The client has sent too many requests within a certain amount of time at com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService.makeRequest(YggdrasilAuthenticationService.java:65) ~[YggdrasilAuthenticationService.class:?] at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fillGameProfile(YggdrasilMinecraftSessionService.java:175) [YggdrasilMinecraftSessionService.class:?] at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService$1.load(YggdrasilMinecraftSessionService.java:59) [YggdrasilMinecraftSessionService$1.class:?] at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService$1.load(YggdrasilMinecraftSessionService.java:56) [YggdrasilMinecraftSessionService$1.class:?] at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195) [guava-17.0.jar:?] at com.google.common.cache.LocalCache.get(LocalCache.java:3934) [guava-17.0.jar:?] at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4827) [guava-17.0.jar:?] at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fillProfileProperties(YggdrasilMinecraftSessionService.java:165) [YggdrasilMinecraftSessionService.class:?] at net.minecraft.client.Minecraft.getProfileProperties(Minecraft.java:3060) [Minecraft.class:?] at net.minecraft.client.resources.SkinManager$3.run(SkinManager.java:131) [skinManager$3.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_102] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_102] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_102] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_102] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_102] [16:25:44] [server thread/INFO]: Player948 has just earned the achievement [Taking Inventory] [16:25:44] [Client thread/INFO]: [CHAT] Player948 has just earned the achievement [Taking Inventory] [16:25:49] [server thread/ERROR]: Encountered an unexpected exception net.minecraft.util.ReportedException: Exception ticking world at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:778) ~[MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) ~[MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) ~[integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_102] Caused by: java.lang.NullPointerException at com.t10a.crystalflask.tileentity.TileEntityBonfire.writeUpdateTag(TileEntityBonfire.java:206) ~[TileEntityBonfire.class:?] at com.t10a.crystalflask.tileentity.TileEntityBonfire.getUpdatePacket(TileEntityBonfire.java:192) ~[TileEntityBonfire.class:?] at net.minecraft.server.management.PlayerChunkMapEntry.sendBlockEntity(PlayerChunkMapEntry.java:297) ~[PlayerChunkMapEntry.class:?] at net.minecraft.server.management.PlayerChunkMapEntry.update(PlayerChunkMapEntry.java:259) ~[PlayerChunkMapEntry.class:?] at net.minecraft.server.management.PlayerChunkMap.tick(PlayerChunkMap.java:134) ~[PlayerChunkMap.class:?] at net.minecraft.world.WorldServer.tick(WorldServer.java:229) ~[WorldServer.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:772) ~[MinecraftServer.class:?] ... 4 more [16:25:49] [server thread/ERROR]: This crash report has been saved to: /drv/Data/Content/Minecraft/Mods/1.10.2/CrystalFlask/run/./crash-reports/crash-2016-09-02_16.25.49-server.txt [16:25:49] [server thread/INFO]: Stopping server [16:25:49] [server thread/INFO]: Saving players [16:25:49] [server thread/INFO]: Player948 lost connection: TextComponent{text='Server closed', siblings=[], style=Style{hasParent=false, color=null, bold=null, italic=null, underlined=null, obfuscated=null, clickEvent=null, hoverEvent=null, insertion=null}} [16:25:49] [server thread/INFO]: Player948 left the game [16:25:49] [Client thread/INFO] [sTDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:649]: ---- Minecraft Crash Report ---- // This doesn't make any sense! Time: 2/09/16 4:25 PM Description: Exception ticking world java.lang.NullPointerException: Exception ticking world at com.t10a.crystalflask.tileentity.TileEntityBonfire.writeUpdateTag(TileEntityBonfire.java:206) at com.t10a.crystalflask.tileentity.TileEntityBonfire.getUpdatePacket(TileEntityBonfire.java:192) at net.minecraft.server.management.PlayerChunkMapEntry.sendBlockEntity(PlayerChunkMapEntry.java:297) at net.minecraft.server.management.PlayerChunkMapEntry.update(PlayerChunkMapEntry.java:259) at net.minecraft.server.management.PlayerChunkMap.tick(PlayerChunkMap.java:134) at net.minecraft.world.WorldServer.tick(WorldServer.java:229) at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:772) at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) at java.lang.Thread.run(Thread.java:745) A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Client thread Stacktrace: at com.t10a.crystalflask.tileentity.TileEntityBonfire.writeUpdateTag(TileEntityBonfire.java:206) at com.t10a.crystalflask.tileentity.TileEntityBonfire.getUpdatePacket(TileEntityBonfire.java:192) at net.minecraft.server.management.PlayerChunkMapEntry.sendBlockEntity(PlayerChunkMapEntry.java:297) at net.minecraft.server.management.PlayerChunkMapEntry.update(PlayerChunkMapEntry.java:259) at net.minecraft.server.management.PlayerChunkMap.tick(PlayerChunkMap.java:134) at net.minecraft.world.WorldServer.tick(WorldServer.java:229) -- Affected level -- Details: Level name: New World All players: 1 total; [EntityPlayerMP['Player948'/1156, l='New World', x=-493.81, y=68.00, z=-811.77]] Chunk stats: ServerChunkCache: 893 Drop: 0 Level seed: -5966445043629997792 Level generator: ID 00 - default, ver 1. Features enabled: true Level generator options: Level spawn location: World: (-486,64,-804), Chunk: (at 10,4,12 in -31,-51; contains blocks -496,0,-816 to -481,255,-801), Region: (-1,-2; contains chunks -32,-64 to -1,-33, blocks -512,0,-1024 to -1,255,-513) Level time: 156 game time, 156 day time Level dimension: 0 Level storage version: 0x04ABD - Anvil Level weather: Rain time: 120201 (now: false), thunder time: 51286 (now: false) Level game mode: Game mode: creative (ID 1). Hardcore: false. Cheats: true Stacktrace: at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:772) at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) at java.lang.Thread.run(Thread.java:745) -- System Details -- Details: Minecraft Version: 1.10.2 Operating System: Linux (amd64) version 4.7.2-1-ARCH Java Version: 1.8.0_102, Oracle Corporation Java VM Version: OpenJDK 64-Bit Server VM (mixed mode), Oracle Corporation Memory: 679137520 bytes (647 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB) JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M IntCache: cache: 0, tcache: 0, allocated: 13, tallocated: 95 FML: MCP 9.32 Powered by Forge 12.18.1.2011 4 mods loaded, 4 mods active States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored UCHIJAAAA mcp{9.19} [Minecraft Coder Pack] (minecraft.jar) UCHIJAAAA FML{8.0.99.99} [Forge Mod Loader] (forgeSrc-1.10.2-12.18.1.2011.jar) UCHIJAAAA Forge{12.18.1.2011} [Minecraft Forge] (forgeSrc-1.10.2-12.18.1.2011.jar) UCHIJAAAA crystalflask{1.10.2-BETA} [Crystal Flask] (bin) Loaded coremods (and transformers): GL info: ~~ERROR~~ RuntimeException: No OpenGL context found in the current thread. Profiler Position: N/A (disabled) Player Count: 1 / 8; [EntityPlayerMP['Player948'/1156, l='New World', x=-493.81, y=68.00, z=-811.77]] Type: Integrated Server (map_client.txt) Is Modded: Definitely; Client brand changed to 'fml,forge' [16:25:49] [Client thread/INFO] [sTDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:649]: #@!@# Game crashed! Crash report saved to: #@!@# ./crash-reports/crash-2016-09-02_16.25.49-server.txt [16:25:49] [Client thread/INFO] [FML]: Waiting for the server to terminate/save. [16:25:49] [server thread/INFO]: Stopping singleplayer server as player logged out [16:25:49] [server thread/INFO]: Saving worlds [16:25:49] [server thread/INFO]: Saving chunks for level 'New World'/Overworld [16:25:49] [server thread/ERROR] [FML]: A TileEntity type com.t10a.crystalflask.tileentity.TileEntityBonfire has throw an exception trying to write state. It will not persist. Report this to the mod author java.lang.NullPointerException at com.t10a.crystalflask.tileentity.TileEntityBonfire.writeToNBT(TileEntityBonfire.java:168) ~[TileEntityBonfire.class:?] at net.minecraft.world.chunk.storage.AnvilChunkLoader.writeChunkToNBT(AnvilChunkLoader.java:409) [AnvilChunkLoader.class:?] at net.minecraft.world.chunk.storage.AnvilChunkLoader.saveChunk(AnvilChunkLoader.java:182) [AnvilChunkLoader.class:?] at net.minecraft.world.gen.ChunkProviderServer.saveChunkData(ChunkProviderServer.java:208) [ChunkProviderServer.class:?] at net.minecraft.world.gen.ChunkProviderServer.saveChunks(ChunkProviderServer.java:236) [ChunkProviderServer.class:?] at net.minecraft.world.WorldServer.saveAllChunks(WorldServer.java:1061) [WorldServer.class:?] at net.minecraft.server.MinecraftServer.saveAllWorlds(MinecraftServer.java:414) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.saveAllWorlds(IntegratedServer.java:238) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.stopServer(MinecraftServer.java:455) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.stopServer(IntegratedServer.java:369) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:589) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_102] [16:25:49] [server thread/INFO]: Saving chunks for level 'New World'/Nether [16:25:49] [server thread/INFO]: Saving chunks for level 'New World'/The End [16:25:49] [server thread/INFO] [FML]: Unloading dimension 0 [16:25:49] [server thread/INFO] [FML]: Unloading dimension -1 [16:25:49] [server thread/INFO] [FML]: Unloading dimension 1 [16:25:49] [server thread/INFO] [FML]: Applying holder lookups [16:25:49] [server thread/INFO] [FML]: Holder lookups applied [16:25:49] [server thread/INFO] [FML]: The state engine was in incorrect state SERVER_STOPPING and forced into state SERVER_STOPPED. Errors may have been discarded. [16:25:49] [Client thread/INFO] [FML]: Server terminated. AL lib: (EE) alc_cleanup: 1 device not closed And here's the TileEntity class(where the error occurs) [spoiler=TileEntityBonfire.class] package com.t10a.crystalflask.tileentity; import com.t10a.crystalflask.init.ModItems; import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.items.ItemStackHandler; public class TileEntityBonfire extends TileEntity { public ItemStack storedItem; public class StackHandler extends ItemStackHandler { @Override public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { if(stack == null || stack.stackSize == 0) { return null; } else return super.insertItem(0, stack, false); } @Override public ItemStack extractItem(int slot, int amount, boolean simulate) { return super.extractItem(0, amount, false); } @Override protected int getStackLimit(int slot, ItemStack stack) { return 1; } @Override public NBTTagCompound serializeNBT() { return super.serializeNBT(); } @Override public void deserializeNBT(NBTTagCompound nbt) { super.deserializeNBT(nbt); } } //Variables telling the TileEntity what's currently contained.; //BELOW IS COMMENTED OUT, MAINLY FOR CHECKING OUT THE NEW ITEMSTACKHANDLER //This tells the block how to handle adding items. /* public boolean addItem(ItemStack heldItem) { if(heldItem.getItem() == ModItems.estus_shard) { storedItem = new ItemStack(ModItems.estus_shard); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } else if(heldItem.getItem() == ModItems.estus_ash) { storedItem = new ItemStack(ModItems.estus_ash); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } else if(heldItem.getItem() == Items.BLAZE_ROD) { storedItem = new ItemStack(Items.BLAZE_ROD); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } return false; } //This tells the block how to handle removing items. public void removeItem() { if(storedItem.getItem() == ModItems.estus_ash) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); } else if(storedItem.getItem() == ModItems.estus_shard) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); } else if(storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(Items.BLAZE_ROD))); } storedItem = null; markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); } */ //Temporary crafting class. It'll be replaced by a dedicated crafting thing, so it's easier to add recipes, or other mods can add to it, in jolly modding cooperation \[T]/ public void bonfireCraft(ItemStack heldItem) { //TODO: Delete this, and make a dedicated recipe handler, so it's easier to add recipes to. For both me and addon developers. if(heldItem.getItem() == Items.PRISMARINE_SHARD && storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); heldItem.stackSize--; storedItem.stackSize--; } else if(heldItem.getItem() == Items.SKULL && heldItem.getMetadata() == 1 && storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); heldItem.stackSize--; storedItem.stackSize--; } } //This is a big chunk of code that used to be on the flask. This handles the restocking the uses, and upgrading of the flask when this is called by BlockBonfire. public void estusRestock(ItemStack heldItem) { if(heldItem.getItem() == ModItems.estus_flask) { NBTTagCompound nbt; if (heldItem.hasTagCompound()) { nbt = heldItem.getTagCompound(); } else { nbt = new NBTTagCompound(); } if (nbt.hasKey("Uses")) { if(storedItem.getItem() == ModItems.estus_shard && nbt.getInteger("Max Uses") < 12) { nbt.setInteger("Max Uses", nbt.getInteger("Max Uses") + 1); storedItem.stackSize--; } else if(storedItem.getItem() == ModItems.estus_ash && nbt.getInteger("Potency") < 5) { nbt.setInteger("Potency", nbt.getInteger("Potency") + 1); storedItem.stackSize--; } nbt.setInteger("Uses", nbt.getInteger("Max Uses")); } else { nbt.setInteger("Uses", 1); nbt.setInteger("Max Uses", 1); nbt.setInteger("Potency", 1); } storedItem.setTagCompound(nbt); } } //This merely saves the variables defined earlier to NBT. @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setTag("ContainedItems", storedItem.serializeNBT()); return compound; } //Similar to above, but it loads from NBT instead. @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); this.storedItem = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("ContainedItems")); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { NBTTagCompound tag = pkt.getNbtCompound(); readUpdateTag(tag); } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeUpdateTag(tag); return new SPacketUpdateTileEntity(pos, getBlockMetadata(), tag); } @Override public NBTTagCompound getUpdateTag() { NBTTagCompound tag = super.getUpdateTag(); writeUpdateTag(tag); return tag; } public void writeUpdateTag(NBTTagCompound tag) { tag.setTag("ContainedItems", storedItem.writeToNBT(tag)); } public void readUpdateTag(NBTTagCompound tag) { this.storedItem = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("ContainedItems")); } }
  6. Not sure how that works, as this is what I did for my item: https://github.com/T10a/CrystalFlask/blob/master/src/main/java/com/t10a/crystalflask/items/ItemCrystalFlask.java
  7. Sure. I did fix it eventually by getting rid of stuff I didnt need. What's your custom property/properties, and your JSON file?
  8. Okay then. How would I initialise the StackHandler in the onBlockActivated? As in, I have the tileEntity defined as TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; , where tileEntity is initialised as TileEntity tileEntity = worldIn.getTileEntity(pos); ? I've got the stackHandler defined as ItemStackHandler stackHandler = (TileEntityBonfire.StackHandler) stackHandler; already.
  9. Okay, got that all in a field. How would I use it in the Block class to say, insert an item on right click? I can't shove it in onBlockActivated like how I did it before, as insertItem can't be called from it. side question: What does simulating the insertion of an item do? And what would it be useful for?
  10. Will I need to create a new class to use ItemStackHandler? I can't extend both TileEntity & ItemStackHandler into my tile entity class.
  11. Okay, made it set the stack to null. Thing is, it crashed the game: (maybe I shouldn't have explicitly told it to register the item as null. I'm just not sure how to clear it.) Here's the TileEntityBonfire class:
  12. That fixed it. Thanks! And yeah, I should have posted the whole log. Oops. Side note: How would I set a ItemStack to null? My code, once something is placed in it, constantly spawns that item on a right click, and it's not clearing the item in there.
  13. Hello, After making my tile entity use ItemStacks as a variable, it now freezes upon exiting the world, looping these two lines in the code, saying something about the writing to NBT is crashing the game. [spoiler=Log Exerpt] [18:46:11] [File IO Thread/INFO] [sTDERR]: [java.lang.ThreadGroup:uncaughtException:1052]: at net.minecraft.nbt.NBTTagCompound.write(NBTTagCompound.java:29) [18:46:11] [File IO Thread/INFO] [sTDERR]: [java.lang.ThreadGroup:uncaughtException:1052]: at net.minecraft.nbt.NBTTagCompound.writeEntry(NBTTagCompound.java:556) Here's the TileEntity code: [spoiler=TileEntityBonfire.class] package com.t10a.crystalflask.tileentity; import com.t10a.crystalflask.init.ModItems; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; public class TileEntityBonfire extends TileEntity { public ItemStack storedItem; //Variables telling the TileEntity what's currently contained.; //This tells the block how to handle adding items. public boolean addItem(ItemStack heldItem) { if(heldItem.getItem() == ModItems.estus_shard) { storedItem = new ItemStack(ModItems.estus_shard); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } else if(heldItem.getItem() == ModItems.estus_ash) { storedItem = new ItemStack(ModItems.estus_ash); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } else if(heldItem.getItem() == Items.BLAZE_ROD) { storedItem = new ItemStack(Items.BLAZE_ROD); markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); return true; } return false; } //This tells the block how to handle removing items. public void removeItem() { if(storedItem.getItem() == (ModItems.estus_shard)) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); storedItem.stackSize--; markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); } else if(storedItem.getItem() == ModItems.estus_ash) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); storedItem.stackSize--; markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); } else if(storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(Items.BLAZE_ROD))); storedItem.stackSize--; markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); } } //Temporary crafting class. It'll be replaced by a dedicated crafting thing, so it's easier to add recipes, or other mods can add to it, in jolly modding cooperation \[T]/ public void bonfireCraft(ItemStack heldItem) { //TODO: Delete this, and make a dedicated recipe handler, so it's easier to add recipes to. For both me and addon developers. if(heldItem.getItem() == Items.PRISMARINE_SHARD && storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); heldItem.stackSize--; storedItem.stackSize--; } else if(heldItem.getItem() == Items.SKULL && heldItem.getMetadata() == 1 && storedItem.getItem() == Items.BLAZE_ROD) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); heldItem.stackSize--; storedItem.stackSize--; } } //This is a big chunk of code that used to be on the flask. This handles the restocking the uses, and upgrading of the flask when this is called by BlockBonfire. public void estusRestock(ItemStack heldItem) { if(heldItem.getItem() == ModItems.estus_flask) { NBTTagCompound nbt; if (heldItem.hasTagCompound()) { nbt = heldItem.getTagCompound(); } else { nbt = new NBTTagCompound(); } if (nbt.hasKey("Uses")) { if(storedItem.getItem() == ModItems.estus_shard && nbt.getInteger("Max Uses") < 12) { nbt.setInteger("Max Uses", nbt.getInteger("Max Uses") + 1); storedItem.stackSize--; } else if(storedItem.getItem() == ModItems.estus_ash && nbt.getInteger("Potency") < 5) { nbt.setInteger("Potency", nbt.getInteger("Potency") + 1); storedItem.stackSize--; } nbt.setInteger("Uses", nbt.getInteger("Max Uses")); } else { nbt.setInteger("Uses", 1); nbt.setInteger("Max Uses", 1); nbt.setInteger("Potency", 1); } storedItem.setTagCompound(nbt); } } //This merely saves the variables defined earlier to NBT. @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setTag("ContainedItems", storedItem.writeToNBT(compound)); return compound; } //Similar to above, but it loads from NBT instead. @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); this.storedItem = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("ContainedItems")); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { NBTTagCompound tag = pkt.getNbtCompound(); readUpdateTag(tag); } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeUpdateTag(tag); return new SPacketUpdateTileEntity(pos, getBlockMetadata(), tag); } @Override public NBTTagCompound getUpdateTag() { NBTTagCompound tag = super.getUpdateTag(); writeUpdateTag(tag); return tag; } public void writeUpdateTag(NBTTagCompound tag) { tag.setTag("ContainedItems", storedItem.writeToNBT(tag)); } public void readUpdateTag(NBTTagCompound tag) { this.storedItem = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("ContainedItems")); } }
  14. Okay, added that marker. It works now! I'll figure out a way to get it so that it uses ItemStacks instead of ints.
  15. Okay, I added a function to save & load the NBT: [spoiler=Tile Entity snippet] @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { NBTTagCompound tag = pkt.getNbtCompound(); readUpdateTag(tag); } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound tag = new NBTTagCompound(); this.writeUpdateTag(tag); return new SPacketUpdateTileEntity(pos, getBlockMetadata(), tag); } @Override public NBTTagCompound getUpdateTag() { NBTTagCompound tag = super.getUpdateTag(); writeUpdateTag(tag); return tag; } public void writeUpdateTag(NBTTagCompound tag) { tag.setInteger("ShardCount", this.shardCount); tag.setInteger("AshCount", this.ashCount); tag.setInteger("BlazeCount", this.blazerodCount); } public void readUpdateTag(NBTTagCompound tag) { this.shardCount = tag.getInteger("ShardCount"); this.ashCount = tag.getInteger("AshCount"); this.blazerodCount = tag.getInteger("BlazeCount"); } Now it does change now, but it only changes when the world is loaded (i.e. entering a world). Weird.
  16. I am 100% sure, as I added these to the randomDisplayTick area: [spoiler=BlockBonfire selection code] if(worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if (tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; if(bonfire.shardCount == 1 && bonfire.ashCount == 0 && bonfire.blazerodCount ==0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.CRIT, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); System.out.println("SPAWNED SHARD PARTICLES"); } else if(bonfire.ashCount == 1 && bonfire.shardCount == 0 && bonfire.blazerodCount == 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_LARGE, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); System.out.println("SPAWNED ASH PARTICLES"); } else if(bonfire.blazerodCount == 1 && bonfire.ashCount == 0 && bonfire.shardCount == 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); if(rand.nextDouble() > 0.3D) { worldIn.spawnParticle(EnumParticleTypes.LAVA, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } System.out.println("SPAWNED BLAZE ROD PARTICLES"); } else { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); System.out.println("SPAWNED DEFAULT PARTICLES"); } } } and the log returned this when the world loaded: [spoiler=Log Snippet] [17:33:13] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:14] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:14] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:15] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:15] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:15] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:15] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:15] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:16] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:16] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:16] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:17] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:17] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:17] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:17] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:18] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:19] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:19] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:19] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:19] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:20] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:20] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:21] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES [17:33:21] [Client thread/INFO] [sTDOUT/]: [com.t10a.crystalflask.blocks.BlockBonfire:randomDisplayTick:126]: SPAWNED DEFAULT PARTICLES I also added your TileEntity suggestions as well.
  17. Changed it so it's got more else ifs, however it will still not change the particles spawned when the variables are changed themselves. Here's the new block code: [spoiler=Block Code] package com.t10a.crystalflask.blocks; import com.t10a.crystalflask.Reference; import com.t10a.crystalflask.init.ModItems; import com.t10a.crystalflask.tileentity.TileEntityBonfire; 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.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; 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; import java.util.List; import java.util.Random; public class BlockBonfire extends Block implements ITileEntityProvider { //private static final AxisAlignedBB BOUNDING_BOX = new AxisAlignedBB(x1, y1, z1, x2, y2, z2); //This sets the hitbox for this block, private static final AxisAlignedBB BOUNDING_BOX = new AxisAlignedBB(0.0625 * 3, 0, 0.0625 * 4, 0.0625 * 12, 0.0625 * 15, 0.0625 * 12); public BlockBonfire(String name, CreativeTabs tabs) { super(Material.ROCK); //It's a good idea to put the modid into the block's unlocalised name, to prevent conflicts in the en_US.lang. setUnlocalizedName(Reference.MOD_ID + "." + name); setRegistryName(Reference.MOD_ID, name); setCreativeTab(tabs); this.setLightLevel(5.0F); } /* * The following are obvious. isFullCube checks if this is a full cube (it isn't), isOpaqueCube checks if this cube is opaque (it isn't a cube, so no), * getBlockLayer returns this block is solid, getBoundingBox tells the game the hitbox we defined earlier(?), and addCollisionBoxToList registers the hitbox(?). */ @SuppressWarnings("deprecation") @Override public boolean isFullCube(IBlockState state) { return false; } @SuppressWarnings("deprecation") @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.SOLID; } @SuppressWarnings("deprecation") @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return BOUNDING_BOX; } @SuppressWarnings("deprecation") @Override public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn) { super.addCollisionBoxToList(pos, entityBox, collidingBoxes, BOUNDING_BOX); } //WIP. Pretty much is responsible for the particle effects this block emits. //TODO: Make this emit special particles based on what item is contained. @SideOnly(Side.CLIENT) @SuppressWarnings("incomplete-switch") public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { double d0 = (double)pos.getX() + 0.5D; double d1 = (double)pos.getY() + rand.nextDouble() * 6.0D / 16.0D; double d2 = (double)pos.getZ() + 0.5D; double d3 = rand.nextDouble() * 0.6D - 0.3D; if (rand.nextDouble() < 0.3D) { worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, SoundEvents.BLOCK_FIRE_AMBIENT, SoundCategory.BLOCKS, 1.0F, 1.0F, false); } if(worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if (tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; if(bonfire.shardCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.CRIT, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } else if(bonfire.ashCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_LARGE, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } else if(bonfire.blazerodCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); if(rand.nextDouble() > 0.3D) { worldIn.spawnParticle(EnumParticleTypes.LAVA, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } else { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } } } //This pretty much tells the TileEntity class what to do based on what's right-clicking it. @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { if(!worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if(tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; if(heldItem != null) { if (heldItem.getItem() == ModItems.estus_shard) { if(bonfire.addShard()) { heldItem.stackSize--; return true; } } else if (heldItem.getItem() == ModItems.estus_ash) { if(bonfire.addAsh()) { heldItem.stackSize--; return true; } } else if (heldItem.getItem() == ModItems.estus_flask) { bonfire.estusRestock(heldItem); return true; } else if (heldItem.getItem() == Items.BLAZE_ROD) { if(bonfire.addBlazeRod()) { heldItem.stackSize--; return true; } } else if(heldItem.getItem() == Items.PRISMARINE_SHARD || (heldItem.getItem() == Items.SKULL && heldItem.getMetadata() == 1)) { bonfire.bonfireCraft(heldItem); return true; } } bonfire.removeShard(); bonfire.removeAsh(); bonfire.removeBlazeRod(); } } return true; } //Basically makes a new TileEntity when this is placed. @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityBonfire(); } } And the TileEntity code: [spoiler=Tile Entity code] package com.t10a.crystalflask.tileentity; import com.t10a.crystalflask.init.ModItems; import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; public class TileEntityBonfire extends TileEntity { //Variables telling the TileEntity what's currently contained. public int shardCount = 0; public int ashCount = 0; public int blazerodCount = 0; //This tells the block how to handle adding new Shards. public boolean addShard() { if (shardCount < 1 && ashCount == 0 && blazerodCount == 0) { shardCount++; return true; } return false; } //This tells the block how to handle removing a shard. public void removeShard() { if(shardCount > 0) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); shardCount--; } } //addAsh & removeAsh does the same as addShard & removeShard, but for the Ash item. I COULD unify them under one call, but for now this works. public boolean addAsh() { if(ashCount < 1 && shardCount == 0 && blazerodCount == 0) { ashCount++; return true; } return false; } public void removeAsh() { if(ashCount > 0) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); ashCount--; } } //Same as above, but for blaze rods. I'm definitely going to unify them under 1 call eventually. public boolean addBlazeRod() { if(blazerodCount < 1 && shardCount == 0 && ashCount == 0) { blazerodCount++; return true; } return false; } public void removeBlazeRod() { if(blazerodCount > 0) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(Items.BLAZE_ROD))); blazerodCount--; } } public void bonfireCraft(ItemStack stack) { //TODO: Delete this, and make a dedicated recipe handler, so it's easier to add recipes to. For both me and addon developers. if(stack.getItem() == Items.PRISMARINE_SHARD && blazerodCount > 0) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_shard))); stack.stackSize--; blazerodCount--; } else if(stack.getItem() == Items.SKULL && stack.getMetadata() == 1 && blazerodCount > 0) { worldObj.spawnEntityInWorld(new EntityItem(worldObj, pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, new ItemStack(ModItems.estus_ash))); stack.stackSize--; blazerodCount--; } } //This is a big chunk of code that used to be on the flask. This handles the restocking the uses, and upgrading of the flask when this is called by BlockBonfire. public void estusRestock(ItemStack stack) { if(stack.getItem() == ModItems.estus_flask) { NBTTagCompound nbt; if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); } else { nbt = new NBTTagCompound(); } if (nbt.hasKey("Uses")) { if(shardCount > 0 && nbt.getInteger("Max Uses") < 12) { nbt.setInteger("Max Uses", nbt.getInteger("Max Uses") + 1); shardCount--; } else if(ashCount > 0 && nbt.getInteger("Potency") < 5) { nbt.setInteger("Potency", nbt.getInteger("Potency") + 1); ashCount--; } nbt.setInteger("Uses", nbt.getInteger("Max Uses")); } else { nbt.setInteger("Uses", 1); nbt.setInteger("Max Uses", 1); nbt.setInteger("Potency", 1); } stack.setTagCompound(nbt); } } //This merely saves the variables defined earlier to NBT. @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setInteger("ShardCount", shardCount); compound.setInteger("AshCount", ashCount); return compound; } //Similar to above, but it loads from NBT instead. @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); this.shardCount = compound.getInteger("ShardCount"); this.ashCount = compound.getInteger("AshCount"); } }
  18. Hello, After defining a few variables inside a TileEntity, I want the block itself to emit particle effects based on what variables are true or not. I have this code inside the block's randomDisplayTick so far, but it doesn't do what I want(i.e. it keeps going to the last else case) [spoiler=randomDisplayTick] double d0 = (double)pos.getX() + 0.5D; double d1 = (double)pos.getY() + rand.nextDouble() * 6.0D / 16.0D; double d2 = (double)pos.getZ() + 0.5D; double d3 = rand.nextDouble() * 0.6D - 0.3D; if (rand.nextDouble() < 0.3D) { worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY(), (double)pos.getZ() + 0.5D, SoundEvents.BLOCK_FIRE_AMBIENT, SoundCategory.BLOCKS, 1.0F, 1.0F, false); } if(worldIn.isRemote) { TileEntity tileEntity = worldIn.getTileEntity(pos); if (tileEntity instanceof TileEntityBonfire) { TileEntityBonfire bonfire = (TileEntityBonfire) tileEntity; if(bonfire.shardCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.CRIT, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } if(bonfire.ashCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_LARGE, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } if(bonfire.blazerodCount > 0) { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); if(rand.nextDouble() > 0.3D) { worldIn.spawnParticle(EnumParticleTypes.LAVA, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } else { worldIn.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); worldIn.spawnParticle(EnumParticleTypes.FLAME, d0, d1 + d3, d2, 0.0D, 0.0D, 0.0D, 0); } } }
  19. I found how to use specific potions in recipes. I used TheMasterGabriel's method, by using PotionUtils. Example code for future googlers: new PotionUtils.addPotionToItemStack(new ItemStack(Items.POTIONITEM), PotionTypes.STRONG_HEALING));
  20. Hello, I'd like to find out how to specify a potion in a recipe (i.e. make a Shaped Recipe use a Healing I potion and a few other things, but no other potion is used.). I do know how to make & register normal shaped & shapeless recipes.
  21. Hello, I've been trying to get a custom texture property to work. It is intended to work somewhat like the Damage & Damaged properties in vanilla, but to work with my custom NBT data "Uses" & "Max Uses". However, it seems to only force the last variant in the JSON file that isn't the "empty" variant. Here's my code for the item: [spoiler=Flask Code] package com.t10a.crystalflask.items; import com.t10a.crystalflask.CrystalFlask; import com.t10a.crystalflask.Reference; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.item.*; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.PotionEffect; import net.minecraft.util.*; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nullable; import java.util.List; //Yes, this is a ton of code. I'll try to clean it up whenever I can. public class ItemCrystalFlask extends Item { public ItemCrystalFlask() { //It's a good idea to put the modid into the item's unlocalised name, to prevent conflicts in the en_US.lang. setUnlocalizedName(Reference.MOD_ID + "." + Reference.ItemBase.ESTUS.getUnlocalizedName()); setRegistryName(Reference.ItemBase.ESTUS.getRegistryName()); // this.addPropertyOverride(new ResourceLocation("uses"), new IItemPropertyGetter() { NBTTagCompound nbt; @SideOnly(Side.CLIENT) public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) { return ItemCrystalFlask.getUsable(stack) ? 1.0F : 0.0F; } }); this.addPropertyOverride(new ResourceLocation("used"), new IItemPropertyGetter() { NBTTagCompound nbt; @SideOnly(Side.CLIENT) public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) { nbt = stack.getTagCompound(); return MathHelper.clamp_float((float)nbt.getInteger("Uses") / (float)nbt.getInteger("Max Uses"), 0.0F, 1.0F); } }); // this.addPropertyOverride(new ResourceLocation("empty"), new IItemPropertyGetter() { @SideOnly(Side.CLIENT) public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) { return ItemCrystalFlask.getUsable(stack) ? 0.0F : 1.0F; } }); // setCreativeTab(CrystalFlask.ESTUSTAB); this.setMaxStackSize(1); } private static boolean isUsed(ItemStack stack) { NBTTagCompound nbt; nbt = stack.getTagCompound(); return nbt.hasKey("Uses") && nbt.getInteger("Uses") < nbt.getInteger("Max Uses"); } //Catches whether or not this item is drinkable or not. private static boolean getUsable(ItemStack stack) { return stack.getItemUseAction() == EnumAction.DRINK; } //If it's drinkable, return the drinking time ticks. If not, return 1 tick for the empty/null flask. public int getMaxItemUseDuration(ItemStack stack) { if(getUsable(stack)) { return 32; } else return 1; } //Check whether the item actually has data, and set the EnumAction based on the result. public EnumAction getItemUseAction(ItemStack stack) { NBTTagCompound nbt; if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); } else { nbt = new NBTTagCompound(); } if(nbt.hasKey("Uses")) { if(nbt.getInteger("Uses") <= 0) { return EnumAction.NONE; } else return EnumAction.DRINK; } else { return EnumAction.NONE; } } //Just checking to see if the item can be right-clicked. public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World worldIn, EntityPlayer playerIn, EnumHand hand) { playerIn.setActiveHand(hand); return new ActionResult(EnumActionResult.SUCCESS, stack); } //A pretty big chunk. If this item has metadata, it'll get it. Then, if it has the metadata "Uses", it'll check to see if it is more than 0. If it is, and this isn't on the server side, it'll @Nullable public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) { NBTTagCompound nbt; if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); } else { nbt = new NBTTagCompound(); } if (nbt.hasKey("Uses")) { if(nbt.getInteger("Uses") > 0) { nbt.setInteger("Uses", nbt.getInteger("Uses") - 1); if (!worldIn.isRemote) { if(nbt.getInteger("Potency") >= 0) { entityLiving.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, 25 * nbt.getInteger("Potency"), 3)); } } } } else { nbt.setInteger("Uses", 1); nbt.setInteger("Max Uses", 1); nbt.setInteger("Potency", 1); } stack.setTagCompound(nbt); return super.onItemUseFinish(stack, worldIn, entityLiving); } //Prints info to the item's description. @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void addInformation(ItemStack stack, EntityPlayer player, List lores, boolean b) { if (stack.hasTagCompound() && stack.getTagCompound().hasKey("Uses")) { lores.add("Uses: " + Integer.toString(stack.getTagCompound().getInteger("Uses"))); lores.add("Max Uses: " + Integer.toString(stack.getTagCompound().getInteger("Max Uses"))); lores.add("Potency: " + Integer.toString(stack.getTagCompound().getInteger("Potency"))); } } } And my JSON file: [spoiler=Item JSON file] { "parent": "item/generated", "textures": { "layer0": "crystalflask:items/estus_4" }, "overrides": [ { "predicate": { "used": 1, "uses": 0.25 }, "model" : "crystalflask:item/ItemEstusFlask_3" }, { "predicate": { "used": 1, "uses": 0.50 }, "model" : "crystalflask:item/ItemEstusFlask_2" }, { "predicate": { "used": 1, "uses": 0.75 }, "model" : "crystalflask:item/ItemEstusFlask_1" }, { "predicate": { "empty": 1 }, "model" : "crystalflask:item/ItemEstusFlask_0" } ] } And finally, a sample from the variants used in the JSON file above: [spoiler=Variant JSON file example] { "parent": "item/generated", "textures": { "layer0": "crystalflask:items/estus_0" } }
  22. Whoops, didn't see that. However, after fixing it and adding a tidbit of code that tells the game if it's empty or not, it'll just ignore it and allow the usage when (nearly) empty anyway.
  23. Hello, I've made an item that is drunken to heal the player, and when it is drunk it reduces the uses by one. However, when I drink it in survival, a weird bug occurs: A red -1 appears on the icon, which briefly changes to a -3. When I hit something with it, it'll be instantly destroyed. What have I done wrong? [spoiler=Images] [spoiler=Item Code] package com.t10a.crystalflask.items; import com.t10a.crystalflask.CrystalFlask; import com.t10a.crystalflask.Reference; import com.t10a.crystalflask.init.ModItems; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.MobEffects; import net.minecraft.item.EnumAction; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.potion.PotionEffect; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; import javax.annotation.Nullable; import java.util.List; public class ItemCrystalFlask extends Item { public int uses; public ItemCrystalFlask() { setUnlocalizedName(Reference.MOD_ID + "." + Reference.ItemBase.ESTUS.getUnlocalizedName()); setRegistryName(Reference.ItemBase.ESTUS.getRegistryName()); setCreativeTab(CrystalFlask.ESTUSTAB); this.setMaxStackSize(1); this.uses = 5; this.setMaxDamage(uses); } @Override public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean par4) { list.add("A crystallised flask, containing a magical flame. Drink to restore HP."); list.add("(totally not an estus flask)"); } public int getMaxItemUseDuration(ItemStack stack) { return 32; } public EnumAction getItemUseAction(ItemStack stack) { return EnumAction.DRINK; } public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) { playerIn.setActiveHand(hand); return new ActionResult(EnumActionResult.SUCCESS, itemStackIn); } @Nullable public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) { if (entityLiving instanceof EntityPlayer && !((EntityPlayer)entityLiving).capabilities.isCreativeMode) { --stack.stackSize; } if (!worldIn.isRemote) { entityLiving.addPotionEffect(new PotionEffect(MobEffects.INSTANT_HEALTH)); stack.damageItem(1, entityLiving); } if (entityLiving instanceof EntityPlayer && !((EntityPlayer)entityLiving).capabilities.isCreativeMode) { --stack.stackSize; } return super.onItemUseFinish(stack, worldIn, entityLiving); } }
  24. Added that shapeless recipe code to the recipes class, and it works! Thanks!
  25. Okay, it loads now, and repairs just fine in an anvil. What do I add to a shapeless recipe for it to repair an item?
×
×
  • Create New...

Important Information

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