Jump to content

SnowyEgret

Members
  • Posts

    112
  • Joined

  • Last visited

Everything posted by SnowyEgret

  1. Everything works fine. Thanks Dieseiben.
  2. getDrops is in the spoiler in reply #2 Something else, the block breaks with no drop, but the player cannot pass through the position vacated by the block.
  3. Is there something else I have missed? Now the block does not drop when I break it. (Same behavior when I don't override harvestBlock) Here my console. Is it normal that removeByPlayer is called twice with different values for willHarvest?
  4. Here is my getDops modeled on BlockFlowerPot: but te is coming up null (maybe because it was broken?). Do I still need to override harvestBlock and pass string path somehow? Or is there a problem with my TileEntity?
  5. I have a field of type String on a TileEntity provided by a block. When I break and then pick up the block, I want the string on the ItemStack in the player's inventory. My intention is to use the string when I place the block again with method public void onBlockPlacedBy(World w, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { I have overridden public void harvestBlock(World worldIn, EntityPlayer playerIn, BlockPos pos, IBlockState state, TileEntity te) { which gives me the string, but I don't know how to put it on the ItemStack's NBT when the player picks the block up. Any help appreciated.
  6. Ok, I had understood the registering it and adding it to the list were two differents steps. I've got the reflection going and my resource pack is on the list. I have build myself a simple tool for building item models in game. Instead of using a seperate applications like MC Model Maker, I am building the model with blocks, selecting them, and then generating a json model. So far, I have this writing to a file which I relocate when I quit the game, but, if not complicated, it would be interesting to load the model at runtime.
  7. Did you get this going? I have a few questions about how this might be implemented. How do you register a custom resource pack and when does it have to be done? Could the pack be modified and a model changed at runtime? If so, how?
  8. I put these printlns in my tile entity's shouldRefresh(): @Override public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) { System.out.println("oldState="+oldState); System.out.println("newSate="+newSate); new Throwable().printStackTrace(); return oldState.getBlock() != newSate.getBlock(); } and get this in the console: [16:26:44] [Client thread/INFO] [sTDOUT]: [org.snowyegret.mojo.block.PrevStateTileEntity:shouldRefresh:30]: oldState=mojo:block_selected [16:26:44] [Client thread/INFO] [sTDOUT]: [org.snowyegret.mojo.block.PrevStateTileEntity:shouldRefresh:31]: newSate=mojo:block_selected [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: java.lang.Throwable [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at org.snowyegret.mojo.block.PrevStateTileEntity.shouldRefresh(PrevStateTileEntity.java:32) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.world.chunk.Chunk.fillChunk(Chunk.java:1425) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.client.network.NetHandlerPlayClient.handleChunkData(NetHandlerPlayClient.java:763) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.network.play.server.S21PacketChunkData.processPacket(S21PacketChunkData.java:64) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.network.play.server.S21PacketChunkData.processPacket(S21PacketChunkData.java:152) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:24) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at java.util.concurrent.FutureTask.run(FutureTask.java:266) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraftforge.fml.common.FMLCommonHandler.callFuture(FMLCommonHandler.java:714) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1078) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.client.Minecraft.run(Minecraft.java:376) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.client.main.Main.main(Main.java:117) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at java.lang.reflect.Method.invoke(Method.java:497) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [16:26:44] [Client thread/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: at net.minecraft.launchwrapper.Launch.main(Launch.java:28) As it turns out, it is this block of code in Chunk.fillChunk() that is calling shouldRefresh(): while (iterator.hasNext()) { TileEntity tileentity = (TileEntity)iterator.next(); if (tileentity.shouldRefresh(this.worldObj, tileentity.getPos(), tileentity.getBlockType().getStateFromMeta(tileentity.getBlockMetadata()), getBlockState(tileentity.getPos()))) invalidList.add(tileentity); tileentity.updateContainingBlockInfo(); } for (TileEntity te : invalidList) te.invalidate(); This must be where minecraft performs a sort of garbage collection by invalidating tile entities which are no longer "referenced" by a block at that position. When the block changes to one that has no new tile entity to overwite it, you don't want it left in the world. I am not sure why this decision is delegated to the tile entity, and why its default implementation returns true if the tile entity is not vanilla (from class TileEntity): private boolean isVanilla = getClass().getName().startsWith("net.minecraft."); but my guess is that the I should be keeping the check for oldState.getBlock() != newSate.getBlock() or I will be populating the world with unused tile entities.
  9. Ok, I have found a fix for my problem, but I have no idea of it's consequences, nor do I understand why it's working. Poking around in Chunk.setBlockState() I came across this block of code which removes tile entities: if (!this.worldObj.isRemote) { if (iblockstate1.getBlock() != state.getBlock()) //Only fire block breaks when the block changes. block1.breakBlock(this.worldObj, pos, iblockstate1); TileEntity te = this.getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK); if (te != null && te.shouldRefresh(this.worldObj, pos, iblockstate1, state)) this.worldObj.removeTileEntity(pos); } else if (block1.hasTileEntity(iblockstate1)) { TileEntity te = this.getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK); if (te != null && te.shouldRefresh(this.worldObj, pos, iblockstate1, state)) this.worldObj.removeTileEntity(pos); } TileEntity.shouldRefresh() looks like this: /** * Called from Chunk.setBlockIDWithMetadata, determines if this tile entity should be re-created when the ID, or Metadata changes. * Use with caution as this will leave straggler TileEntities, or create conflicts with other TileEntities if not used properly. * * @param world Current world * @param pos Tile's world position * @param oldID The old ID of the block * @param newID The new ID of the block (May be the same) * @return True to remove the old tile entity, false to keep it in tact {and create a new one if the new values specify to} */ public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) { return !isVanilla || (oldState.getBlock() != newSate.getBlock()); } In my tile entity class I have overidden it leaving out the test for isVanilla: @Override public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) { return oldState.getBlock() != newSate.getBlock(); } and my problem (and it has been a problem for weeks - I have tried everything) has gone away. Please, if anyone has some insight, please share it. I am wary of the caution in the javadoc comment.
  10. Something else that may be relevant. I sometimes get this warning in the console when the tile entity is coming up null: [12:47:43] [Client thread/WARN]: Needed to grow BufferBuilder buffer: Old size 524288 bytes, new size 2621440 bytes. Does anyone know which class is printing this warning?
  11. Thanks delpi. BTW, I have modified my original post so that the image in the spoiler correctly shows the problem.
  12. After I set my block (BTW, world.setBlock(pos, state, 3) without marking the position for update seems to behave identically) I need to set field prevState (type IBlockState) on the tile entity. When the tile entity is created by my block, field prevState is uninitialized: @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new PrevStateTileEntity(); }
  13. I have placed this line with a breakpoint after the test for a null tile entity (just gets the tile entity again) world.getTileEntity(pos); it takes me here in class RegionRenderCache: public TileEntity getTileEntity(BlockPos pos) { int i = (pos.getX() >> 4) - this.chunkX; int j = (pos.getZ() >> 4) - this.chunkZ; return this.chunkArray[i][j].getTileEntity(pos, Chunk.EnumCreateEntityType.QUEUED); } to here in class Chunk: public TileEntity getTileEntity(BlockPos pos, Chunk.EnumCreateEntityType p_177424_2_) { TileEntity tileentity = (TileEntity)this.chunkTileEntityMap.get(pos); if (tileentity != null && tileentity.isInvalid()) { chunkTileEntityMap.remove(pos); tileentity = null; } if (tileentity == null) { if (p_177424_2_ == Chunk.EnumCreateEntityType.IMMEDIATE) { tileentity = this.createNewTileEntity(pos); this.worldObj.setTileEntity(pos, tileentity); } else if (p_177424_2_ == Chunk.EnumCreateEntityType.QUEUED) { this.field_177447_w.add(pos); } } return tileentity; } tileentity comes back null from chunkTileEntityMap then when p_177424_2_ == Chunk.EnumCreateEntityType.QUEUED, the position is added to field_177447_w which is of type ConcurrentLinkedQueue.
  14. I have a block which provides a tile entity and is rendered by an ISmartBlockModel. Method handleBlockState() is overidden to lookup a model given an IBlockState which is read from an unlisted property which is in turn set from a field on the block's tile entity. This is all based on TheGreyGhost's Minecraft by Example MBE04, and works fine, most of the time. Here is my block: public class BlockSelected extends Block implements ITileEntityProvider { public static final PrevStateProperty prevStateProperty = new PrevStateProperty(); public BlockSelected() { super(Material.clay); } @Override public boolean isOpaqueCube() { return false; } @SideOnly(Side.CLIENT) public EnumWorldBlockLayer getBlockLayer() { return EnumWorldBlockLayer.CUTOUT_MIPPED; } @Override protected BlockState createBlockState() { return new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[] { prevStateProperty }); } @Override public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos) { PrevStateTileEntity tileEntity = (PrevStateTileEntity) world.getTileEntity(pos); IBlockState prevState = null; if (tileEntity != null) { prevState = tileEntity.getPrevState(); } else { System.out.println("tileEntity=" + tileEntity); } return ((IExtendedBlockState) state).withProperty(prevStateProperty, prevState); } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new PrevStateTileEntity(); } } and here is the ISmartBlockModel's relevent code: public class BlockSelectedModel implements ISmartBlockModel { private IBakedModel model; @Override public IBakedModel handleBlockState(IBlockState state) { IBlockState s = ((IExtendedBlockState) state).getValue(BlockSelected.prevStateProperty); model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(s); return this; } } Here is my tile entity with its IBlockState field: public class PrevStateTileEntity extends TileEntity { private IBlockState prevState; private final String PREV_STATE_KEY = "b"; public IBlockState getPrevState() { return prevState; } public void setPrevState(IBlockState state) { prevState = state; } @Override public void writeToNBT(NBTTagCompound tag) { tag.setInteger(PREV_STATE_KEY, Block.getStateId(prevState)); super.writeToNBT(tag); } @Override public void readFromNBT(NBTTagCompound tag) { prevState = Block.getStateById(tag.getInteger(PREV_STATE_KEY)); super.readFromNBT(tag); } @Override public Packet getDescriptionPacket() { NBTTagCompound tag = new NBTTagCompound(); writeToNBT(tag); super.writeToNBT(tag); return new S35PacketUpdateTileEntity(pos, this.getBlockMetadata(), tag); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { readFromNBT(pkt.getNbtCompound()); super.readFromNBT(pkt.getNbtCompound()); } } I am placing the block in the world like this: world.setBlockState(pos, state, 1); world.markBlockForUpdate(pos); PrevStateTileEntity tileEntity = (PrevStateTileEntity) world.getTileEntity(pos); tileEntity.setPrevState(prevState); The problem occurs when the tile entity in getExtendedState() occasionally comes up null during rendering. Without the tile entity, I can not set the unlisted property and the block can't render. This always happens when I set a range of blocks, and then set another adjacent range. The first range renders properly after being set, but then their tile entities come back null after the adjacent range is set. I know the tile entity is null, because I get the println in getExtendedState(). If I set the first range, then walk away into another chunk before coming back and setting the second range, things are ok, and world.getTileEntity(pos) comes back with a valid tile entity. Here is an image of the problem. The outermost ring of blocks are the new setBlockStates. The inner blocks were rendering properly before the outer ring was added. I am guessing they cross a chunk boundary which would explain why some of the inner ones are rendering properly:
  15. Given a reference to a block, how can I look up the name of the sound that is played when the block is placed. More specifically, If I have Block block, at runtime, how can I get String sound for: getWorld().getWorld().playSoundAtEntity(player, sound, 1f, 1f); I want the sound which is played when the block is placed.
  16. Much better. Only one message to server. Testing for modifier presses on the server side only. Thanks. I still want something higher lever like this on the server side (I am wrapping player to encapsulate the mess of getting extended properties): UndoManager um = player.getUndoManager(); Modifiers modifiers = player.getModifiers(); boolean isHollow = modifiers.isPressed(Modifier.SHIFT); boolean isOnSurface = modifiers.isPressed(Modifier.ALT); and this when I add to overlay info to explain what the modifiers do (looks up strings from lang files): info.addModifiers(Modifier.SHIFT, Modifier.ALT); Also useful here: static { for (Modifier m : Modifier.values()) { KEYS_TO_TRACK.add(m.key); } // Other keys to track which are not modifiers KEYS_TO_TRACK.add(Keyboard.KEY_DELETE); }
  17. This is what I am putting in my map: public enum Modifier { // Use ints to avoid Keyboard class on server side // http://www.minecraftforge.net/forum/index.php/topic,31059.msg161734.html#msg161734 // http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes // SHIFT(16), // CTRL(17), // ALT(18), // X(88), // Y(89), // Z(90), // This is what I was getting from printlns SHIFT(42), CTRL(29), ALT(56), X(45), Y(21), Z(44), SPACE(57); public int key; private Modifier(int key) { this.key = key; } // For ModifierMessage.fromBytes() public static Modifier fromKey(int key) { for (Modifier m : values()) { if (m.key == key) { return m; } } return null; } // Convenience method for client side only @SideOnly(Side.CLIENT) public boolean isPressed() { return Keyboard.isKeyDown(this.key); } } Can I hard code the ints instead of e.g. Keyboard.KEY_SPACE or will I run into trouble? Already I was not getting what I expected from Keyboard.getEventKey() in my KeyInputEvent handler. Also, is this the proper usage of @SidefOnly to avoid problems with isPressed() on the server side?. Method isPressed() is intended to used client side only like this: if (Modifier.CTRL.isPressed()) { If this is not recommended I will just dump it and test like this: if (Keyboard.isKeyDown(Modifier.CTRL.key))
  18. I like it. Thanks Ernio. Just one other thing. KeyInputEvent that you suggested ealier in the thread does not have a keystate property like MouseEvent has a buttonstate property. It is difficult to tell if the event is a press or a release, especially in the case of combinations of 3 modifier keys which be pressed or released an in any order. Is there another event, possibly on the forge side, that has key and keystate properties?
  19. Thanks Ernio for pointing this out to me. I am talking about the selectionManager, pickManager, and undoManager discussed a couple of days ago in this topic: http://www.minecraftforge.net/forum/index.php/topic,30991.msg161418.html#msg161418 There is one for each player. Up until now I have just been throwing them out when the player quits the game - there is no real incentive to keep their data. I suppose I can just leave IIEP's saveNBTData(), loadNBTData(), and init() unimplemented?
  20. Something like PlayerInteractEvent.Action.MODIFIER_CTRL would have been helpful. I will use KeyInputEvent and message the server as you suggest. And yes, modifiers must be on a per player basis. Since I'm already tracking other stuff for each player which cannot be put on extended properties, I think I will stick with my class Modifiers and look it up from a Player to Modifiers map.
  21. My mouse input is all nicely picked up on the server thread. Now I would like a way to modify the clicks with a set of defined modifier keys. I need a way to replace Keyboard.isPressed(). Something like Player.isSneaking(). So far I have a class Modifier with enums for the keys I am using for modifiers - shift, click, alt, x, y, z, and spacebar, and a class Modifiers, instantiated on the server side, with a map of Modifier to Boolean and with methods setPressed(), isPressed(). I need an event preferably with a WorldServer property, which allows me to distinguish key presses from releases, so that I can set the modifier state in class Modifiers. First of all, am I completely out to lunch? Have I missed something that forge gives me for managing this? Is my strategy a good one? What is the best event for the job?
  22. Actually, I'm no longer getting the arm swing animation. Its the block break animation that I am still getting - the little puff of dust. No luck with event.useBlock = Result.DENY.
  23. Sweet! Now if I could only stop that break sound and animation on Action.LEFT_CLICK_BLOCK.
  24. I think I abandoned using this event a while back because there was no PlayerInteractEvent.Action.LEFT_CLICK_AIR and I couldn't find a way to stop the break sound and animation on Action.LEFT_CLICK_BLOCK. Is there a way to do this? Is there an event fired when left clicking on air which will give me a remote world?
  25. Just wanted to check that there is no method like onItemUse() or onItemRightClick() for the left mouse click which would give me a remote world. I want to replace the breaking behavior for left mouse click for my Item. Currently I am subscribing to MouseEvents and messaging to the server from the client thread. Does 1.8 offer any new ways to do this?
×
×
  • Create New...

Important Information

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