huanghongxun / WaterPower

A Minecraft Mod which adds watermills, trousers, rotors, machines.
http://minecraft.curseforge.com/mc-mods/224579-water-power
20 stars 6 forks source link

A Bug with Code in file BlockWaterPower #25

Closed q178666380 closed 8 years ago

q178666380 commented 8 years ago

the BlockContainer.TEMPORARYTILEENTITY_LOCAL is static,it mean every instance shared this variable,when use industrialcraft wrench to remove water generator,industrialcraft wrench will first call method getDrops(),than call breakBlock()(this method called by world.setBlockToAir(III)),it mean the TEMPORARYTILEENTITY_LOCAL will store this water generator next time when i use picks or other tools to dig block which extend from BlockContainer and the block is not a TileEntity,the block of drops will replace by TEMPORARYTILEENTITY_LOCAL,such like i dig a ore,than i get a water generator

The following suggestions may solve the problem set TEMPORARYTILEENTITY_LOCAL no-static or when breakBlock() method called,clear TEMPORARYTILEENTITY_LOCAL before do other code

huanghongxun commented 8 years ago

I see. When I dug the block by a pickaxe, the system firstly called breakBlock, then called getDrops but when I used a wrench to do the same thing, IC2 firstly called getDrops then called breakBlock.

I missed this difference..

huanghongxun commented 8 years ago

Could you test new codes? I'm not sure it's fixed.

q178666380 commented 8 years ago

i have test this code,look like bug do not happen any more public void breakBlock(World world, int x, int y, int z, Block block, int meta) { TEMPORARYTILEENTITY_LOCAL.remove();//first remove any exist TileEntity TileEntity te = world.getTileEntity(x, y, z); ...... } this maybe nouseful,if some tools also call get drop first that will make the same bug,so i think set TEMPORARYTILEENTITY_LOCAL to non-static is the best

huanghongxun commented 8 years ago

Making the variable non-static will not fix the bug. It will happen again when a player do it among blocks that have same id but not same metadata.

Does "nouseful" mean "noiseful"?

q178666380 commented 8 years ago

Different instance have different memory of TEMPORARYTILEENTITY_LOCAL,so why bug will happen again or could you tell me how to operate will cause bug

huanghongxun commented 8 years ago

Blocks which have the same id and different metadata will share one instance. And these blocks are not the same for players. So bug will happen when digging or wrenching blocks that are all watermill.

q178666380 commented 8 years ago

Instance of block be same only when mod to register this block but when blocks are on ground,if their have the same instance,it mean their have the same position forge will call clone() method to copy new block to place to ground, and I have test code(set to non-static) by wrench ,buildcraft pipeItemsStripes,this bug has never occur yet

huanghongxun commented 8 years ago

Have you tested blocks among watermills? If you test blocks that have different ids, the bug will be fixed certainly.

each block has its own TileEntity instance, but share one Block instance, have you got memory address of these blocks? A block class will be instantiate once for registering, then the instance will be put to BlockRegistry map. Or why the argument list of methods in class Block has block position? Why does not class Block have field x, y or z?

虽然不知道是不是Chinese但是我觉得写英文好辛苦。

q178666380 commented 8 years ago

嘛,我测试的时候貌似就没有出现过那个bug了,多个方块的话实例是有多个的吧,就算是同一个实例,发生那个bug的条件就是要先有一个TileEnity的方块而且是先被调用getDrop方法。然后再有一个方块不是TileEnity被挖才会发生这个bug,但是相同id的物品类型都是同一类的吧

huanghongxun commented 8 years ago

你应该是没有研究过MC的方块物品注册? 所有同Id的方块共用一个instance就是在物品注册的时候确定的。 如果一个方块一个instance,内存不炸就怪了。 说过16种水利发电机公用一个Id,metadata不同? 只不过实现的时候放下来以后都变成metadata 0,数据值存到TileEntity里。 但还是有一些方块不是这么实现的,比如矿物,不过矿物不能Wrench所以bug出不来。 但是bug总归还是有的,只不过暂时没有触发方式。 这么做目的是防范于未然。

q178666380 commented 8 years ago

参考了TE的代码 在BlockWaterPower.java中重写 public void onBlockHarvested(World world, int x, int y, int z, int meta, EntityPlayer player)方法, 并执行以下两行代码 super.dropBlockAsItem(world,x,y,z,meta,0); world.setBlock(x,y,z,Blocks.air,0,7); 这样做可以保证先调用getDrops()方法,再调用breakBlock()方法 说到底,breakBlock()方法就已经把方块和实体全部移除了,你本来就不应该记录TileEntity

huanghongxun commented 8 years ago

记录TileEntitiy的方法是来自GT的