Jump to content

IceMetalPunk

Members
  • Posts

    402
  • Joined

  • Last visited

Everything posted by IceMetalPunk

  1. You've handed us your code, but you haven't explained what's wrong. Are you getting errors? If so, what are those errors? Or are you not getting errors, but something isn't working properly? If so, what's not working, and what should it be doing that it's not (or what is it doing that it shouldn't)?
  2. As I said, that's what I tried originally, and not only did the sound not play, but I got an error logged when trying to play the sound that it was an "empty sound". That's why I added the domain, and the error disappeared...
  3. The only thing I can think of is code that references the world folder. Because the world folder is on the dedicated server when there is one, any code that references it should probably be in the server proxy. But honestly, I'm just speculating and haven't tried any such code, so it might work in the common proxy as well.
  4. No. isReplaceable() is not a setter, it's a getter. Meaning when you call it, it is returning true or false, meaning whether or not the block is replaceable. It does not set that. You should be checking the value of isReplaceable() to determine if the block is, in fact, replaceable, and if so, using other methods (such as World#setBlockState or something) to replace it.
  5. I'm just trying to get a sound to play, but it's not. It's not playing anything, but there are no errors or warnings logged. For the filenames below, my mod ID is redplusplus. I have a sounds.json file in my assets/redplusplus folder with this in it: { "redplusplus:item.redstone_sandwich.eat": { "sounds": [ "redplusplus:item/redstone_sandwich/eat" ] } } I've also tried leaving out the redplusplus domain from the sound location, but it didn't help. (And of course, if I leave the redplusplus domain out of the sound name itself, I get an "unable to play empty sound" error, so I think it's necessary, yes?) I have a class which extends SoundEvent for easier registration, which just sets the registry name upon initialization: package com.icemetalpunk.redplusplus.sounds; import com.icemetalpunk.redplusplus.RedPlusPlus; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraftforge.fml.common.registry.GameRegistry; public abstract class RedPlusPlusSound extends SoundEvent { public RedPlusPlusSound(String name) { super(new ResourceLocation(RedPlusPlus.MODID, name)); this.setRegistryName(new ResourceLocation(RedPlusPlus.MODID, name)); } public void register() { GameRegistry.findRegistry(SoundEvent.class).register(this); } } And then my sound group classes extend RedPlusPlusSound, taking in a specific name within the group; for instance, I have this class for the sounds related to eating "redstone sandwiches" (an item in my mod): package com.icemetalpunk.redplusplus.sounds; public class SoundRedstoneSandwich extends RedPlusPlusSound { public SoundRedstoneSandwich(String subset) { super("item.redstone_sandwich." + subset); } } So I can have item.redstone_sandwich.eat, and in the future (when this is working), item.redstone_sandwich.super, etc. all be instances of the same class. And then I actually just call these instances' register() methods (defined in the parent RedPlusPlusSound class above) in a handler for the RegistryEvent<SoundEvent> event type. I do have the file assets/redplusplus/sounds/item/redstone_sandwich/eat.ogg which is a non-empty sound. And when I use the /playsound command, that full resource location for my sound does properly auto-complete, so it's definitely registering something with that name. So what would cause the sound not to play if there's no indication of any errors?
  6. I wonder if this is the cause of my previous crashing problem I asked about in another topic that was never answered. If I were to have a recipe in its .json form and also register it through addShapedRecipe / addShapelessRecipe, would that cause a conflict and crash? (The error message received is a generic JVM one, so I didn't know where the problem was other than it only happened when I added the advancement and recipe .json files.)
  7. Can you actually register recipes from the JSON files? I've been using GameRegistry.addShapedRecipe / GameRegistry.addShapelessRecipe in 1.12, and it works just fine...
  8. Since 1.12 is encouraging recipes to be unlocked, I figured I'd make my mod's recipes unlockable in the same way. So as a quick test, I started with just one. I created the assets/redplusplus/advancements/recipes folder and basically copied/pasted one of the vanilla recipe advancements in. Then I changed it to trigger when getting a comparator in your inventory instead of the iron ingot that was there, and to unlock my redplusplus:block_redstone_counter recipe instead of the one it was unlocking. (I also made a copy of the vanilla recipes/root.json advancement, which is just an impossible trigger and nothing else, and parented my advancement to that one just in case.) Then I created the assets/redplusplus/recipes/block_redstone_counter.json file, where I copied the recipe file for an anvil and changed the recipe ingredients and output. The ingredients are all vanilla items, the output is my custom item. I made sure to use the proper domains for all resource locations in these files, whether they're minecraft: or redplusplus: alike. The game loads fine, but when I open a crafting table, it crashes completely. The weird thing is the stacktrace doesn't include any of my code, only vanilla code; can someone help me pinpoint what I've done to cause a fatal error here? Stacktrace: [main/FATAL]: Error executing task java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException: bitIndex < 0: -1 at java.util.concurrent.FutureTask.report(Unknown Source) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.get(Unknown Source) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:54) [Util.class:?] at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1161) [Minecraft.class:?] at net.minecraft.client.Minecraft.run(Minecraft.java:436) [Minecraft.class:?] at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_111] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_111] at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_111] at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?] at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_111] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_111] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_111] at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_111] at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?] at GradleStart.main(GradleStart.java:26) [start/:?] Caused by: java.lang.IndexOutOfBoundsException: bitIndex < 0: -1 at java.util.BitSet.get(Unknown Source) ~[?:1.8.0_111] at net.minecraft.stats.RecipeBook.containsRecipe(RecipeBook.java:35) ~[RecipeBook.class:?] at net.minecraft.client.gui.recipebook.RecipeList.func_194214_a(RecipeList.java:35) ~[RecipeList.class:?] at net.minecraft.client.network.NetHandlerPlayClient.lambda$handleRecipeBook$2(NetHandlerPlayClient.java:1636) ~[NetHandlerPlayClient.class:?] at java.util.ArrayList.forEach(Unknown Source) ~[?:1.8.0_111] at net.minecraft.client.network.NetHandlerPlayClient.handleRecipeBook(NetHandlerPlayClient.java:1634) ~[NetHandlerPlayClient.class:?] at net.minecraft.network.play.server.SPacketRecipeBook.processPacket(SPacketRecipeBook.java:40) ~[SPacketRecipeBook.class:?] at net.minecraft.network.play.server.SPacketRecipeBook.processPacket(SPacketRecipeBook.java:14) ~[SPacketRecipeBook.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:21) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:53) ~[Util.class:?] ... 15 more
  9. Ah, I didn't even look at the date! >_< I may switch over to the newest release, then, at some point. For now, I'll make sure the rest of my mod is functional and then transition after. Thanks for the help!
  10. Ah. I could swear I tried registering a block with the same name as a Minecraft block (and domain), and got an error for trying to register duplicate entries. Then again, I haven't been using the registry events, and have been registering things in the preInit, so I'll try to switch over to the events and see if I can get it working after all. Thank you!
  11. Hm. That's annoying. I'm trying to make my mod as vanilla-feeling as possible, and having a special machine for just one recipe (or a small handful) puts it in the mod-feel realm. Thanks for the info; I'll see if there's some hacky workaround I can come up with, or else just scrap the feature I was planning. *EDIT* Speaking of workarounds, it seems substitution aliases no longer exist. What would be the proper way to replace the vanilla furnace block with a custom one that implements my custom recipes? Because that may work, if it can be done.
  12. Is there a way to register a smelting recipe that requires a certain fuel item? For instance, a recipe that only works if you smelt the item with coal, but not if you smelt it with wood or lava? Since the GameRegistry.addSmelting methods don't have options for that, I thought I'd need to use event handling, but while there are events for pre-and-post brewing, I can't find any for smelting. So how would I do this?
  13. I'm trying to make a simple analog lamp, where the light output equals the max redstone input. I thought this would be simple, but it's not working. This is the relevant code, inside the block class: @Override public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos) { if (world instanceof World) { World theWorld = (World) world; return theWorld.isBlockIndirectlyGettingPowered(pos); } return 0; } @Override public void observedNeighborChange(IBlockState thisState, World world, BlockPos thisPos, Block changedBlock, BlockPos changedBlockPos) { world.setLightFor(EnumSkyBlock.BLOCK, thisPos, world.isBlockIndirectlyGettingPowered(thisPos)); world.checkLight(thisPos); } Some debug output shows that the observedNeighborChange() method is being called correctly, when there's a block state change next to the lamp, and that isBlockIndirectlyGettingPowered() is returning the appropriate redstone signal strength. Yet the block never lights up. Why not? *Update* After more testing, it seems like the block light *is* getting set properly, but only after I exit the world and reload it. I thought checkLight() was supposed to update the light levels; if it's not, what do I need to call to update the light levels without relogging? *UPDATE 2* I fixed it! As it turns out, you need to change the block state for Minecraft to actually update the lighting. Even calling setBlockState with the current state won't work; it needs to be a new block state. So I added a "power" property and set power equal to the redstone input, then I change the blockstate whenever the neighbor changes and it all works fine.
  14. Ah! And now it works! So what's the main benefit to using ModelLoader rather than ItemModelMesher? They seem to work equally well, just with registration occurring at different times. Is there a benefit under the hood I'm not aware of?
  15. Dylem's solution seems to work just fine; when I tried switching the code to ModelLoader.setCustomModelResourceLocation(this.itemBlock, 0, model) [this.itemBlock is of course the ItemBlock instance], it doesn't work, it just shows the purple-and-black undefined model instead again...
  16. Yeah, about 4 minutes after posting, I found it myself Thank you, it seems to work now!
  17. That helps, but what is the ItemModelMesher instance passed as an argument? I assume I can't just create a new instance of it and use that; where does it come from?
  18. I've added a new block to the game, which is fully functional. It has its own block model and textures, which also works fine. But now, I'm trying to give its ItemBlock a model, and it's just not working. I've noticed that quite a few things about item and block registration have changed in Forge for 1.12; how would I properly register an item model? Currently, I'm simply creating an ItemBlock from my block class and registering it with the GameRegistry.findRegistry(Item.class) registry. Then I have a JSON file in my assets/<mod>/models/item folder (using the actual mod ID, not literally "<mod>") which simply defines the model parent to be the block model that already works. But the item isn't showing up; it's just the standard purple-and-black "not found" texture instead. So then I tried adding a call, after registering the item with FML, to ModelBakery.registerItemVariants passing only one registry name to it, in hopes that would work out; it didn't change anything. No errors, just also no item model. I'm probably missing a step or two; what am I missing?
  19. That's what I figured. Thanks for all your help!
  20. Well. I had no idea that a pack.mcmeta file was required for mod resources to prevent it from loading legacy filenames. I added that, and lo and behold, it works now Thank you! I learn something new everyday. A question about convention, though: is it better to include the pack.mcmeta file, or to leave it out and use the old mixed-case filenames instead? I'd assume using the new lower-case names with the pack file is preferred, but I'd like to be sure.
  21. It's been awhile since the last time I've worked on any mods, so I'm probably overlooking something stupid here, but I can't seem to figure out the problem; so here I am. The issue is simple: my language file isn't loading properly. None of the strings (or at least, the creative tab name and the item name for the one block I've added) are translating. Here's a screenshot to show you: I create the tab like this, for reference of the tab name: public static CreativeTabs tab = new CreativeTabs("warpstone") { @Override public ItemStack getTabIconItem() { return new ItemStack(Item.getItemFromBlock(Warpstone.blocks.get("warpstone_ore"))); } }; I set the unlocalized name of the block *and* ItemBlock to "warpstone_ore". And in my mod's src folder, I have the file main\resources\assets\warpstone\lang\en_us.lang With these basic contents: tile.warpstone_ore.name=Warpstone Ore itemGroup.warpstone=Warpstone And yet, as you can see from the screenshot, it's definitely not translating the names at all. What am I doing wrong?
  22. That worked! And it makes sense, too! Thank you! (Also, an interesting note: if the position tags are wrong, and I run the /blockdata command on the block's position, it seems to automatically fix the position in the tile entity tags [showing a successful change to the tags even if I supply an empty tag to the command] and the updates start ticking again. Weird, but interesting.) And yet if I don't load it myself in that onBlockPlacedBy override, when I re-place a broken block, all the tile entity data is lost completely (I just tested it)...
  23. Thank you! It's a bit silly to check what the block should drop after its associated data is already removed, isn't it? But anyway, overriding the removedByPlayer and harvestBlock methods appropriately did the trick, and now it's dropping! It's almost working, except... when I place the block back down, it correctly retains the tile entity data, but it seems as though the tile entity stops ticking/updating. No errors, it just never runs the update code (and yet, the constructor is being called, so the TE is created, just not ticking). Here's the entire TE class, block base class, and specific block class I'm testing with: Tile Entity: package com.icemetalpunk.chaotica.tileentities; import java.util.Iterator; import java.util.Map; import javax.annotation.Nullable; import com.icemetalpunk.chaotica.Chaotica; import com.icemetalpunk.chaotica.ChaoticaUtils; import com.icemetalpunk.chaotica.fluids.FluidTankChaos; import com.icemetalpunk.chaotica.handlers.ChaoticaMessage; import com.icemetalpunk.chaotica.handlers.ChaoticaPacketHandler; import com.icemetalpunk.chaotica.sounds.ChaoticaSoundRegistry; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; import net.minecraft.util.SoundCategory; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; public class TileEntityChaoticCondenser extends ChaoticaTEBase implements ICapabilityProvider, ITickable { protected Fluid fluid = Chaotica.fluids.CORROSIVE_CHAOS; protected int capacity = 5 * Fluid.BUCKET_VOLUME; protected FluidTankChaos tank = new FluidTankChaos(this.capacity); protected int countdown = 40; protected int maxCountdown = 60; // Max amount it resets to public TileEntityChaoticCondenser() { this.tank.setTileEntity(this); System.out.println("Created TE"); } @Override public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { return true; } return super.hasCapability(capability, facing); } @Override public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(this.tank); } return super.getCapability(capability, facing); } // Ticks until the next check for blocks to convert to chaos public int getCountdown() { return this.countdown; } public int getMaxCountdown() { return this.maxCountdown; } public Fluid getFluid() { if (tank.getFluid() == null) { return null; } return this.tank.getFluid().getFluid(); } public void setFluidAmount(int amount) { if (tank.getFluid() == null) { tank.setFluid(new FluidStack(this.fluid, 0)); } tank.getFluid().amount = amount; } @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); NBTTagCompound tankTag = tag.getCompoundTag("Tank"); this.tank.readFromNBT(tankTag); this.countdown = tag.getInteger("Countdown"); } @Override public NBTTagCompound writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); NBTTagCompound tankTag = new NBTTagCompound(); tank.writeToNBT(tankTag); tag.setTag("Tank", tankTag); tag.setInteger("Countdown", this.countdown); return tag; } public int fill(int amount, boolean doFill) { return this.tank.fill(new FluidStack(this.fluid, amount), doFill); } @Override public void update() { System.out.println("Updating TE"); if (--this.countdown == 0) { this.countdown = this.maxCountdown; if (!this.worldObj.isRemote) { IBlockState east = this.getWorld().getBlockState(this.pos.east()); IBlockState west = this.getWorld().getBlockState(this.pos.west()); IBlockState north = this.getWorld().getBlockState(this.pos.north()); IBlockState south = this.getWorld().getBlockState(this.pos.south()); IBlockState up = this.getWorld().getBlockState(this.pos.up()); IBlockState down = this.getWorld().getBlockState(this.pos.down()); // Iterate over the amounts map and add the appropriate amount // of fluid if applicable boolean playSound = false; Iterator<Map.Entry<ChaoticaUtils.BlockPair, Integer>> it = ChaoticaUtils.pairAmounts.entrySet().iterator(); while (it.hasNext()) { Map.Entry<ChaoticaUtils.BlockPair, Integer> entry = it.next(); ChaoticaUtils.BlockPair pair = entry.getKey(); int amount = entry.getValue().intValue(); if (pair.isPair(east.getBlock(), west.getBlock())) { if (this.fill(amount, true) > 0) { playSound = true; this.getWorld().destroyBlock(this.pos.east(), false); this.getWorld().destroyBlock(this.pos.west(), false); } } if (pair.isPair(north.getBlock(), south.getBlock())) { if (this.fill(amount, true) > 0) { playSound = true; this.getWorld().destroyBlock(this.pos.north(), false); this.getWorld().destroyBlock(this.pos.south(), false); } } if (pair.isPair(up.getBlock(), down.getBlock())) { if (this.fill(amount, true) > 0) { playSound = true; this.getWorld().destroyBlock(this.pos.up(), false); this.getWorld().destroyBlock(this.pos.down(), false); } } } if (playSound) { this.worldObj.playSound(null, this.getPos(), ChaoticaSoundRegistry.CONDENSE_CHAOS, SoundCategory.BLOCKS, 1.0f, 1.0f); ChaoticaPacketHandler.INSTANCE.sendToAll(new ChaoticaMessage(ChaoticaMessage.MessageTypes.CONDENSER_LEVEL, this.pos.getX(), this.pos.getY(), this.pos.getZ(), this.tank.getFluidAmount())); } } } } // If shouldHarvest() returns true, this will drop a fully tagged item // instead of an empty one. @Override public boolean shouldHarvest() { return true; } @Override public ItemStack getHarvest() { Block block = this.worldObj.getBlockState(this.pos).getBlock(); Item item = Item.getItemFromBlock(block); ItemStack stack = new ItemStack(item, 1); NBTTagCompound nbt = new NBTTagCompound(); this.writeToNBT(nbt); stack.setTagCompound(nbt); return stack; } } TE Provider Block Base Class: package com.icemetalpunk.chaotica.blocks; import java.util.ArrayList; import com.google.common.collect.Lists; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public abstract class ChaoticaTEBlock extends ChaoticaBlockBase { public ChaoticaTEBlock(String name, Material materialIn) { super(name, materialIn); } // Make sure when the block is dropped, the item retains the TE's data tags @Override public final ArrayList<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { int meta = state.getBlock().getMetaFromState(state); ItemStack ret = new ItemStack(this, 1, meta); NBTTagCompound nbt = new NBTTagCompound(); TileEntity te = world.getTileEntity(pos); NBTTagCompound teTag = new NBTTagCompound(); te.writeToNBT(teTag); nbt.setTag("BlockEntityTag", teTag); ret.setTagCompound(nbt); return Lists.newArrayList(ret); } @Override public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) { if (willHarvest) return true; // If it will harvest, delay deletion of // the block until after getDrops return super.removedByPlayer(state, world, pos, player, willHarvest); } @Override public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te, ItemStack tool) { super.harvestBlock(world, player, pos, state, te, tool); world.setBlockToAir(pos); } @Override public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) { return true; } // When placed, if the item has a tag, set the tile entity's tag /* * FIXME: When placed like this, tags are properly set, but tile entity * fails to update ever after. */ @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { super.onBlockPlacedBy(worldIn, pos, state, placer, stack); if (stack.hasTagCompound() && stack.getTagCompound().hasKey("BlockEntityTag")) { NBTTagCompound tag = stack.getTagCompound().getCompoundTag("BlockEntityTag"); worldIn.getTileEntity(pos).readFromNBT(tag); } } // Tile entity providers should provide the class and name of their tile // entity here for registration. public abstract Class<? extends TileEntity> getTileEntityClass(); public abstract String getTileEntityName(); @Override public boolean hasTileEntity(IBlockState state) { return true; } // Generic createNewTileEntity so only the getTileEntityClass needs to be // specified. @Override public TileEntity createTileEntity(World world, IBlockState state) { try { return this.getTileEntityClass().newInstance(); } catch (InstantiationException e) { e.printStackTrace(); return null; } catch (IllegalAccessException e) { e.printStackTrace(); return null; } } } Block Base Class: package com.icemetalpunk.chaotica.blocks; import com.icemetalpunk.chaotica.Chaotica; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.oredict.OreDictionary; public class ChaoticaBlockBase extends Block { public ChaoticaBlockBase(String name, Material materialIn) { super(materialIn); this.setUnlocalizedName(name).setRegistryName(new ResourceLocation(Chaotica.MODID, name)).setCreativeTab(Chaotica.tab); } protected void register() { GameRegistry.register(this); if (this instanceof ChaoticaTEBlock) { GameRegistry.registerTileEntity(((ChaoticaTEBlock) this).getTileEntityClass(), ((ChaoticaTEBlock) this).getTileEntityName()); } String[] oreDict = this.getOreDict(); if (oreDict != null) { for (String entry : oreDict) { OreDictionary.registerOre(entry, this); } } } // Override this if this block has an oredict entry. public String[] getOreDict() { return null; } } Specific Block Class: package com.icemetalpunk.chaotica.blocks; import javax.annotation.Nullable; import com.icemetalpunk.chaotica.Chaotica; import com.icemetalpunk.chaotica.gui.ChaoticaGuiHandler; import com.icemetalpunk.chaotica.tileentities.TileEntityChaoticCondenser; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class BlockChaoticCondenser extends ChaoticaTEBlock { public BlockChaoticCondenser() { super("chaotic_condenser", Material.ROCK); this.setHardness(3.5F); this.setSoundType(SoundType.STONE); this.register(); } @Override public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, @Nullable ItemStack item, EnumFacing side, float hitX, float hitY, float hitZ) { if (!world.isRemote) { player.openGui(Chaotica.instance, ChaoticaGuiHandler.Guis.CONDENSER.ordinal(), world, pos.getX(), pos.getY(), pos.getZ()); } return true; } @Override public Class<? extends TileEntity> getTileEntityClass() { return TileEntityChaoticCondenser.class; } @Override public String getTileEntityName() { return "ChaoticCondenser"; } } How could the tile entity be created (it is!), its data be accessible (it is! It's displaying properly!), but the update method fail to be called, even though it works fine if I place down a fresh, "clean" block, just not when I place one down which already has tags? How could it be final in the Block class? Then you would not be able to override it. You do know what final means, right? But yes, it does not hurt. Finality is good actually. Yes, I did think it was strange that I was able to override it, but being relatively new to Java, I thought there was some quirk of the language that allowed me to do it...turns out I'm just an idiot and confused the example code I was learning from (which declared it as final) with the base Block class itself Sorry for the confusion!
  24. D'oh! This is what I get for trying to code at 5AM; how did I not see that? >_< Unfortunately, fixing it to return Lists.newArrayList(ret) doesn't seem to fix the problem. It still drops nothing at all no matter how I harvest it. I wasn't sure if there were certain cases where getItemDropped() was called instead of getDrops(), and if so, I didn't want it to drop anything different. Since I can't return an ItemStack with getItemDropped(), I just had it return null for safe measure. But removing that override doesn't help; it still drops nothing. Just because it's final in the Block class, so I kept it that way in my override. Probably not necessary, but it also doesn't hurt, right?
  25. Solve one problem, another shows up. I'm trying to simply make a block, which provides a tile entity, drop a tagged item stack when harvested. In other words, the item stack should have a BlockEntityTag with all the tile entity's data, ready to resume when placed down again. Instead...I'm getting no drops at all. Whether I'm in Creative mode or Survival, using a tool or not, the block doesn't drop anything when broken. Here's the relevant code: @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { return null; } @Override public final ArrayList<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { int meta = state.getBlock().getMetaFromState(state); ItemStack ret = new ItemStack(this, 1, meta); NBTTagCompound nbt = new NBTTagCompound(); TileEntity te = world.getTileEntity(pos); te.writeToNBT(nbt); ret.setTagCompound(nbt); return Lists.newArrayList(new ItemStack(this, 1, meta)); } @Override public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player) { return true; } I'm returning an array containing the item stack from getDrops(), and I've ensured the block is harvestable at all times, so why isn't it dropping anything at all?
×
×
  • Create New...

Important Information

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