Jump to content

IceMetalPunk

Members
  • Posts

    402
  • Joined

  • Last visited

Everything posted by IceMetalPunk

  1. Yeah... I'm still having trouble. I suppose if I don't get it working by 2016 (heh, Friday, that is), I can just go the excessive route and make 4 different blocks, one for each state, and replace the blocks in the world according to inputs. I'm just not yet convinced there isn't a more elegant solution to this...
  2. I suspect that your problem here is not quite solved the right way. How does the vanilla diode avoid a circular call? Minecraft has some non-intuitive labeling in places. However, my redstone modding was done in 1.8, so my experience doesn't align exactly. Go back to the diode (repeater) and imitate its naming/passing scheme as applicable, changing only the strengths to suit your goal. I've tried looking into BlockRedstoneDiode/BlockRedstoneRepeater, and it's a mess of obfuscated callbacks. The best I can tell, it's just using the isRepeaterPowered member to determine whether it's on or off, but I can't find anywhere that member is actually set to true or false. I'll keep looking, but for now I don't know where the check for power is coming from in the default classes. *EDIT* Scratch that. Two seconds after posting, I found it. The default diodes actually use two different block IDs each, one for powered and one for unpowered. That works fine if there's only one input and one output, but...here I have two of each. If I were to use the same method, I'd need 4 different blocks to handle every combination of on and off between them. There *must* be a more efficient way to do this, right? As mentioned, I fixed that problem by changing the final parameters to getIndirectPowerLevelTo() from out1,2 to in1,2. That prevented the infinite callbacks (since in1,2 are the opposite sides of out1,2 and out1,2 caused the infinite loops). It's still not outputting anything, though.
  3. 1) >_< D'oh, chalk that up to Eclipse auto-complete and my lack of proofreading. Still, I got no access violation errors, and the block added fine, so that's not the problem. 2) I can be sure, because I've tested all 4 horizontal sides 3) Yup. Whenever there's a block update, like a redstone signal change, to my block, it outputs debug messages just fine saying it's checking side out1 and side out2 for weak power. But still, no output signal is sent. One thing to note is that during testing, I had to change the final parameters of World#getIndirectPowerLevelTo from out1 and out2 to in1 and in2; leaving it as out# ended up causing an infinite loop until a stack overflow crashed the game, with getIndirectPowerLevelTo calling isProvidingWeakPower and vice-versa until crash. Changing it to in1 and in2 fixed that crash, but it still doesn't supply any output signal from any side, despite properly getting into the side conditionals on block update.
  4. As usual, I started out thinking this wouldn't be difficult, and now I'm stuck >_< All I want is for two adjacent sides of my block (which two is determined by block metadata set on placement, like a furnace direction) to output the same redstone signal coming in on the opposite sides. Kind of like if you took two comparators oriented 90-degreed from each other and combined them into one block. Instead...well, the block doesn't give off any redstone signal at all, regardless of what's coming into it from any side. Here's the code; let's play "spot the noob mistake" >_< package com.IceMetalPunk.redplus.blocks; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.util.Direction; import net.minecraft.util.Facing; import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public class BlockRedstoneBridge extends Block { protected BlockRedstoneBridge() { super(Material.circuits); } @Override public boolean canProvidePower() { return true; } @Override public int isProvidingWeakPower(IBlockAccess blockAccess, int x, int y, int z, int side) { World world = (World) blockAccess; int out1 = (world.getBlockMetadata(x, y, z) & 3); int out2 = Direction.rotateLeft[out1]; int in1 = Direction.rotateOpposite[out1]; int in2 = Direction.rotateOpposite[out2]; if (side == out1) { return world.getIndirectPowerLevelTo(x + Facing.offsetsXForSide[in1], y, z + Facing.offsetsZForSide[in1], out1); } else if (side == out2) { return world.getIndirectPowerLevelTo(x + Facing.offsetsXForSide[in2], y, z + Facing.offsetsZForSide[in2], out2); } return 0; } @Override public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_) { int l = MathHelper.floor_double((double) (p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; if (l == 0) { p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 2, 2); } if (l == 1) { p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 5, 2); } if (l == 2) { p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 3, 2); } if (l == 3) { p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 4, 2); } } } (And yes, I just copied the onBlockPlacedBy code straight from BlockFurnace, hence the obfuscated parameter names.)
  5. Okay, then...I think I'll be saving that for a learning experience test mod rather than trying to do it for this actual mod Thanks for all the help!
  6. Well, I have a little experience with ASM in general, but no experience with ASM coremodding nor with Java bytecode. On a scale from "1=a beginner can do it" to "10=you practically need to write the binary bits yourself", where would ASM coremodding rank?
  7. Ah. I was under the impression that setting the item stack's stackTagCompound would cause those tags to be used on the item placed, regardless of what the item was, where applicable. Okay, I'll try doing it with event handlers, then, and hopefully I can make this work. Thanks again.
  8. Ugh. That's annoying. Well, I suppose it's not the worst thing in the world if these gates block light, then. Thanks for your help.
  9. That's not really possible for this. I need this mod to be compatible with being run next to several other popular mods which haven't updated to 1.8 yet, meaning I can't update, either. Is there a way to make it work in 1.7.10?
  10. D'oh, so simple! So now I've fixed that problem, and run into another. I'm trying to copy the cart's NBT data into the dropped ItemStack's stackTagCompound. If I understand correctly, that should mean if it breaks a container cart, it'll drop a container cart item which, when placed, will have the same contents the original cart had, yes? And yet, though I'm not getting any errors, the dropped cart is always empty when placed, even if the original cart had contents. I thought it'd be as simple as using .getEntityData().copy() on the minecart and setting the ItemStack's stackTagCompound to that, but it didn't work. So then I tried creating a new NBTTagCompound and writing the minecart's NBT data to it, then setting *that* to stackTagCompound...still nothing. Here's the current code; why isn't it copying the contents properly, and how can I make it do that? @Override public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) { if (world.isRemote || !(entity instanceof EntityMinecart)) { return; } if (entity.isDead) { return; } NBTTagCompound cartTags = new NBTTagCompound(); entity.writeToNBT(cartTags); ItemStack cartItem = ((EntityMinecart) entity).getCartItem(); cartItem.stackSize = 1; cartItem.stackTagCompound = cartTags; System.out.println(cartItem.stackTagCompound); // tags print out perfectly fine, including contents EntityItem droppedItem = new EntityItem(world, entity.posX, entity.posY, entity.posZ, cartItem); if (entity instanceof EntityMinecartContainer) { try { Field dropConts = EntityMinecartContainer.class.getDeclaredField("dropContentsWhenDead"); dropConts.setAccessible(true); dropConts.setBoolean(entity, false); } catch (NoSuchFieldException e) { System.out.println("No such field!"); } catch (SecurityException e) { System.out.println("Security exception!"); } catch (IllegalArgumentException e) { System.out.println("Illegal Argument!"); } catch (IllegalAccessException e) { System.out.println("Illegal Access Exception!"); } } entity.setDead(); world.spawnEntityInWorld(droppedItem); } If the tags print fine, why don't they get set when I place the cart back down? Why is the inventory lost?
  11. I'm trying to make a custom fence gate, which extends BlockFenceGate, but has slightly different behavior through overriding its onBlockActivated() method. This is all fine and working. The problem is that it doesn't visually connect to fences. Looking through the code, I see that BlockFence#canConnectFenceTo() specifically checks for either normal, opaque blocks, BlockFence, or Blocks.fence_gate. That means it'll never connect to any subclasses of BlockFenceGate. I can make it work by overriding my class's renderAsNormalBlock() method to return true, but then it blocks light, causing odd lighting "glitches". Is there any way to allow a custom fence class to retain its transparency while still allowing fences to connect to them? For instance, is there a way (perhaps through reflection?) to override the default BlockFence#canConnectFenceTo() method so I can have it check for my custom fence gate as well? (I don't know much about how reflection works, but from the little I do know, I haven't seen anything about overwriting methods...) Or is there another way?
  12. Um...it's extremely important. The code is designed to make a copy of the minecart in item form--in other words, to "break it" without its components (i.e. cart and chest, cart and hopper, etc.) or its inventory contents flying everywhere. If that code is running twice per collision, it becomes an inventory duplicator, where players can roll a minecart chest full of items over it and get twice the inventory back, then rinse and repeat. It's a game-breaking bug... I don't know why it's happening, but it definitely needs to be fixed before I can release the mod.
  13. *EDIT* Wait, no, I'm not an idiot. Maybe. For some odd reason, the onEntityCollidedWithBlock() method is getting called twice per collision, both on the server. Why is it doing that? This is the code I'm using, in a custom class that extends BlockRailPowered: @Override public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) { if (world.isRemote || !(entity instanceof EntityMinecart)) { return; } NBTTagCompound cartTags = (NBTTagCompound) entity.getEntityData().copy(); ItemStack cartItem = ((EntityMinecart) entity).getCartItem(); cartItem.stackTagCompound = cartTags; EntityItem droppedItem = new EntityItem(world, entity.posX, entity.posY, entity.posZ, cartItem); entity.setDead(); world.spawnEntityInWorld(droppedItem); System.out.println("World is remote? "+world.isRemote); } As you can see, I'm outputting one message with the world's remote status, yet every collision, I'm getting two identical outputs, both saying the world is not remote, but both spawning item entities. What's with the doubling? Previous post below... >_< Wait, never mind. It turns out, I'm an idiot. I posted this after testing with a plain minecart with no inventory, and I thought it was dropping itself because it was dropping two minecarts, whereas the custom drops were supposed to be just one. After you said calling .setDead() on a regular minecart shouldn't drop anything, I did a bit more testing, and I realized I was making the stupid mistake of spawning my custom itemstacks on both the server and the client, which is why there were two...so the problem I thought I had didn't actually exist >_< Sorry! I do still need to make sure container carts don't drop their items, though, so I'll try to make it work with reflection and if I have any trouble, I'll ask about it here. Thanks for the help!
  14. I can't update to 1.8 as I'm trying to keep my mod compatible next to some popular mods that haven't updated yet. But it seems that wouldn't be what I'm looking for anyway; I need it to not drop *anything*, including the cart itself. This is true not only of container minecarts, but just regular minecarts as well, which don't even have that variable member.
  15. I'm trying to kill a particular minecart, but without it dropping anything. (The reason is that I'm making a rail which destroys carts that travel over it, but with its own custom drops instead of the minecart's default drops.) I haven't been able to figure out how to do this. Whether I cal entity.setDead() or entity.killMinecart(), it always drops its own items. I've even tried setting entity.captureDrops=true before killing it, as the code seemed to suggest that would stop the drops, but it didn't. How can I kill a minecart without any drops? (That includes killing container minecarts without them dropping their contents, too, by the way.)
  16. I've greatly simplified the code by moving the check for redstone power into the onBlockActivated() method, removing the need for a hashmap at all. So now I'm not even touching the breakBlock() method...and still, if I break the bottom of the door, the top remains (invisible as ever). Here's the updated, simplified code. Maybe it'll help someone find something I can do to fix this problem? package com.IceMetalPunk.redplus.blocks; import java.util.Random; import com.IceMetalPunk.redplus.items.RedPlusItems; import net.minecraft.block.Block; import net.minecraft.block.BlockDoor; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.world.World; public class BlockDiamondDoor extends BlockDoor { public BlockDiamondDoor() { super(Material.anvil); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float px, float py, float pz) { // Determine if this block has redstone power boolean thisPowered = world.isBlockIndirectlyGettingPowered(x, y, z); boolean otherPowered = false; // Depending on if this is the top or bottom, determine if the "other" block has redstone power if ((world.getBlockMetadata(x, y, z) & == 0) { otherPowered = world.isBlockIndirectlyGettingPowered(x, y + 1, z); } else { otherPowered = world.isBlockIndirectlyGettingPowered(x, y - 1, z); } // If either half has redstone power, don't change state; otherwise, do what doors do. if (thisPowered || otherPowered) { return false; } else { super.onBlockActivated(world, x, y, z, player, side, px, py, pz); return true; } } @Override public Item getItemDropped(int meta, Random rand, int fortune) { return (meta & != 0 ? null : RedPlusItems.diamondDoor; } @Override // So redstone doesn't open and close the door public void onNeighborBlockChange(World world, int x, int y, int z, Block block) { } } *EDIT* Ah, I fixed it! Turns out, the door destruction is handled in the onNeighborBlockChange() method. By overriding that, I was stopping it from detecting when the bottom half was destroyed. So I had to basically copy/paste the code from the BlockDoor#onNeighborBlockChange() method, and just selectively remove the redstone handling condition. Now everything works perfectly!
  17. Not sure how I missed that; I just added it in now. But sadly, it hasn't solved the problem. The top half still remains after breaking the bottom half. I'm almost ready to just manually set the top half to air in #breakBlock, but I feel like there's some underlying problem which would only be compounded by that.
  18. I'm trying to make a custom door which doesn't open with redstone, only manually, and can't change state if it has a redstone signal. I'm achieving this with a static HashMap associating locations (as x|y|z Strings) with lock states (as Booleans). That all works, and I don't think it has much to do with the problem at hand, though I can't be sure. The problem is that if I break the bottom half of my door, it leaves an invisible, open, top half of the door behind. It's always open regardless of the door's state before breaking. If I break the top half first, then the entire door breaks properly. I don't even see anywhere that the BlockDoor class actually handles its breaking, so I'm not sure what I need to do to make this work. Here's the code I currently have: BlockDiamondDoor.java: package com.IceMetalPunk.redplus.blocks; import java.util.HashMap; import java.util.Random; import com.IceMetalPunk.redplus.items.RedPlusItems; import net.minecraft.block.Block; import net.minecraft.block.BlockDoor; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.world.World; public class BlockDiamondDoor extends BlockDoor { public static HashMap<String, Boolean> stateMap = new HashMap<String, Boolean>(); public BlockDiamondDoor() { super(Material.anvil); } @Override public void onBlockAdded(World world, int x, int y, int z) { boolean powered = world.isBlockIndirectlyGettingPowered(x, y, z); stateMap.put(x + "|" + y + "|" + z, Boolean.valueOf(powered)); int meta = world.getBlockMetadata(x, y, z); if ((meta & == 0) { stateMap.put(x + "|" + (y + 1) + "|" + z, Boolean.valueOf(powered)); } } @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { stateMap.put(x + "|" + y + "|" + z, false); if ((meta & == 0) { stateMap.put(x + "|" + (y + 1) + "|" + z, false); } } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float px, float py, float pz) { if (!stateMap.containsKey(x + "|" + y + "|" + z) || stateMap.get(x + "|" + y + "|" + z).equals(Boolean.valueOf(false))) { super.onBlockActivated(world, x, y, z, player, side, px, py, pz); return true; } else { return false; } } @Override public Item getItemDropped(int meta, Random rand, int fortune) { return (meta & != 0 ? null : RedPlusItems.diamondDoor; } @Override public void onNeighborBlockChange(World world, int x, int y, int z, Block block) { boolean hasPower = world.isBlockIndirectlyGettingPowered(x, y, z) || world.isBlockIndirectlyGettingPowered(x, y + 1, z); stateMap.put(x + "|" + y + "|" + z, Boolean.valueOf(hasPower)); int meta = world.getBlockMetadata(x, y, z); if ((meta & == 0) { stateMap.put(x + "|" + (y + 1) + "|" + z, Boolean.valueOf(hasPower)); } else { stateMap.put(x + "|" + (y - 1) + "|" + z, Boolean.valueOf(hasPower)); } } } Why is the top-hlaf-door remaining behind after breaking the bottom half (and especially why is it not having the same problem in the other way 'round)?
  19. To elaborate, I believe you need to use event.message.getFormattedText() to get the actual string of the text itself.
  20. Some items place entities in the world rather than blocks. I know that paintings and item-frames are entities. I haven't worked with signs, but their text suggests they may be too. When you ask about a "given block", are you asking about a block archetype, or are you asking about an instance (the block currently at a particular position)? I suggest that you put a break point in onNeighborBlockChange, run in the debugger, and start breaking the blocks that interest you. Find out how they decide to drop when support breaks. Tell us what you discover. I can work with either the block singleton or the class itself; either is fine, I'd think. It just has to be the appropriate one. Signs are in fact blocks with tile entities. Two different types of blocks, actually--wall and standing signs--which may be part of the problem here, but it doesn't help me solve the issue. I think the canPlaceBlockAt() method should contain the logic to check whether a neighboring block is required and present. Then when you actually place it, it will convert to the right metadata. You shouldn't have to know the metadata to determine if it a standalone block. That doesn't work. If I try to have a tile entity place a block like this, it just sets the metadata to 0 unless I manually specify a value. For example, using World#setBlock with a wall sign just has it floating in midair, even though there's a valid block on one side for it to attach to. (Note: the block won't always be in the same direction, or even there at all, which is why I need to know the valid metadata.) It's looking more and more like I need to do my own checking and check all 6 sides, though it seems like that would be specific to signs only. I don't have any access to my own laptop right now due to hardware failure, but I'm worried if there are any other similar blocks I'd have to manually handle like this...and then with other mods' blocks, keeping compatibility sounds like a potential nightmare. But if I have to do it, I have to, I guess.
  21. Hm. For some reason, I didn't think the BlockButton class overrode the canPlaceBlockAt method properly, though it seems it does. But that leads to my next question. Keeping in mind I'm getting the blocks from an ItemStack using Block.getBlockFromItem(), for those blocks which must have a certain metadata to be placed in an area, what's the best way to figure out what that metadata should be? For example, if it's a button, would I need to check every surrounding side to see which are solid? Also, it seems that some items don't work properly with that method; if I try something like Block.getBlockFromItem(Items.sign), it actually returns Block.air as though there's no such item as Items.sign. How can I make sure to get the proper block from an ItemStack?
  22. Sorry, typo, it is in fact >, not <. I can't get access to the code right now, but I've already released the mod anyway (using integer amounts and a cooldown timer), so it's not terribly important anymore. If you'd like to see it in action, just add a tick handler that calls EntityPlayerMP#heal(0.05) each tick and see for yourself
  23. Is there any easy way to check if a given block can stand on its own? For example, buttons can't, wall signs can't (but standing signs can), levers can't, etc. I can't use the isNormalCube() because some blocks aren't opaque but can still stand on their own. I'd rather not have to compile a list of blocks that can or can't manually, so if there's some easier way I'm missing, can someone please let me know? Right now, I'm getting the item equivalent, then using onItemUse to simulate the nearest player placing it on the ground nearby, then checking its return value...but that's very hacky, and it still doesn't work for standing signs.
  24. Nope, the potions use the heal() method, but they always heal in integer amounts, so they avoid this problem. I did walk through the callstack...it's a mess of stack and packet handling and obfuscated members, but this is the general process: EntityPlayerMP#heal calls EntityPlayerMP#setHealth, which updates a dataWatcher value. EntityPlayerMP#onUpdateEntity checks if the player's health had changed, and if so, sends an S06PacketUpdateHealth to the client. That packet gets sent over to an INetHandler for processing on the client. That net handler calls the game controller's player's EntityClientPlayerMP#setPlayerSPHealth method to set the health. This calls EntityPlayer#setHealth as well as EntityPlayerSP#setPlayerSPHealth. That then sets the EntityPlayerSP's health (client player's health) and checks previous health minus updated health as a float, and if it's < 0, it sets the EntityPlayerSP#hurtResistantTime to half the max. (This is why I believe the issue to be a float precision error.) And that value is what determines whether the damage animation should be rendered or not. So there's not really anywhere to intercept it, since the client's health is updated in the same method that sets hurtResistantTime. I mean, technically, I could set hurtResistantTime back to 0 after, since it's public, but if you actually *are* getting hurt by something, doing that every step would remove your hit immunity, which is definitely not desired.
  25. Video showcase and explanation of all the WeatherWorks features is now available! I just...don't know how to embed it, so a link will do for now. If someone could let me know how to embed videos on these forums, I'd appreciate that...
×
×
  • Create New...

Important Information

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