Posted September 25, 20159 yr Hello everyone, In my mod, I remove block from world using world.setBlockState(myBlockPos, Blocks.air.getDefaultState(), 2); when an explosion occurs to prevent any drops. There is a problem when I try to remove block like redstone dusts or torches, sometimes there still are drops. I use '2' as flags so normaly game engine doesn't care about order, right ? In fact, when I have 4 redstone dusts above dirt blocks and I remove this 8 blocks, all is fine, all is removed, I have no drops. But when I have 5 redstone dusts and I remove this 10 blocks (5 redstone dusts + 5 dirts blocks), sometimes 1 or 2 redstone dusts are dropped, sometimes no drops. It is random, I don't know what happens. I really don't think it come from my side And I can't release my mod with this bug Do you have any ideas ?
September 25, 20159 yr Have you tried using world.setBlockToAir? That might stop some of the randomness. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 25, 20159 yr Author I try it, but nothing changes This method is the same but with flags = 3
September 25, 20159 yr Probably what's happening is you are removing the supporting block before the redstone dust and torches. Then it drops as an item before you removed the actual block. I'm not sure what all the flags represent, but I'm sure one of the flags must allow you to remove the block without updating the surrounding blocks. If not, perhaps you should try removing all the blocks that require a support, then those that don't. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 25, 20159 yr Author perhaps you should try removing all the blocks that require a support When I do it, that's work but no way lol This is for this mod https://www.youtube.com/watch?v=A3_ibDsezwo, and I can't reverse iterate throught the dependency tree to know which I have to remove first That's why I must remove blocks without taking care about orders. Why it's work for 4 blocks with dependency and more it doesn't ?
September 25, 20159 yr Sometimes it works, sometimes it doesn't? Could it be that you are trying to remove some of these blocks client side? I've run into that problem before, myself.... Also, reverse iteration is hardly needed: just work from the highest y to the lowest. That already eliminates anything on floors - only things on walls could then still be an issue... Is there any way you could maybe remove non-opaque blocks first? Because all the things you mention need to be attached to opaque blocks... If anyone has a comprehensive, visual guide to GUIs - don't hesitate to message me. They make my head spin.
September 26, 20159 yr I'm not sure what all the flags represent Is in the Javadoc. 1 causes a block update. 2 sends the change to the client. 4 prevents it from being rerendered. Flags can be added together. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
September 26, 20159 yr Author Sometimes it works, sometimes it doesn't? Could it be that you are trying to remove some of these blocks client side? I've run into that problem before, myself.... Also, reverse iteration is hardly needed: just work from the highest y to the lowest. That already eliminates anything on floors - only things on walls could then still be an issue... Is there any way you could maybe remove non-opaque blocks first? Because all the things you mention need to be attached to opaque blocks... I do this operation serverside only. It's not a simple reverse iteration Because wall hanging object, bed, and other custom blocks could be afftected My mod must be compatible with other mods ... Imagine a mods which add a diamond non-opaque block which need support from above, it will be droped and replaced, so duplicate. I can't release my mod with this potential bug
September 26, 20159 yr Here's an idea: 1. Scan for and store all ItemEntities in the area. 2. Destroy blocks. 3. Destroy all ItemEntities in the area. 4. Do whatever you do to restore blocks in that really cool video ya got. 5. Restore the stored ItemEntities. If anyone has a comprehensive, visual guide to GUIs - don't hesitate to message me. They make my head spin.
September 26, 20159 yr Now I'm curious. How exactly did you do that in the video? I'm assuming you get affected block positions from explosion event, but how did you get them to slowly regenerate, instead of all at once? Did you start a new thread for that? With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 26, 20159 yr Author Now I'm curious. How exactly did you do that in the video? I'm assuming you get affected block positions from explosion event, but how did you get them to slowly regenerate, instead of all at once? Did you start a new thread for that? https://github.com/EyZox/ForgeCreeperHeal/tree/1.2.0 Open source Handler : https://github.com/EyZox/ForgeCreeperHeal/blob/1.2.0/main/java/fr/eyzox/forgecreeperheal/handler/ExplosionEventHandler.java Handler Processing Class : https://github.com/EyZox/ForgeCreeperHeal/blob/1.2.0/main/java/fr/eyzox/forgecreeperheal/worldhealer/WorldHealer.java Data Structure : https://github.com/EyZox/ForgeCreeperHeal/blob/1.2.0/main/java/fr/eyzox/timeline/AbstractTimeline.java I use the tick loop, because Minecraft isn't thread safe
September 26, 20159 yr I use the tick loop, because Minecraft isn't thread safe Yeah, I've learned the hard way Minecraft isn't thread safe, that's why I was so curious about how you accomplished that. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 27, 20159 yr So, I was working on a solution and I came up with this something like this. I'm not sure how you are storing blocks to be removed, but I used a Map<BlockPos, IBlockState>, and an additional map for tile entities. To remove blocks, something like this worked for me: public static List<BlockPos> orderBlocks(List<BlockPos> affectedBlockPositions, World worldObj) { final List<BlockPos> airBlocks = Lists.newArrayList(); final List<BlockPos> fallingBlocks = Lists.newArrayList(); final List<BlockPos> fullBlocks = Lists.newArrayList(); final List<BlockPos> nonFullBlocks = Lists.newArrayList(); Iterator<BlockPos> iterator = affectedBlockPositions.iterator(); while (iterator.hasNext()) { BlockPos pos = iterator.next(); Block block = worldObj.getBlockState(pos).getBlock(); if (block == Blocks.air) airBlocks.add(pos); else if (block instanceof BlockFalling) fallingBlocks.add(pos); else if (block.isFullBlock()) fullBlocks.add(pos); else nonFullBlocks.add(pos); } airBlocks.addAll(fullBlocks); airBlocks.addAll(fallingBlocks); airBlocks.addAll(nonFullBlocks); return airBlocks; } Might not be the most efficient way, but it seems to work. For replacing the blocks, it was similar, but just a bit more complicated. Assuming the blocks are stored in a map like above, replacing them like this should work. Comparator<BlockPos> posComparator = new Comparator<BlockPos>() { @Override public int compare(BlockPos o1, BlockPos o2) { return o1.compareTo(o2); } }; List<Map<BlockPos, IBlockState>> ordered = Lists.newArrayList(); Map<BlockPos, IBlockState> fullBlocks = Maps.newHashMap(); Map<BlockPos, IBlockState> fallingBlocks = Maps.newTreeMap(posComparator); Map<BlockPos, IBlockState> nonFullBlocks = Maps.newHashMap(); ordered.add(fullBlocks); ordered.add(fallingBlocks); ordered.add(nonFullBlocks); for (Map.Entry<BlockPos, IBlockState> entry : blocks.entrySet()) { Block block = entry.getValue().getBlock(); if (block == Blocks.air) continue; else if (block instanceof BlockFalling) fallingBlocks.put(entry.getKey(), entry.getValue()); else if (block.isFullBlock()) fullBlocks.put(entry.getKey(), entry.getValue()); else nonFullBlocks.put(entry.getKey(), entry.getValue()); } If you iterate over the list 'ordered', and then iterate over each map and replace accordingly, you shouldn't have too many problems. Only thing is that doing it like so seems to screw over doors and beds, but it seems you already have a workaround for that. Again, this probably is terribly inefficient, and ugly, but it seemed to work. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 27, 20159 yr Author This is not efficient, not scalable and not custom block compatible. Watch my code, I use a Factory to build each "healable block". Its allow someone who have create a custom block to create its own factory to make it compatable with my mod. I can't use falling, non-opaque etc ... because this is not constant rules. Then, with you method, you sort all block in one time when an explosion occurs. This could create a lag spike for massive explosions.
September 27, 20159 yr This is not efficient, not scalable and not custom block compatible. Watch my code, I use a Factory to build each "healable block". Its allow someone who have create a custom block to create its own factory to make it compatable with my mod. I can't use falling, non-opaque etc ... because this is not constant rules. Then, with you method, you sort all block in one time when an explosion occurs. This could create a lag spike for massive explosions. Yeah that's just something I threw together quickly as a proof of concept. I didn't bother making it scalable or compatible with custom blocks since you already had. It got me thinking, though. Perhaps for each IHealable, you can require a priority. Then, use that priority to determine removal and replace order. Just a thought, though. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 27, 20159 yr Author I ran in debug mod with breakpoint on each EntityItem constructors. Except these f*ck**g chickens who spawn eggs entity items each 5 min, I could see where is the problem by studying the stack trace. World.setBlockState call Chunk.setSate call Block.breakBlock call sometimes Block.updateNeightboor >< So the call to Block.breakBlock in Chunk.setState is the source of this issue. I think I have to create a copy of Chunk.setState method, use reflection to access private Chunk field and then I hope this will be fixed. However, I have an other question if I use reflection. What is the most performant ? Create a wrapper wich contains private chunk field initialized in constructor with reflection and store it in cache while explosion event processing. Or each time use reflection to get field ? I think I will ask this on stackoverflow but if someone have the answers, I take it
September 28, 20159 yr I would think that doing it once per explosion then storing it would be faster, since you're only doing it once. You could try both ways, test performance, and if there is no noticeable difference, you could do what you are most comfortable with. For me though, unless the speed benefits contrast in a large manner, I tend to go for whatever I come up with first that works. With all due respect, sir: I do, what I do, the way I do it. ~ MacGyver
September 28, 20159 yr Author This is what I've done and it's work fine Thank you for your help This topic was very interessant
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.