-
Posts
424 -
Joined
-
Last visited
Everything posted by Daeruin
-
I created a tile entity with inventory and a GUI. It was challenging to my amateur programming skills. Now I want to create several more containers of different sizes. I made my tile entity into an abstract class and create two subclasses to override the getSizeInventory and getName methods. That has worked fine so far—at least my original container now works by using one of the subclasses I created. I still haven't built the additional GUI to handle the different number of slots of the other subclass, or registered the block or created the texture, etc. What I'm wondering is if I can instead create a variable to represent the number of inventory slots, set it in the tile entity's constructor, and use it in getSizeInventory rather than using a hard-set int value. I started along that path but didn't get very far, so I'm not sure if I was just dumb to try or if I'm missing something. It would be cool if I didn't have to subclass my tile entity a dozen times for all the different containers I want to make.
-
[SOLVED] [1.8] Container that keeps inventory when broken
Daeruin replied to Daeruin's topic in Modder Support
Nice tip. Worked great. Thanks! -
[SOLVED] [1.8] Container that keeps inventory when broken
Daeruin replied to Daeruin's topic in Modder Support
Thank you, Choonster, that worked! It took me a while to figure out how to use the "BlockEntityTag" sub-compound. Google ended up taking me to a couple other posts you made to help out other folks. I ended up having to also override getItemDropped to prevent two copies of the container from dropping when broken. Finished code, for the record: // Keep inventory when block is broken @Override public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { List<ItemStack> ret = super.getDrops(world, pos, state, fortune); PrimalTileEntity te = world.getTileEntity(pos) instanceof PrimalTileEntity ? (PrimalTileEntity)world.getTileEntity(pos) : null; if (te != null && Item.getItemFromBlock(state.getBlock()) != null) { ItemStack stack = new ItemStack(this); NBTTagCompound tag = new NBTTagCompound(); NBTTagCompound tagCompound = new NBTTagCompound(); te.writeToNBT(tag); tagCompound.setTag("BlockEntityTag", tag); stack.setTagCompound(tagCompound); ret.add(stack); } return ret; } @Override public boolean removedByPlayer(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(world, pos, player, willHarvest); } @Override public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, TileEntity te) { super.harvestBlock(world, player, pos, state, te); world.setBlockToAir(pos); } @Override public Item getItemDropped(IBlockState state, Random rand, int fortune) { return null; } -
I am trying to create a container that keeps its inventory when broken. I have the tile entity and container block created. I can place and break the container as expected. I just want it to maintain its inventory when broken, so its contents aren't spilled out and when I re-place the container, its inventory is the same as when it was broken. I've done some searching and haven't really found anything. Any ideas how to do this? What methods do I need to be looking at? I know the breakBlock method is what causes the container's contents to spill out when the container is broken. Do I override it?
-
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Fair enough. I hadn't thought about Eclipse's outline view. My classes are small enough that I haven't used outline view much, except when looking at some large vanilla classes. Thanks to everyone for your input on this. I guess it's about time to call this one resolved, since I've gone fairly far off topic, and the original issue is fixed. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
What's the advantage of having a dozen event handler methods in the same class versus different classes? I'm not trying to be difficult, I just want to learn. It seems like using multiple classes is better organized and easier to find things. -
Couldn't you also make it player-specific by checking the player's ticksExisted in your tick counter? Like this: if (event.player.ticksExisted % 20 == 0)
-
Probably a PlayerTickEvent. Are you familiar with Forge's event system?
-
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
The options I've thought, and don't like, are: a. Make the log list static and keep it in BreakEvent, then simply refer to it from HarvestEvent when I need to check if something is a log. I don't like this idea because it feels messy. There's no particular reason why the list should reside in one or the other. b. Put both events in the same class. I don't like this idea because I've been keeping each event in its own class. It feels more organized and keeps my classes from getting really huge. c. Create a new class to hold the list. This feels slightly better, because it would provide a place to keep code that's common to multiple event classes. But so far I only have the one tiny thing to put in it. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
1) I didn't include my entire class and misplaced the isLog variable as I was copying the code into my post. isLog was actually part of the onDig method. But your comment made me realize I could do everything without that variable, so thanks for that. 2) I only included the part of my code I wanted feedback on. I'm actually going to cancel the event if the player isn't using a specific tool, along with a few other things that aren't really relevant to the question at hand. Any advice on where to create the OreDictionary list if I need to use it in multiple events? Or do I create a separate list in each event class? Does it even matter? New code, in case it matters: public class BreakSpeedEvent { List woodList = OreDictionary.getOres("logWood"); @SubscribeEvent public void onDig(BreakSpeed event) { Block block = iblockstate.getBlock(); for (int i=0; i < woodList.size(); i++) { if (OreDictionary.itemMatches((ItemStack) woodList.get(i), new ItemStack(block), false)) { // Code to cancel event if player is holding wrong tool, and other stuff } } } } -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
This is what I came up with. It seems to be working well. What if I need to do something similar in another event, like a harvest event? Would it make sense to create the list somewhere else, like in my Main class, and then iterate through it separately in each event? public class BreakSpeedEvent { List woodList = OreDictionary.getOres("logWood"); boolean isLog = false; @SubscribeEvent public void onDig(BreakSpeed event) { Block block = iblockstate.getBlock(); for (int i=0; i < woodList.size(); i++) { if (OreDictionary.itemMatches((ItemStack) woodList.get(i), new ItemStack(block), false)) { isLog = true; break; } } } } -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Yes, I was thinking of checking if something is a log, for example in a HarvestDropsEvent. Thanks for the advice. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Yes, I was thinking of checking if something is a log, for example in a HarvestDropsEvent. Thanks for the advice. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Got it. I am planning to add many types of wood to my mod eventually. Each would have a regular version and a version stripped of bark. That's why I was considering using TE in the first place. Another factor is referring to all these types of wood in events. The Ore Dictionary makes multiple wood types easy to use for recipes. Can it be used in events? Or is there some other easy way to avoid messiness if you have four or five different log classes to refer to? -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Got it. I am planning to add many types of wood to my mod eventually. Each would have a regular version and a version stripped of bark. That's why I was considering using TE in the first place. Another factor is referring to all these types of wood in events. The Ore Dictionary makes multiple wood types easy to use for recipes. Can it be used in events? Or is there some other easy way to avoid messiness if you have four or five different log classes to refer to? -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
I got around to reading about TileEntities today. It looks like each tile entity block is a separate object in memory. Is that what you mean by TileEntities being more expensive? I wonder how it would affect performance if every block of wood in the world was a TileEntity. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
I got around to reading about TileEntities today. It looks like each tile entity block is a separate object in memory. Is that what you mean by TileEntities being more expensive? I wonder how it would affect performance if every block of wood in the world was a TileEntity. -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
I'll have to give that a try. Thanks for the feedback! -
[1.8.9] [SOLVED] Custom log somehow gets wrong metadata
Daeruin replied to Daeruin's topic in Modder Support
Dang. I think I read that somewhere but forgot about it. I kept wondering why vanilla had two log classes. What about using a tile entity instead? I've been thinking about adding some of my own wood types in the future. It seems ridiculous to keep creating new log classes just because of that. -
I'm making a custom log. The idea is that if the player sneaks while breaking vanilla logs, it drops bark and replaces the log with a stripped log. I have a custom log class that extends BlockLog. I'm using a HarvestDropsEvent for the drops and the log swap. I have textures and models for all the stripped logs. Everything was working fine when I only had four variants (to match vanilla's BlockOldLog), but when I tried to add the two wood variants from BlockNewLog, that's when things went wrong. I had to do some weird things to make the metadata work for the block orientation while still grabbing the right texture. The code feels kludgy to me but I'm not sure what to do to make it better. Maybe two custom classes, one for BlockOldLog and one for BlockNewLog? Bitwise operators are new to me so I've been reluctant to mess with the switch statements for the log orientation. Anyway, after making the changes, suddenly oak and jungle wood get swapped out with the acacia and dark oak textures. I've put in a ton of sysout statements to track the meta value. Everything looks right, the log has all the right metadata before and after I call event.world.setBlockState in the harvest drops event, and yet somehow, at some point after the harvest event places the correct block, it's getting changed to the wrong block. I've removed all the sysout statements from the code below, but here's a pastebin to show what the logs look like: http://pastebin.com/dpTB2ZsQ. You can see the metadata is 0 (log_oak_stripped) all the way down until after the harvest event, when it suddenly switches to 4 (log_acacia_stripped). My custom log class: public class PrimalBlockStrippedLog extends BlockLog { public static final PropertyEnum VARIANT = PropertyEnum.create("variant", PrimalBlockStrippedLog.EnumWoodType.class, new Predicate() { public boolean apply(PrimalBlockStrippedLog.EnumWoodType type) { return type.getMetadata() < 6; } public boolean apply(Object p_apply_1_) { return this.apply((PrimalBlockStrippedLog.EnumWoodType)p_apply_1_); } }); public PrimalBlockStrippedLog() { this.setDefaultState(this.blockState.getBaseState() .withProperty(VARIANT, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDOAK) .withProperty(LOG_AXIS, BlockLog.EnumAxis.Y)); setHardness(2.0F); setResistance(0.5F); //setStepSound(Block.soundTypeWood); this.setCreativeTab(PrimalCreativeTabs.tabPrimalcraft); } @SideOnly(Side.CLIENT) public void getSubBlocks(Item block, CreativeTabs tab, List list) { System.out.println("[getSubBlocks] called"); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDOAK.getMetadata())); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDSPRUCE.getMetadata())); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDBIRCH.getMetadata())); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDJUNGLE.getMetadata())); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDACACIA.getMetadata())); list.add(new ItemStack(block, 1, PrimalBlockStrippedLog.EnumWoodType.STRIPPEDDARKOAK.getMetadata())); } public IBlockState getStateFromMeta(int meta) { int vanillaMeta = meta; // Used so vanilla functions still work if (meta > 3) vanillaMeta = meta - 4; // This is a BlockNewLog; adjust meta down to match vanilla log classes IBlockState iblockstate = this.getDefaultState().withProperty(VARIANT, PrimalBlockStrippedLog.EnumWoodType.byMetadata(meta)); switch (vanillaMeta & 12) { case 0: iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Y); break; case 4: iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.X); break; case 8: iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.Z); break; default: iblockstate = iblockstate.withProperty(LOG_AXIS, BlockLog.EnumAxis.NONE); } return iblockstate; } @SuppressWarnings("incomplete-switch") public int getMetaFromState(IBlockState state) { System.out.println("[getMetaFromState] called"); int i = 0; int meta = ((PrimalBlockStrippedLog.EnumWoodType)state.getValue(VARIANT)).getMetadata(); if (meta > 3) meta = meta - 4; // This is a BlockNewLog; adjust meta down to match vanilla log classes i = i | meta; // i = i | ((PrimalBlockStrippedLog.EnumWoodType)state.getValue(VARIANT)).getMetadata(); switch ((BlockLog.EnumAxis)state.getValue(LOG_AXIS)) { case X: i |= 4; break; case Z: i |= 8; break; case NONE: i |= 12; } return i; } @Override protected BlockState createBlockState() { return new BlockState(this, new IProperty[] {VARIANT, LOG_AXIS}); } protected ItemStack createStackedBlock(IBlockState state) { return new ItemStack(Item.getItemFromBlock(this), 1, ((PrimalBlockStrippedLog.EnumWoodType)state.getValue(VARIANT)).getMetadata()); } public int damageDropped(IBlockState state) { return ((PrimalBlockStrippedLog.EnumWoodType)state.getValue(VARIANT)).getMetadata(); } public static enum EnumWoodType implements IStringSerializable { STRIPPEDOAK(0, "log_oak_stripped"), STRIPPEDSPRUCE(1, "log_spruce_stripped"), STRIPPEDBIRCH(2, "log_birch_stripped"), STRIPPEDJUNGLE(3, "log_jungle_stripped"), STRIPPEDACACIA(4, "log_acacia_stripped"), STRIPPEDDARKOAK(5, "log_dark_oak_stripped"); private static final PrimalBlockStrippedLog.EnumWoodType[] META_LOOKUP = new PrimalBlockStrippedLog.EnumWoodType[values().length]; private final int meta; private final String name; private final String unlocalizedName; private EnumWoodType(int meta, String name) { this(meta, name, name); } private EnumWoodType(int meta, String name, String unlocalizedName) { this.meta = meta; this.name = name; this.unlocalizedName = unlocalizedName; } public int getMetadata() { return this.meta; } public String toString() { return getName(); } public static PrimalBlockStrippedLog.EnumWoodType byMetadata(int meta) { if (meta < 0 || meta >= META_LOOKUP.length) { meta = 0; } return META_LOOKUP[meta]; } public String getName() { return this.name; } public String getUnlocalizedName() { return this.unlocalizedName; } static { PrimalBlockStrippedLog.EnumWoodType[] var0 = values(); int var1 = var0.length; for (int var2 = 0; var2 < var1; ++var2) { PrimalBlockStrippedLog.EnumWoodType var3 = var0[var2]; META_LOOKUP[var3.getMetadata()] = var3; } } } } My harvest event (this isn't the whole thing, just the relevant part): public void onDrop(HarvestDropsEvent event) { Block block = event.state.getBlock(); if (event.harvester != null) { boolean blockIsLog = false; int meta = 0; EntityPlayer player = event.harvester; boolean holdingTool = false; boolean holdingNonTool = false; boolean holdingNothing = false; boolean isSneaking = false; if (player.getHeldItem() != null) { if (player.getHeldItem().getItem() instanceof ItemTool) holdingTool = true; else holdingNonTool = true; } else holdingNothing = true; if (player.isSneaking()) isSneaking = true; // Regular log if (block == Blocks.log) { blockIsLog = true; meta = block.getMetaFromState(event.state); } if (block == Blocks.log2) { blockIsLog = true; meta = block.getMetaFromState(event.state) + 4; // Adjust meta to match my PrimalBlockStrippedLog class } if (blockIsLog) { if (holdingTool) { if (!isSneaking) { return; // Allow to drop log as normal } else if (isSneaking) { event.drops.clear(); // Don't drop log event.drops.add(new ItemStack(PrimalItemRegistry.ItemBarkOak, 4)); // Drop 4 bark event.world.setBlockState(event.pos, PrimalBlockRegistry.log_stripped.getStateFromMeta(meta)); // Replace log with stripped log } } Blockstate JSON:
-
[SOLVED] [1.8.9] Wrong texture variant when placing log horizontally
Daeruin replied to Daeruin's topic in Modder Support
Well, that was dumb of me. New getMetaFromState: public int getMetaFromState(IBlockState state) { int i = 0; i = i | ((PrimalBlockStrippedLog.EnumWoodType)state.getValue(VARIANT)).getMetadata(); switch (PrimalBlockStrippedLog.SwitchEnumAxis.AXIS_LOOKUP[((PrimalBlockStrippedLog.EnumAxis)state.getValue(LOG_AXIS)).ordinal()]) { case 1: i |= 4; break; case 2: i |= 8; break; case 3: i |= 12; } return i; } Seems to be working great so far. Thanks for the tip. -
I'm trying to create custom logs. The overall goal is that if you sneak while breaking a log, it drops bark and gets replaced with a stripped log. I've created a custom block class for the properties and a corresponding item class. I have two variants so far, oak and birch. Everything is working fine, except that when I place the stripped oak horizontally, it uses the birch texture instead. Any idea what's going on? My custom log block class: My log item class: The block register class: JSON files for stripped oak variant:
-
Your event handler class name: public class IYPEventHandler How you're registering the event in CommonProxy: MinecraftForge.EVENT_BUS.register(new IYPDropHandler()); Notice anything peculiar?
-
[1.8.9] [SOLVED] PlayerTickEvent not applying damage when it should
Daeruin replied to Daeruin's topic in Modder Support
IT WORKS! Also, I need to quit being a doofus and remember not to test this kind of stuff while in Creative Mode. -
[1.8.9] [SOLVED] PlayerTickEvent not applying damage when it should
Daeruin replied to Daeruin's topic in Modder Support
So I spent a while learning about packets and set up a very basic thirst system while following some tutorials by coolAlias, diesieben, and jabelar. Cool stuff. After doing all that, I changed my PlayerTickEvent to listen on the client side and created a packet (called PlayerToeStub, haha) to perform the damage on the server side. Unfortunately, it doesn't seem to work. I registered the packet as a server message and set up the handler to run on the correct thread (I think) but a check for world.isRemote inside the runnable shows that it still seems to be running on the client, and the damage doesn't get applied. I must be doing something wrong, but I don't know what it is. Any ideas or advice? PlayerTickEvent (listens on client for the right conditions, then sends the packet) Packet (sends damage to be applied to player on server) (Side note: I just realized that I'm creating a playerId variable but not using it anywhere—I think that's a holdover from the thirst system that I started to implement based on something I read. But I'm not using the playerId in my thirst packet, either, and everything seems to be working fine in single player mode. Maybe it will become problematic with multiple players?) Packet registration in CommonProxy: