Jump to content

Choonster

Moderators
  • Posts

    5160
  • Joined

  • Last visited

  • Days Won

    76

Everything posted by Choonster

  1. You need to call IThreadListener#scheduleTask with a Runnable implementation that performs the appropriate action in its run method (an anonymous class or lambda is usually used here). Currently you're immediately calling IvVillager#hire_Villager (on the network thread) and passing the result to IThreadListener#scheduleTask. The only thing you do on the network thread should be scheduling the task to run on the main thread. What do you mean by "ids"? If you mean the index argument of the Slot/SlotItemHandler constructors (assigned to Slot#slotIndex/SlotItemHandler#index), that's the slot index within the inventory (IItemHandler) that the Slot should read from/write to. If you have Slots for multiple inventories in a Container (which is often the case), you'll often have multiple Slots with the same index argument but different inventories (e.g. one for slot 0 of the villager's inventory and one for slot 0 of the player's inventory). Slot#slotNumber is the unique index of the Slot in the Container, this is automatically assigned when you call Container#addSlot. To protect against malicious clients sending the packet when the player isn't actually near the villager.
  2. You can't safely interact with normal Minecraft classes from the network thread, so the first thing you do in IMessageHandler#onMessage should be to schedule the task to run on the main thread. Only get the villager and hire it inside the scheduled task. WorldServer#addScheduledTask isn't a static method, you need to call it on an instance of WorldServer. The MinecraftServer class also implements IThreadListener, so you can use the server instance (EntityPlayerMP#mcServer) to schedule the task instead of a WorldServer instance (the WorldServer implementation of IThreadListener delegates to the MinecraftServer implementation anyway). The MessageSendEntityID name isn't much better than EntityIDProxy. The purpose of the packet is to hire a villager, the fact that it sends an entity ID is just an implementation detail. Entity already implements ICapabilityProvider, so IvVillager implements it as well. You don't need to create a new implementation. What I was trying to say is that you only need to expose an IItemHandler (or any other capability handler instance) through the ICapabilityProvider methods if you want vanilla or other mods to interact with it. If only your code needs to interact with it, you can create your own method in IvVillager to return it. The IMessageHandler shouldn't really be checking the hire cost itself, it should simply check that the player is within range of the villager before calling IvVillager#hire_Villager. IvVillager#hire_Villager should check the hire cost and the hired status before setting the villager as hired and the player as its owner.
  3. You're not doing it the way I told you to in my previous post, but it's mostly correct. The main issues are that you're running this code on the network thread instead of the main thread (see the Warning box on the Simple Network Wrapper documentation page for an explanation) and that you're checking that the villager is hired before attempting to hire it. Why are using slot 15 of the IItemHandler? You should expose the IItemHandler that stores the emeralds directly (either via ICapabilityProvider#getCapability or a custom method) and use that rather than using a wrapper of all of the villager's inventories (which I presume is why you're using slot 15). You only need to expose an object through ICapabilityProvider if you want external code to be able to access it. Use descriptive names for your classes, fields, methods, etc. that reflect their purpose: EntityIdProxy doesn't tell me that the class is an IMessage, nor does it tell me anything about what the packet does. I recommend naming your packets Message[Action], where [Action] is the action that the packet performs (i.e. why it's sent in the first place). This packet hires a villager, so name it something like MessageHireVillager. toSend doesn't tell me anything about the contents or purpose of the field, the fact that it's sent in a packet is already obvious from the context so it doesn't need to be included in the name. This field stores the villager's entity ID, so name it something like entityID or villagerEntityID. Only declare local variables in the scope where they're used. There's no reason to declare the remaining_i variable at the start of the method if you're only going to use inside the if statement.
  4. You don't access the GUI, you access the IItemHandler inventory that the GUI interacts with. The IMessageHandler should check that the player is in range and then call the hire method. The hire method should take an EntityPlayer argument and check that there are enough emeralds in the villager's inventory and the villager isn't already hired (plus any other prerequisites) before setting the villager as hired and the player as its owner.
  5. The IMessageHandler#onMessage implementation should call the IvVillager method that hires the villager (after checking that it's allowed). Look at the GuiHandler code you merged from my fork of the repository, I did the same thing there.
  6. Look at EntitySlime#getCanSpawnHere (specifically the last if statement) to see how it determines whether the chunk it's currently in is a slime chunk. You'll need to iterate outward through all chunks surrounding the current position until you find one. Minecraft records the positions of large structures like Nether Fortresses or Strongholds (that use the MapGenStructure system), but it doesn't record the positions of smaller structures like Dungeons (that use Vanilla's WorldGenerator or Forge's IWorldGenerator systems). @diesieben07 explained how to search for a TileEntity in a Chunk in the post linked below, you can use this method to find nearby mob spawners.
  7. Whether or not each side needs a Forge mod installed depends on what the mod does. If it adds a new Block or Item, both the client and server must have the mod installed. If it adds a new server-side command, only the server needs to have the mod installed (though the client will also need it installed if you want to use any non-vanilla localisations). If it changes client-side things like rendering, only the client needs to have the mod installed. Set @Mod#clientSideOnly or @Mod#serverSideOnly to true if the mod is client-only or server-only to prevent it from being loaded on the opposite physical side. Set @Mod#acceptableRemoteVersions to "*" (i.e. accept any version, including none) if the mod is only required on one side. Edit: acceptableRemoteVersions, not acceptedMinecraftVersions.
  8. This will fail if the ITextComponent isn't a TextComponentString. ITextComponent already provides the getFormattedText method, you shouldn't need to cast it. You can use ITextComponent#getUnformattedComponentText to get the text without the formatting codes. All vanilla ITextComponents also override Object#equals, so you can use this to compare the two messages.
  9. Send the villager's entity ID in the packet. Don't send the number of emeralds to drop, let the server determine that itself. Malicious clients can send whatever packets they want, they could tell the server to drop a hundred emeralds. You don't need to send the player, the packet handler knows which player's client sent the packet.
  10. Only check the emerald count when the button is clicked (or when drawing the screen if you want the button to look different when there's enough emeralds), don't check it in initGui. World#isRemote will always be true in a method called from a GUI, because GUIs only exist on the logical client. Use the Simple Network Implementation to send packets.
  11. You should also override TileEntity#getUpdateTag to return data that should be sent to the client with the chunk (usually the same data as the update packet). Do you ever manually trigger the sending of the update packet with World#notifyBlockUpdate? Are the contents of the fluid tanks ever used for rendering the block, or are they only rendered in the GUI? If they're only rendered in the GUI, you can sync them in the Container rather than the TileEntity's update tag/packet (and avoid re-rendering the chunk whenever you receive the update packet).
  12. ClientChatReceivedEvent#getMessage returns the message as an ITextComponent. This could be an instance of any class that implements ITextComponent, e.g. TextComponentString or TextComponentTranslation. What are you trying to achieve?
  13. You should add the button once in an override of GuiScreen#initGui, after calling the super method. You're currently adding a new button every frame. Override GuiScreen#actionPerformed to perform an action when the button is pressed. When clicked, the button should send a packet to the server that hires the villager after checking that the player is allowed to do so, e.g. they're within range and there are enough emeralds in the inventory. GUIs only exist on the client, the game state needs to be controlled by the server.
  14. You don't need to extend PotionEffect, it works with any Potion (like ItemStack works with any Item). Just create an instance. The system became a lot simpler with the move from metadata bit-shifting in 1.8.9 and earlier to PotionTypes in 1.9.
  15. In 1.8.9, create an ItemStack of Items.potionitem and set the "CustomPotionEffects" key of the stack compound tag to a list tag that contains a compound tag for each PotionEffect applied by the potion. You can use PotionEffect#writeCustomPotionEffectToNBT to write a PotionEffect to a compound tag. Set the metadata to 0x4000 (or any number that returns a non-zero result when bitwise AND-ed with 0x4000) to make it a splash potion. In 1.11.2, create an ItemStack of Items.POTIONITEM, Items.SPLASH_POTION or Items.LINGERING_POTION and use PotionUtils.addPotionToItemStack to set the stack's PotionType. No, you can have as many ForgeGradle workspaces as you want. I have a separate TestMod3 workspace for each Minecraft version, each of which is its own branch of the TestMod3 Git repository.
  16. One of your coremods is broken, possibly BetterFPS. Make sure you're using the latest version of every mod. If the issue persists, remove BetterFPS. If that fixes it, report this error to the author of BetterFPS.
  17. It looks like you need to subscribe to PotionBrewEvent.Pre, check the input items with PotionBrewEvent#getItem, modify the output with PotionBrewEvent#setItem and then cancel the event. For the vanilla brewing stand, indexes 0-2 are the three input items (the potions to be converted) and index 3 is the ingredient item. It may be easier to use Forge's brewing recipe system. You can use BrewingRecipeRegistry#addRecipe to add a brewing recipe for an input, ingredient and output or add an instance of IBrewingRecipe. If you update to 1.10.2+, you can register PotionType conversions with the vanilla PotionHelper class.
  18. The active hand isn't what you think it is. The active hand is the hand that's actively using an item (by holding down right click), e.g. blocking with a shield, eating food, drinking a potion, drawing a bow. EntityLivingBase#getActiveHand, EntityLivingBase#getActiveItemStack, EntityLivingBase#getItemInUseCount and EntityLivingBase#getItemInUseMaxCount only return valid results when the entity is actively using an item, i.e. EntityLivingBase#isHandActive returns true. When a player is placing a block, it's very unlikely that either hand will be active.
  19. Your tanks should not be in static fields, each instance of the TileEntity should have its own tanks. I'm not entirely sure what's causing that behaviour in the GUI, but it may be related to the static fields. How are you syncing the tanks to the client? Post the code that does this.
  20. I explain which models are loaded from where here. You need a blockstates file for the block models. The item models can either be their own model files or specified by the blockstates file.
  21. Your getCapability method is wrong. Please read my instructions carefully, I've told you exactly what you need to do: I didn't tell you to change the if statement, I told you to change the cast of this.item_handler.
  22. TileEntity#shouldRefresh is the method to look at. This controls whether the TileEntity is re-created when the IBlockState changes.
  23. Capability#cast casts it for you without the unchecked warning.
  24. Almost, but not quite. Instead of casting this.item_handler directly to T and suppressing the unchecked warnings resulting from it, call CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast with this.item_handler as the argument. Capability objects are singletons, compare them with the equality operator (==) rather than the Object#equals method. CapabilityItemHandler.ITEM_HANDLER_CAPABILITY is a field of type Capability (more specifically Capability<IItemHandler>), there's no reason to cast it to Capability. In addition to that, there's no Capability#equals method with a Capability parameter; only Object#equals with an Object parameter. Only cast when it's required by the compiler. Import classes like Capability and EnumFacing instead of using fully-qualified names. Forge only uses fully-qualified names in vanilla patches to reduce the patch size (by removing the need for an import statement).
  25. Post the EntityTestbroom class, the issue may be there. It's best to keep client-only code like model registration in dedicated client-only classes to help avoid issues like this, though PotterEntities.registerRenders probably isn't the cause of the issue. Side note: RenderingRegistry#registerEntityRenderingHandler(Class<? Entity>, Render<? extends Entity>) is deprecated, call RenderingRegistry#registerEntityRenderingHandler(Class<T>, IRenderFactory<? super T>) in preInit instead.
×
×
  • Create New...

Important Information

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