Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. Why do you care if the code runs on the client side, though? Only the server side should care about whether an attack or action is performed - the only exception is if you need some animation or something to happen on the client, and then you can just send a packet or health update flag saying 'this action was done on the server, so do your thing now client'.

     

    So the solution is to only run the code on the server side - there is no reason to run it on both sides for a non-player entity.

  2. You can't inform the client if your mod is server-side only unless you can use a vanilla packet - you'll need to search through Minecraft's network package(s) for one that may work.

     

    On another note, isn't the idea of one-sided mods a little bit outdated? I don't see what the advantage is - sure, in theory, only the server (or clients) would have to install your mod, but it's not that difficult for everyone to drop one more .jar file into their mods folder.

     

    I really am curious, as I still see people trying to make client-side only mods fairly frequently, but I honestly don't see any benefit to doing so.

  3. I strongly suggest you use an interface for your additional item methods instead of a 'base' class - it will be far more flexible, both for you and for anyone that may write addons for your mod.

     

    Just as a simple example, you have your CustomItem class that extends Item and adds one or more methods for interacting with the mob item in use. All fine and dandy. BUT, now imagine you have a custom sword that, logically, extends ItemSword, but you want your mobs to be able to use it, too... now what? You are stuck.

     

    Java does not support multiple inheritance, so you cannot extend both ItemSword and CustomItem at the same time, and you have to either add an additional check in your item use logic to account for the sword exception, OR you have to duplicate all of the ItemSword code in a new class that extends CustomItem, and even then that custom sword that isn't a sword will not play well with some other mods that check for instances of ItemSword in their logic.

     

    The solution is interfaces:

    public interface IMobUsable {
        void onUsingTick(ItemStack stack, EntityLivingBase (or EntityCustom) entity, int useCount);
    }
    

    Now ANY item can implement this interface and be usable by your mobs, even items from other mods if the author wants to make their item(s) compatible with your mobs.

  4. Thornack, you are misunderstanding how packets work.

     

    A packet is created on one side, populating all the class fields as needed and then writing those to an output stream so it can be sent to the other side; when this data is received on the other side, a COMPLETELY NEW instance of the packet is created, meaning NONE of your class fields have any information in them yet.

     

    The data is then parsed by the packet's read method, which is generally where you initialize class fields, and then those fields can be used when the handler processes the packet.

     

    That said, Jabelar is correct - you shouldn't need to manually sync inventory information, as that is done by the Container class. If you don't have a Container class, you probably don't have a GUI, and if you don't have a GUI, then why does the client need to know the information anyway?

  5. You'll have to implement all of that yourself.

     

    Typically, AI is used to simulate the ability of computer-controlled entities to behave as though they were intelligent players, so your best bet is to create some AI tasks that handle the logic for you and then add them to your entities' task lists.

     

    This can be very powerful when combined with some custom interfaces, e.g. IEntityItemUser, that allow your AI and Entity classes to interact more effortlessly.

     

    Or you can hard-code it all into your entity's onUpdate methods.

     

    EDIT: On second thought, I don't think you're going to be able to do it the way you want - all of the item use methods take an EntityPlayer parameter that you obviously won't be able to furnish from your non-player entity, and even if you come up with a way to hack one in there (or pass null), you will either have to restrict the usable items to ones of your own making that don't rely on that parameter, or expect things to go very very wrong.

     

    However, if you are okay with passing null, you can make an interface for items that can be used by mobs, such as IMobUsable, and give them methods to call when used by mobs instead of players. Not ideal, but that's the best I can think of.

  6. Uhm, you are just using it wrong, my friend. The arguments are inverted:

    Sorry, but I disagree - there is nothing in the specification that requires it to be used with the calling class and argument in a specific order, especially given that #isAssignableFrom is usually used when there is not an object instance available or the object's type is not otherwise known until run-time.

     

    Here is part of the description of #isAssignableFrom:

    Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via [b]an identity conversion[/b] OR via a [url=http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.5][b]widening reference conversion[/b][/url]
    

    It is the widening reference conversion which gives it the subtle behavior depending on the order of arguments:

    A widening reference conversion exists from any reference type S to any reference type T, [b]provided S is a subtype (§4.10) of T[/b]. 
    

    Therefore, if S is a subtype of T, and you then call T.class.isAssignableFrom(S.class) instead, you get false as expected; while instanceof would also give you false in such a case, it requires that you have an instance of T to test against S, which sometimes is impossible, and that's where #isAssignableFrom shines.

     

    Anyway, I don't mean to start an argument here, I was just surprised by your statements, and your suggestion of testing class identity is a more suitable solution anyway ;)

     

    EDIT: Ah, I see what you mean now - you are correct that my usage of it may be confusing to people, as #isAssignableFrom does not usually imply that the classes are equal (though it does in this case because all of EntitySpider's parent classes are abstract), and therefore is inappropriate to use in this case. Okay, after all that, I agree with you. Damn it :P

  7. if (event.entity.getClass().isAssignableFrom(EntitySpider.class)) {
      // only the regular vanilla spider will pass this check, cave spiders will not
    }

     

    This is not true. isAssignableFrom does the same check as instanceof. If you want to only check for vanilla spider use .getClass() == EntitySpider.class.

    Diesieben, I'm shocked you don't know the difference, as they are definitely NOT the same. Put this in EntityInteractEvent and right click on some entities:

    System.out.println("Entity class: " + event.target.getClass());
    System.out.println("Instanceof EntityLiving      : " + (event.target instanceof EntityLiving ? "true" : "false"));
    System.out.println("Assignable from EntityLiving : " + event.target.getClass().isAssignableFrom(EntityLiving.class));
    System.out.println("EntityLiving assignable from : " + event.target.getClass() + ": "  + EntityLiving.class.isAssignableFrom(event.target.getClass()));
    

    Here is the output you will see:

    Entity class: class zeldaswordskills.entity.npc.EntityGoron
    Instanceof EntityLiving      : true
    Assignable from EntityLiving : false // This one right here is the big difference
    EntityLiving assignable from : class zeldaswordskills.entity.npc.EntityGoron: true
    

    #isAssignableFrom can appear to act like instanceof depending on which class you compare to which. If a more specific class is the caller and a less specific class is the method argument, you will get false, as you cannot create the more specific class (such as EntityCaveSpider) from a less specific one (such as EntitySpider).

     

    In other words:

    // okay to assign an EntitySpider from an EntityCaveSpider
    EntitySpider spider = new EntityCaveSpider(world);
    
    // NOT okay to assign EntityCaveSpider from EntitySpider
    EntityCaveSpider spider = new EntitySpider(world);
    

  8. Try too only check the worldObj.isRemote for the spawning. Leave the other code outside of the iff check.

    No, that is completely wrong. If isRemote is true, that means it is a CLIENT world, and you DO NOT want to spawn an entity on the client - server only. Besides, the code that calls this event is only in WorldServer, so following your advice would result in nothing happening at all.

     

    @OP That is very strange - I haven't used that particular event before, nor do I see anything in its placement that would suggest it shouldn't work perfectly fine, but I've had success doing something similar using the EntityJoinWorldEvent.

     

    As an aside - rather than comparing strings, why not use an instanceof check, or Class#isAssignableFrom if you want to ensure ONLY that class (as in, not any sub-classes, such as if a mod extends EntitySpider):

    if (event.entity instanceof EntitySpider) {
      // it's either a spider or any sub-class thereof; e.g. a cave spider will also pass this check
    }
    
    if (event.entity.getClass().isAssignableFrom(EntitySpider.class)) {
      // only the regular vanilla spider will pass this check, cave spiders will not
    }
    

  9. Use

    this.setBlockBounds(float minX, float minY, float minZ, float maxX, float maxY, float maxZ);

    in your blocks constructor to change the blocks hitbox.

    He's asking about an entity... -.-

     

    @OP Minecraft doesn't support horizontal-axis-based rectangular hitboxes, but there have been one or two people that have pursued this and, I think, come up with some solutions. Try searching the forums and you might find some of their threads.

  10. Neither - some effects, such as weapon enchantments, the attacker's potion effects, etc., have been applied, but the defender's armor and defensive bonuses have not yet been factored in.

     

    No, there is no event that triggers after those have been accounted for - you can see the logic flow in EntityLivingBase#damageEntity for exactly which things are not yet factored into the damage when the event is posted.

  11. Yep, and here is your problem:

    @Override
    protected boolean canPlaceBlockOn(Block ground)
    {
    return ground != HLFlowers.mushroomGlow;
    }	
    

    Look at BlockMushroom's implementation. You shouldn't even need to override this method unless your new mushroom is a full block, and then you should either call super or perform the same check.

  12. Did you register the event handler? Try putting a println as the very first line within the method.

     

    Also, I personally prefer to use 'PlayerUseItemEvent.Finish' instead of just 'Finish' - it helps prevent any sort of ambiguity when importing, as well as making the event handling method easier to read.

  13. #isDamaged always returns true after a stack has taken even 1 point of damage, even if it didn't take any damage recently.

     

    Is the problem that the println isn't printing, or that the counter from your IEEP is not what you expected, or something else entirely?

     

    Show your IEEP code for #addToCounter and #getCounter

  14. Start event fires when the player first begins using the item.

    Tick event fires each tick while the item is in use.

    Stop event fires when the player stops using the item.

    Finish event fires after everything to do with using the item is finished.

     

    Most of this is explained in the Java docs for the events, and the rest you can gather from looking at where the events are called via the Call Hierarchy in your IDE, all of which lead to the Item class eventually.

  15. Nope, it's not. You are comparing Strings with '==' instead of #equals - google that for an explanation, but even more important is your implementation is, frankly, ridiculous.

     

    You create a List, presumably of allowable items, and populate it every single time the method is called - don't do it that way, only create this list once and initialize it with a static block or some such.

     

    Also, when comparing Items, you can compare the item directly, which is MUCH better than comparing strings:

    for (ItemStack solvent : solvents) {
      if (itemstack.getItem() == solvent.getItem()) {
        return true;
      }
    }
    

    Note that if any of your solvent items have subtypes or use NBT to differentiate amongst themselves, you will need to make the logic more complex to account for that.

  16. Slots are rendered from the GuiContainer class, specifically from #drawSlot, which ultimately calls Slot#getSlotTexture, which is overridden by the anonymous class used for armor slots to return the EMPTY_SLOT_NAMES from the ItemArmor class - these are the background icons.

     

    You can find the anonymous class for armor slots in the ContainerPlayer constructor.

  17. You can NOT implement IInventory in an Item class - Items in Minecraft are singletons, so there is only ever one instance of each item, but for an Inventory to work you need the Inventory itself to be a unique instance, otherwise it will be all sorts of messed up.

     

    If you want each player to have a unique backpack instance, like a portable Ender Chest, you need to store the inventory in IExtendedEntityProperties and only access the inventory GUI via your item - the item itself will have nothing else to do with the inventory.

     

    If you want players to be able to carry as many backpacks as they want, each backpack having storing an independent inventory, you must store the Inventory inside the ItemStack's NBT and basically recreate the inventory from that tag each time you want to interact with it.

     

    I have a tutorial that covers both cases.

  18. If you have the look vector from the player, the code I wrote above works perfectly for offsetting something to the right or left of the direction the player is looking. As I said, I don't know how well it will work if you use the projectile entity for the look vector - apparently, not perfectly.

     

    But, if you just want the particles to not obstruct the player's vision, all you have to do is move them down so they don't spawn right in front of your face. Keep in mind, however, the view from 3rd person (which is what other players will see, at least if you spawned particles on their clients as well) - if you move it down too far, or in some other direction, it may end up looking great from 1st person, but very bizarre from 3rd.

  19. It only happens in survival because of this bit of code:

    if (entityplayer.capabilities.disableDamage || this.shootingEntity instanceof EntityPlayer && !((EntityPlayer)this.shootingEntity).canAttackPlayer(entityplayer))
                    {
                        movingobjectposition = null;
                    }
    

    That's where the arrow has found a potential target, i.e. the player at < 5 ticks, but if the player is immune to damage due to being in creative mode, it completely ignores the impact and keeps going.

  20. That's not at all how the #readSpawnData method should look... you are supposed to find the actual player ENTITY, not assign an ID to it - it already has an ID, and it's the same one that you are reading in from the packet.

    Entity shooter = worldObj.getEntityByID(buffer.readInt());
    if (shooter instanceof EntityLivingBase) {
    shootingEntity = (EntityLivingBase) shooter;
    }
    

×
×
  • Create New...

Important Information

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