Jump to content

lyn mimistrobell

Members
  • Posts

    24
  • Joined

  • Last visited

Everything posted by lyn mimistrobell

  1. It seems there are a number events/methods used when a block is placed: canPlaceBlockOnSide getStateForPlacement onBlockPlacedBy Are there any more? Are these always called in this order? I have a block where I want to remember the TE against which the block was placed - let's call it targetTE - (so it can act as an interface to that targetTE). I implemented canPlaceBlockOnSide to verify that the user actually clicked a TE and not a regular block; e.g. it returns false if you try to place the block against dirt but true if you place the block (shift-click) against a chest. I implemented getStateForPlacement to rotate my block the correct way to face the targetTE. I believe both methods are called before the block is actually placed. I also implemented neighborChanged to break (and drop) my block if the targetTE is removed. Which method would be the best method to store the targetTE? onBlockPlacedBy doesn't provide the EnumFacing I need to find the block (and TE) the user clicked. Should I store the targetTE or determine it every time I need it (using my blocks PropertyDirection) - which may be every tick? I couldn't find any documentation on the order of events for placing a block - is there any?
  2. Wow I totally missed that it's parsing the NBT to a new local ItemStack and then ignores it... thanks.
  3. I did add more debugging and found the issue is with ItemStack.deserializeNBT which doesn't handle the NBT (created with ItemStack.serializeNBT) properly (created a separate topic for that). I use Eclipse Neon 2 and I know how to set breakpoints (unfortunately, they didn't help for this problem) - I didn't think use the property as watchpoint but I'll do that next time. Thanks.
  4. ItemStack: public NBTTagCompound serializeNBT() { NBTTagCompound ret = new NBTTagCompound(); this.writeToNBT(ret); return ret; } public void deserializeNBT(NBTTagCompound nbt) { // TODO do this better while respecting new rules final ItemStack itemStack = new ItemStack(nbt); this.stackTagCompound = itemStack.stackTagCompound; this.capNBT = itemStack.capNBT; } So effectively, that's what those methods already do...
  5. I have an ItemStack with a single piece of e.g. coal; when I call itemStack.serializeNBT I get: {id:"minecraft:coal",Count:1b,Damage:0s} When I then try to deserialize the tag I get: 1xtile.air@0 I found that deserializeNBT calls new ItemStack(compound); it calls Item.getByNameOrId("minecraft:coal") which returns 1xitem.coal@0. For some reason, this fails and causes ItemStack to have 1xtile.air@0 : this.item = Item.getByNameOrId("minecraft:coal"); This works, however: itemStack = new ItemStack(Item.getByNameOrId("minecraft:coal")); Am I doing something wrong calling nbt.setTag("mystack", itemStack.serializeNBT()); and itemStack.deserializeNBT(tag.getTag("mystack")); ?
  6. Hi, For my mod I created a custom Capability that handles fuel burning (initial burn time, remaining burn time, etc.): My TE calls setFuelItem with an ItemStack that has coal; the log shows that the coal was accepted: [18:32:02] [Server thread/INFO] [RadioTools]: [TileEntityFurnaceGenerator.update] fuelItemStack: 1xtile.blockCoal@0 [18:32:02] [Server thread/INFO] [RadioTools]: [FurnaceGeneratorHandler.setFuelItem] fuelItem: 1xtile.blockCoal@0 [18:32:02] [Server thread/INFO] [RadioTools]: [FurnaceGeneratorHandler.setFuelItem] this.fuelItem: 1xtile.blockCoal@0, initialBurnTime:200 Next, sendBlockEntity calls TE.getUpdatePacket which calls TE.getUpdateTag which tries to get the NBT of my Handler, but for some reason this.fuelItem was reset: [18:32:02] [Server thread/INFO] [RadioTools]: [FurnaceGeneratorHandler.serializeNBT] this.fuelItem=0xtile.air@0 [18:32:02] [Server thread/INFO] [RadioTools]: [FurnaceGeneratorHandler.serializeNBT] tag={remainingBurnTime:200,fuelItem:{id:"minecraft:air",Count:0b,Damage:0s}} The only places where I expect the fuel to be updated are setFuelItem and decreaseRemainingBurnTime when it finished burning but that doesn't happen until 10 seconds later: [18:32:12] [Server thread/INFO] [RadioTools]: [FurnaceGeneratorHandler.decreaseRemainingBurnTime] Finished burning I'm probably missing something obvious but I right now I'm blinded and I can't find it... The only other logging was from the client which (of course) deserialized a tag with fuelItem air; deserializeNBT is never called on the server. Full log: Anybody with good eyes? Linda
  7. Hi, It's my understanding that one of the key benefits of the Capability system is that other mods can provide the Capability you designed - is that right? So far I've discovered that Forge provides Capability<IAnimationStateMachine>, Capability<IEnergyStorage>, Capability<IFluidHandler>, Capability<IFluidHandlerItem> and Capability<IItemHandler>. I suspect many people have created their own Capabilities by now and I'm sure some (almost) duplicate Capabilities exist out there. Perhaps we should be sharing and documenting Capabilities rather than each invent our own. For example, I created Capability<IFuelHandler> which provides basic furnace functionalities related to remainingBurnTime, initialBurnTime, etc. I can imagine a number of implementations; e.g. one that provides the vanilla Furnace implementation, one (that I made) that provides higher burnrates (with more FE/t) for "higher" fuels (coke, buckets of lava, etc.), etc. Is there any kind of sharing for Minecraft (other than bitbucket) "snippets" like Capabilities, GUI helpers (haven't we all made one?), etc.? Linda
  8. I found the problem; my writeToNBT method didn't call super.writeToNBT so the TileEntity class never stored my TE's id.
  9. I've implemented: - getTileEntityClass - getTileEntity - hasTileEntity (returns true) - createTileEntity(world, state) (though deprecated) - createTileEntity(world, meta) (though deprecated) My Block and TE class have a constructor without parameters. One thing that bugs me is that all registrations happen through event.getRegistry; except for the TE registration which uses GameRegistry.registerTileEntity - seems inconsistent.
  10. I provided all the relevant code... In the log I see it does: - preInit (on Client) - RegistrationHandler.registerBlocks (on Client) - GameRegistry.registerTileEntity (on Client) - RegistrationHandler.registerItems (on Client) - RegistrationHandler.registerItems (on Client, for the models) - init (on Client) - postInit (on Client) Then when I right-click my block: - onBlockActivated (on Server) - TE.onLoad (on Server) - TE.onLoad (on Client) Anything unexpected here? The block itself is registered on RegistrationHandler.registerBlocks; is that a problem?
  11. I'm having the same issue and I'm wondering about the different events that are being used. My main class implements: @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) @Mod.EventHandler public void init(FMLInitializationEvent event) @Mod.EventHandler public void postInit(FMLPostInitializationEvent event) It also defines this class @Mod.EventBusSubscriber public static class RegistrationHandler implementing these methods: @SubscribeEvent public static void registerItems(RegistryEvent.Register<Item> event) @SubscribeEvent public static void registerItems(ModelRegistryEvent event) @SubscribeEvent public static void registerBlocks(RegistryEvent.Register<Block> event) I got this from some tutorials and I was under the impression that the RegistrationHandler was the new preferred implementation. I tried this in both the preInit and the registerBlocks events: GameRegistry.registerTileEntity(MyTileEntity.class, "mymod:my_tile_entity") And still my TE doesn't trigger onLoad until I right-click the block to open the GUI. Previously I had seen some "Skipping BlockEntity with id " (and no id was printed there) which leads me to believe my TE's weren't storing their NBT but after moving the registryTileEntity to preInit that error is gone. 1. What is the preferred implementation for the registration events; in which event should I register the Block and the TE? 2. Why is my TE not loaded on world load?
  12. I want an ITickable class to keep track of and regularly update multiple blocks and possibly items; serverside. It shouldn't be dependent on things like chunk loading and actually I actually don't event want an inworld block for it. Is there a recommended way to imlement this? Can I use a TileEntity and can I just initialize this in my mod postInit? Would it be able to store NBT data?
  13. I found it to be the best way without the need to expose new methods (requiring me to cast the TE to my own TE class). I didn't feel like doing this just for the IItemHandler issue but I suspect a Progress capability can will be useful more often.
  14. I was able to get it working with the facing option (of course, it restricts me to 6 IItemHandlers but for now I just needed 3 anyway). I feel it's a hack/workaround and not a proper solution tho... I did create a custom capability for my furnace progress. The vanilla furnace uses IInventory which offers getField and setField, I feel that's missing from the standard capabilities; perhaps I'll create a generic IStorage<IProperties> capability to offer generic properties handling to any TE... For now, I created a Progress capability (with minValue, maxValue, value and a method to get actual progress) that my TE sets to 0, initialBurnTime, remainingBurnTime and from which my Gui calls getProgress(34) (my progress bar is 34 pixels). Am I correct that every custom capability needs all this? - Capability interface (ICapabilityProgress) - Capability class (CapabilityProgress implements ICapabilityProgress) - Serializer (CapabilityProgressProvider implements ICapabilitySerializable<NBTBase>) - Storage class (CapabilityProgressStorage implements IStorage<ICapabilityProgress>)
  15. I'm building a TileEntity which I want to have multiple ItemStackHandler for different slots. I'm trying to add capability constants to use in getCapability: @CapabilityInject(IItemHandler.class) public static Capability<IItemHandler> CAPABILITY_SET1 = null; @CapabilityInject(IItemHandler.class) public static Capability<IItemHandler> CAPABILITY_SET2 = null; On runtime, both CAPABILITY_SET1 and CAPABILITY_SET2 reference the same Capability object so I can't distinguish between them. I tried this: @CapabilityInject(IItemHandler1.class) public static Capability<IItemHandler1> CAPABILITY_SET1 = null; @CapabilityInject(IItemHandler2.class) public static Capability<IItemHandler2> CAPABILITY_SET2 = null; Where both IItemHandler1 and IItemHandler2 are empty interfaces with extends IItemHandler. On runtime, CAPABILITY_SET1 and CAPABILITY_SET2 remain null. Do I really have to build a custom Capability with custom writeNBT, custom readNBT, custom Factory, custom implementation, etc.?
  16. They're synced from server to client using IContainerListener; I've found now client to server syncing...
  17. Are you playing on a multiplayer server or just a singleplayer instance?
  18. I noticed and I already had a similar approach; I have like a BlockMachineBase, ContainerMachineBase, GuiMachineBase (extends GuiInventoryBase which extends GuiContainer) and TileEntityMachine base and each machine extends that, e.g. BlockFurnaceGenerator, ContainerFurnaceGenerator, etc. But you don't have Client Gui -> Server Container communication, as far as I could tell.
  19. I've refactored my blocks to use IItemHandler(I actually used your ReasonableRealism as an example/guide, Draco18s, thanks for that), this also meant I lost the IIventory's setField and getField. So, back to my original question: How do I communicate from Gui (Client) to the Container (Server) which needs this info for transferStackInSlot? OOTB the Container seems to use updateProgressBar (called from IContainerListener.sendWindowProperty, looks like) as a setField but it's marked as @SideOnly(Side.CLIENT). 1) I could again call a TileEntity setter method from an IMessageHandler and call a TileEntity getter method from my Container. 2) I could create a custom method in my Container and use player.openContainer to get the Container instance on the server; I'm not sure that's the best approach tho 3) Perhaps I can create a custom INetHandler Packet with listener, seems a bit overengineered. Any suggestions? I looked at ContainerModChest but it just calls TileEntity methods from the Container... !? For now, I've changed updateProgressBar to be both server and client. Gui calls client side container updateProgressBar and uses SimpleNetworkWrapper.sendToServer with a custom IMessage; its handler uses player.openContainer updateProgressBar to set the same on the server. Any feedback is appreciated.
  20. I've been looking for examples that use IItemHandler capability (nothing in the decompiled source seems to use this) with a Container and GUI. I believe I understand how it can replace IInventory tho I currently fail to see the benefits. More importantly: How do I achieve my multiple-gui solution through IItemHandler?
  21. Can you provide some details how would I use a capability for this? My TE class already returns the inventoryStacks through getCapability.
  22. I implemented as follows (my TE's also implements IInventory which has getField/setField methods): The class MessageUpdateTileEntityField implements IMessage, constructor like: MessageUpdateTileEntityField(TileEntity te, int field, int value) which creates a message with TE's pos, dimension, field id and value. On click of the button in the GUI it calls te.setField(1, id) (of course, this is CLIENT), in the TE class, setField triggers a simpleNetworkWrapper.sendToServer call with the new MessageUpdateTileEntityField(this, 1, id). The internal IMessageHandler class of MessageUpdateTileEntityField, on receiving a message, finds the TE based on pos/dimension (world.getTileEntity(pos)) and calls setField(fieldId, value) (this is on the SERVER). My Container class has a reference to the TE, it overrides transferStackInSlot and calls te.getField(1) to get the GUI ID and adjust its behaviour. With this, there's no need to reinitialize the Container and TE to open the new GUI. I based the setup of my TE, Container and GUI classes on the vanilla Furnace. Edit: Oh, and this is working... worth mentioning ?
  23. Hi, I'm building a machine with a GUI that has multiple screens with different slots on each screen. That means the Container method transferStackInSlot needs to behave differently for the different screens. My approach so far is: - GUI calls TileEntity.setField(1, guiId) to set the ID on switching - Container calls TileEntity.getField(1) to get the ID in transferStackInSlot Unfortunately, the GUI call happens only on Client, the Container call happens on both Server and Client but of course only the Client gets the updated value. I was looking at an IMessage example which should be triggered by TileEntity.setField in case of !world.isRemote which would send the ID to the Server TileEntity; is that the best approach? Any other suggestions on how to achieve this? Lyn
×
×
  • Create New...

Important Information

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