Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. You can use reflection to generalize your construction of a new entity, e.g.:

    Entity newProjectile = oldProjectile.getConstructor(World.class, EntityLivingBase.class, float.class).newInstance(world, shooter, charge);
    

    Then your code will handle any type of projectile entity so long as it has a constructor with that signature (taken from EntityArrow, so you may need to instead use the one that doesn't take the float, or have a different case for EntityArrow vs. EntityThrowable sub-classes).

     

    A problem with that, though, is that you lose any extra information that may have been stored in the original class instance, i.e. any custom fields, such as damage, that were set previously.

     

    Another option, as I already mentioned, is to just change the heading at any time by setting the projectile entity's motionX/Y/Z values to whatever you want. That's what #setVelocity does, mostly, but the problem with that is you also need to make sure the clients all know about it, too, or else the client version of the entity (which is the one you see) will still be headed in the original direction.

     

    A further problem is that, since the projectile has already impacted, chances are it has had #setDead called and will be cleaned up very shortly. You need to undo that and also make sure it is no longer colliding with any entity, otherwise it will just re-collide on the next tick and do its onImpact business.

     

    Take a look at #setThrowableHeading (or some version thereof, including pretty much any constructor that takes the shooting / throwing entity) in EntityArrow / EntityThrowable to get an idea of the code you'll need. That and a way to avoid hitting the same entity again, which most projectiles do by using an 'if (this.ticksExisted < 5) { ignore the shooting entity when checking for impact }'

     

  2. It doesn't look like you're spawning the arrow entity at all, so I don't see how you can say it's having no problems changing directions...

     

    Furthermore, your Java is a bit messy - you have a trailing 'else' with no brackets and you're casting the arrow's shooting entity to an EntityArrow and then to an EntityLivingBase.

     

    Anyway, you need to spawn the new arrow entity, or use the existing one and just modify its position and motion to the new direction.

  3. Plus, you know that cameras involve rendering only, so logically the code for it can only be in the minecraft/client package, and in there is a package called /renderer.

     

    Furthermore, you know that this rendering only has to do with entities, mainly the player, so you should look for a class involved in rendering entities. Narrows it down pretty quickly, no? :P

  4. I thought I'd post in your thread instead of writing my own.

    Wow, someone who uses search! Thanks for bumping the thread, I'd totally forgotten about it ;)

     

    It seems there is no way to fix this other than to submit a PR to the Forge project or open an issue and hope Lex decides to work on it. All it would need to change is line 80 of LayerArmorBase to use #hasEffect(ItemStack) instead of #isItemEnchanted.

     

    I tried setting up a Forge workspace before but had some issues. The first time I set it up the code base was somehow 2000+ commits behind master. No idea how that could have happened, as I cloned straight from the master branch. Second time I got the latest commits but there was an error in the build script that prevented the project from setting up or something, don't remember exactly what it was now, as this was over a month ago, but there was a post with the same problem from back in 1.7.10 and the fix was on Forge's end then.

     

    Anyway, long story short, due to technical difficulties, I won't be submitting PRs myself anytime soon.

  5. I've already tried setting its target to null in the event, but the field is final, and the entity's saved target is private. I already have the item canceling damage, but that's not the point.

    How did you set the target to null? I've done it using ((EntityLiving) event.entity).setAttackTarget(null); and that works for most mobs. 1.8 is better than 1.7.10 for this since now most mobs are using the AI system, whereas before spiders and many others were not, meaning they wouldn't be affected at all.

     

    Anyway, the above should work (mostly) - the mobs won't even walk towards you. If it's not working for you, show your code.

  6. You don't want to remove their AI tasks - then they won't attack anyone EVER again.

     

    Easy way: cancel LivingAttackEvent when the target is wearing your item. Downside is that mobs may still 'target' the player, i.e. walking towards it and such, but you won't take any damage.

     

    Another way: use LivingSetAttackTargetEvent to set the attacker's current target to null (or another nearby selectable target) if the target is wearing your item, but this doesn't (or perhaps didn't) work for all entities (e.g. creepers, iirc, as well as some others) so you'd have to account for that by using some fancier magic such as ASM.

     

    Best way is a combination of the above 2 - the 2nd to prevent most mobs from even trying to target the player, and the 1st to stop them from doing any damage if they still end up targeting despite your other efforts.

     

    Probably more ways as well, but that's all I can think of at the moment.

  7. The reason you would use KeyInputEvent is if you want the actual key press to trigger something directly, e.g. press 'x' to open a GUI.

    Nope, no need to.

    In that case you would use ClientTickEvent (which actually fires more rarely than KeyInputEvent most of the time) and check for your key being pressed there.

    My understanding is that KeyInputEvent fires immediately when a key is pressed, whereas ClientTickEvent you'd not only be waiting to process the input (granted probably an imperceptible amount of time), but you'd be taking a craps shoot as the key might not still be pressed if the player simply tapped it very quickly (very unlikely, but still), depending on whether you check if the key is still down or if the pressed variable was incremented and has yet to be decremented.

     

    Plus, semantically, it makes more sense to use the KeyInputEvent, though subscribing to it may waste some resources by processing for every single key when one only actually cares about a few.

     

    Am I completely off base here, i.e. is that not how it works? If your situation is very dependent on the timely processing of the key press, e.g. combat / movement related, wouldn't you want KeyInputEvent?

  8. The reason you would use KeyInputEvent is if you want the actual key press to trigger something directly, e.g. press 'x' to open a GUI.

     

    If your key binding is used elsewhere, such as in combination with a mouse click, then as diesieben said, you don't need KeyInputEvent for that particular case.

     

    Furthermore, if you don't care about users being able to change the key used, you can get away without a KeyBinding at all and just use the Keyboard object directly to check key states. This is what happens in GUIs (indirectly), for example, when the Escape key is pressed.

  9. I've tried every Forge world gen event hook there is and none of them work 100% - mineshafts, ravines, and other multi-chunk structures / terrain features (such as lakes >.<) still destroy my structures from time to time.

     

    PopulateChunkEvent.Post is supposed to fire after everything else has generated (and it does, in the code), but it's still not bulletproof.

     

    You can stop lakes from breaking your stuff setting PopulateChunkEvent.Populate to DENY for EventType.LAKE if your structure is in or around the current chunk.

     

    Based on my experiences testing various things (as opposed to minutely dissecting the actual code, though I've done a fair amount of that as well), it seems that mineshafts and other such features have a 'start' chunk that triggers them to generate in their entirety, so in that one chunk you have the normal Forge event hook progression, but every other chunk that it generates in is completely outside of the normal flow.

     

    Obviously that's not completely true, otherwise lakes wouldn't be posting the Populate event, but I haven't been able to figure out in all this time how to stop mineshafts and such from doing what they do. I'm probably just not looking in the right places, but I've traced the hell out of the world gen code multiple times and still can't figure out how to prevent it, so if you (or anyone else) does figure it out, please share!

  10. There is no easy way to remove an enchantment, but it can be done by iterating through the enchantment list stored in the ItemStack's NBT and removing a specific enchantment that way.

     

    E.g.

    NBTTagList enchList = stack.getTagCompound().getTagList("ench", Constants.NBT.TAG_COMPOUND);
    for (int i = 0; i < enchList.tagCount(); ++i) {
    NBTTagCompound compound = enchList.getCompoundTagAt(i);
    if (compound.getShort("id") == Enchantment.whatever.effectId) {
    	enchList.remove(i); // example only - you should use Iterators when removing elements from a Collection
    }
    }
    

  11. If that's the case, perhaps your computer doesn't have enough juice to handle both the dev environment and running Minecraft at the same time? Or are you using a Mac?

     

    I'm not sure what type of computer Jabelar has, but neither he nor I have this issue. I have a gaming laptop running Windows 7 and my mod entities act the same whether in dev or compiled.

  12. Here's my reply to another thread which may also prove useful to you, and you can also look up ConcurrentModificationException on Google to find many great explanations.

     

    Basically, a CME usually happens with Collections when one thread is iterating over the collection and another thread tries to modify the same collection. Easy fix is to synchronize your iteration, or, if you are the one modifying it, use thread-safe operations e.g. Iterator.

  13. If you just want the damage to change based on number of souls, you would simply override Item#getAttributeModifiers(ItemStack) to return a multimap with the appropriately leveled AttributeModifier for attack damage according to the ItemStack NBT.

     

    If you need access to another item in the player's inventory (vanilla or otherwise), it becomes slightly more complicated. There is no way to know about any other items or other player-related info in the method mentioned above, so you'd probably have to use the LivingHurtEvent to modify damage and the PlayerTickEvent to check for the equipped item every tick and apply or remove whatever enchantment, but you'd also need to make sure the item tooltip displays the correct damage amount, prevent the re-equip animation from playing each time you update the NBT, etc.

     

    Lots more things to think about in the second situation, as you can see, which is why I would recommend you start with the simpler version and go from there. It's far easier to make something simple that works more complicated, rather than trying to make something complicated immediately and trying to figure out why it's not working. One step at a time.

  14. Right-clicking, assuming you mean while the sword is in hand, would be the simplest implementation - you already know that the player is holding your sword by the fact that your sword's Item#onItemRightClick method was called, and you won't have to deal with all the complications of a GUI (IGuiHandler, opening the GUI, sending packets to server, etc.).

     

    onItemRightClick is called on both client and server, so you can do all the server-side things (such as changing the ItemStack NBT) directly from there.

     

    If you want the 'soul' is an entity, though, it might be better to handle this from your Entity class' interact method (or whatever it's callled - don't have my IDE open right now), since it can be tricky to get the clicked entity from the Item method. Then you just have to check the held item of the entity that is interacting with the soul using #getHeldItem().

  15. According to what download page? Latest recommended version has been 11.14.3.1450 for quite some time now.

     

    As for your issue, if your mobs are doing something (buggy) that vanilla mobs are also doing, then the problem is very likely something in vanilla code that you won't be able to fix; if they are doing something that vanilla mobs are NOT doing, then it is very likely a problem in YOUR code.

     

    I haven't noticed any of my nor vanilla mobs acting the way you describe in 1.8, aside from occasionally falling into the ground, but even that is pretty rare.

  16. Did you actually try using '3' instead of '1' for the update frequency? No vanilla mobs use 1, and you shouldn't either. It can actually have very real effects on how your mobs operate, for example I tried making a custom arrow class that extended EntityArrow and used 10 (like throwables) instead of 20 (like arrows) and it had problems correctly impacting blocks and entities, often bouncing off. Using the same value as vanilla arrows fixed it.

     

    You should also update your Forge version to at least the latest recommended version, though I don't think that has anything to do with your issue.

     

    Falling into the ground is a vanilla issue, but it shouldn't happen as frequently as you seem to be experiencing.

  17. Why would you go about implementing an entire packet & handling system when #getDescriptionPacket and #onDataPacket already exist? Just use the vanilla S35PacketUpdateTileEntity and only send the ItemStack. Less code = less things to go wrong / debug.

     

    Similarly, why implement custom get/setInventoryContent methods when there are already getStackInSlot and setInventorySlotContents? Why are you not using the methods already available?

     

    And this:

    ItemStack itemstack = new ItemStack(bgd.getInventoryContent().getItem(), 1, meta);
    

    Why are you making a NEW ItemStack here? Just get the contents of the first slot:

    ItemStack itemstack = bgd.getStackInSlot(0);
    

    That goes for when placing items into the inventory as well. You are going to lose a LOT of information the first time you place an ItemStack with NBT (e.g. enchantments) in there:

    bgd.setInventoryContent(new ItemStack(playerIn.getCurrentEquippedItem().getItem(), 1, meta));
    

    Yikes.

     

    Finally, did you register your TESR? Have you tried putting debug statements in there to see what's happening, e.g. is the ItemStack ever not null?

     

    Aside: Don't mark the block for update when writing to NBT - there is no reason to do this.

  18. tesr's are for blocks not items.

    Did you even read his question?

     

    @OP Your problem is that the client side version of the TileEntity does not know anything about what is in its inventory, so if you want that information available, you need to send that information via packet. Luckily, TileEntities have a built-in method to do so called getDescriptionPacket:

    @Override
    public Packet getDescriptionPacket() {
    	NBTTagCompound tag = new NBTTagCompound();
    	this.writeToNBT(tag);
    	return new S35PacketUpdateTileEntity(getPos(), 1, tag);
    }
    
    @Override
    public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity packet) {
    	readFromNBT(packet.getNbtCompound());
    }
    

    That's the simplest implementation, but if you have lots of data that doesn't need to be sent, you're better off only sending what you need (e.g. one single ItemStack instead of everything).

     

    The packet is automatically sent any time the block is marked for an update, so any time your inventory changes you will want to call worldObj.markBlockForUpdate(getPos());

×
×
  • Create New...

Important Information

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