Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. Its Minecraft.getMinecraft().objectMouseOver

    And that will crash your game when used on the SERVER, which is where the OP is trying to get a MovingObjectPosition. Not only that, but the objectMouseOver is limited in range and thus limited in use.

     

    @OP What about the code is not working for you? Works fine for me:

    Vec3 vec31 = new Vec3(player.posX, player.posY + player.getEyeHeight(), player.posZ);
    Vec3 vec32 = new Vec3(i, j, k); // where i, j, k are coordinates of some place in the world, such as the normalized coordinates from the player's look vector multiplied by some amount indicating maximum range, e.g. 100
    MovingObjectPosition mop = world.rayTraceBlocks(vec31, vec32);
    

    However, that will only result in a hit on BLOCKS; if you want to check for an entity within the player's line of sight, this is not the solution.

  2. For anyone interested, my full responses to this topic are here, only because I happened to see it there first.

     

    I suggested using the vanilla mechanics: i.e., when you switch to your special mode, store the current hot bar inventory in an array in your IEEP, and swap the items from your custom hot bar into the vanilla slots. Then vanilla handles all of the work for you, you still get to use the number keys and all that to operate your custom hot bar, and the only reason you'd want to mess with the vanilla hot bar rendering would be to limit the number of slots rendered.

     

    When the player presses 'E', that results in GuiOpenEvent being triggered so you should be able to cancel the vanilla inventory opening and swap in your own with just a few lines of code.

  3. It really depends on how you want your design to work, and a combination of approaches may be best:

     

    If you want each Item to 'belong' to a particular player, then you will need to store that player in the ItemStack's NBT so that only they can use it.

     

    If you want each entity to only be summonable once per player at any given time, then you need to store which entity(s) the player currently has summoned in IEEP. Likewise, if you want each player to only be able to summon any one entity at any given time, i.e. not 1 of entity A and one of entity B, but only one or the other, then you can just store a simple boolean 'summonedEntity' in IEEP.

     

    If, however, you want each entity to only be summonable globally at any given time, i.e. if player A summons entity X, then player B cannot also summon it, then you'd want to store which entities are summoned not per player, but somewhere else like your CommonProxy - whenever one of your special entities joins the world (EntityJoinWorldEvent), update the array or whatever in your CommonProxy. When a player attempts to summon one, check that array and see if one already exists.

     

    The last 2 options protect you from any 'dupe' bugs, while the 1st addresses item ownership. These are just examples of how your implementation depends on your design.

  4. You can check if the key exists before you 'overwrite' it, as well as take advantage of the default return values when a key doesn't exist, e.g.:

    public onItemUse() { // obviously not correct signature, but you know what I mean
      // Only set to a blank compound if it doesn't already have one
      if (!stack.hasTagCompound()) { stack.setTagCompound(new NBTTagCompound()); }
      // default is 'false' if the key doesn't exist, which is great since that means the item hasn't been used yet
      if (stack.getTagCompound().getBoolean("Active")) {
        stack.getTagCompound().setBoolean("Active", true); // now it's 'active'
      }
    }
    

    If, however, you are trying to create an item that can only summon one of each creature per player, you would be better off, in my opinion, storing such data in IExtendedEntityProperties rather than trying to cram it all into the stack's NBT tag.

     

    For one, if the player has more than one "Item of Summon X", each of those stacks has a different NBT tag and the player could then summon 2 of the same entity by using both items. If that is how your item is intended to work, then great, but if not, it'd be much more straightforward to simply check 'has this player already summoned entity X?' via IEEP which, in this case, would store data per player rather than per item.

  5. The only thing in there that might not be SMP friendly is 'public boolean keyActive;' - what is that for? I don't see it used anywhere in your Item code, but any class field of Item (or Block) is effectively static as Items and Blocks are all singletons.

     

    What this means is that if you set keyActive to true for one player using your Item, ALL ItemStacks containing your Item are affected, so player 2 who is not using the Item but has it now tries to use it and can't, for example, because keyActive is true for him/her too.

     

    Any dynamic information must, therefore, be stored in the ItemStack's NBT, which is unique per ItemStack.

  6. Yes, using Reflection will allow you to replace all of your if statements with a single block of code such as shadowfacts'.

     

    In your case, you would use the ItemStack's damage value to retrieve the correct values from your various arrays, of which you will need one containing either the various Entity classes or, as diesieben suggested, the constructors for those classes. You will need that in order to create a new instance of that entity, just as shadowfacts showed in his code.

  7. I just use it when I want to get the value.

     

    The ReflectionHelper sets the field to be accessible when you access it, and if it's already been made accessible I don't think that it has to do that step again so you shouldn't be incurring any extra performance penalty, but I haven't delved too deeply into the details of exactly how Reflection works so take all that with a grain of salt.

     

    At any rate, since you will only be using Reflection in onCollideWithPlayer, even if it wasn't the most performance-friendly solution no one would ever notice because it is usually only called once ;)

  8. I've looked and I can't find it. Does anyone know?

    Did you look in the Entity class? Look again, specifically #moveEntity. Click on that method and open up the call hierarchy (Ctrl+Alt+H in Eclipse) and you will find your answer.

     

    And yes, there are that many places that define 'gravity' logic, making it a right pain to mess with if you want to do so at that level, unless you rewrite* the Entity#moveEntity code to check for negative motionY (i.e. 'falling') and have it switch to a positive value.

     

    EDIT: * and by 'rewrite' I mean make a core mod to modify the class, in case that wasn't obvious...

  9. Nice, though double precision doesn't usually lend itself well to direct equality comparisons, it can still work out for the most part :P

     

    If you wanted to go the Reflection route, Forge provides the handy ReflectionHelper class. Class fields are indexed starting from 0, so just count the fields in EntityArrow until you reach 'inGround' and you will have the correct index:

    // you want field 5 (i.e. 'inGround' from the EntityArrow class) and using the current instance [the spear entity] to retrieve the value
    Object o = ReflectionHelper.getPrivateValue(EntityArrow.class, this, 5);
    
    // should print out 'true' when your spear is in the ground and 'false' otherwise
    System.out.println("Value for field 5: " + o);
    

    Pretty straightforward, for the most part, though that just scratches the surface ;)

  10. I see your problem now - you have duplicated the EntityArrow#onGround field, but you can't override class fields like that. EntityArrow's onGround is the one being used in all of the logic, and yours just sits there doing nothing.

     

    Since it is private in 1.8, you can use reflection (recommended course of action) or find some other way to determine if it is in the ground (e.g. current velocity < 0.1 or something). You could even use ASM to change the vanilla code so that the field is public, if you wanted, but that's probably more work than it's worth.

  11. Oh, I see why (at least if you are using this constructor):

    public EntityOniceSpear(World worldIn, EntityLivingBase shooter, EntityLivingBase p_i1755_3_, float p_i1755_4_, float p_i1755_5_)
        {
            super(worldIn);
        }
    

    You are calling the wrong super method - all of the extra processing that gets done when there is a shooter is not being done.

     

    Again, can you show the code that actually spawns the entity? E.g. in your Item class #onItemRightClick or wherever?

  12. You are getting a null pointer on line 33:

    Caused by: java.lang.NullPointerException
       at com.exo594.tutorial.IngotMasherRecipes.<init>(IngotMasherRecipes.java:33)
    

    What's on line 33?

     

    Re: Draco's reply - you can, however, use the various equality-related methods within the ItemStack class, or simply compare the #getItem() and #getItemDamage() of the two stacks.

  13. Usually that is caused by the position being out of sync between server and client, and the 'movement' is caused by the client getting the real position from the server.

     

    I remember having a similar issue long ago and thought it was solved by using the same tracking values as a real EntityArrow, but you already do, so I'm not too sure.

     

    There is one thing that your entity will not have that arrows do, however, and that is the initial spawn packet of arrows sends information about the shooter to the client. This happens in NetHandlerPlayClient#handleSpawnObject, which you can replicate by implementing IEntityAdditionalSpawnData for your spear:

    @Override
    public void writeSpawnData(ByteBuf buffer) {
    	buffer.writeInt(shootingEntity != null ? shootingEntity.getEntityId() : -1);
    }
    
    @Override
    public void readSpawnData(ByteBuf buffer) {
    	Entity shooter = worldObj.getEntityByID(buffer.readInt());
    	if (shooter instanceof EntityLivingBase) {
    		shootingEntity = (EntityLivingBase) shooter;
    	}
    }
    

    I doubt that will fix your issue directly, but it will at least make your spear more closely mimic vanilla arrows.

  14. What version of Forge are you using? I didn't see that information anywhere in your post, and it could be very important.

     

    To continue troubleshooting, I think your best bet is probably to remove all mods but yours, see if you can reproduce the issue, then remove ALL of your network code and see if it still happens. If so, remove the Nuke entity and try again. This should give you a rough idea of where the problem is.

     

    If you are using Git, you can run 'git diff' against the earlier version to see everything that has changed since then and perhaps get more clues as to the cause.

  15. You can keep it, but its not necessary, just have a method in your clientproxy in which you register all your tileentities. If you wanna make it a bit more easy and don't wanna have all that GameRegistry.registerTileEntity stuff for each of your tiles-use this generic method:

     

    private void setupTile(Class<? extends TileEntity> class1, TileEntitySpecialRenderer render) {
    	try {
    		ClientRegistry.bindTileEntitySpecialRenderer(class1, render.getClass().newInstance());
    	} catch (Exception e) {
    		e.printStackTrace();
    		}
    		GameRegistry.registerTileEntity(class1, class1.getName());
    }
    

    It takes in the TileEntity and the relatet renderer

    No, don't do that - render classes can only be registered on the CLIENT, whereas TileEntities themselves need to be registered on both sides (i.e. 'common' code).

     

    You are just asking to crash your mod when you play it multiplayer by writing code like that - rendering registrations should all be in the ClientProxy.

     

    EDIT: I reread your post and see that snippet IS in your ClientProxy, in which case are you also registering the TileEntities on the server? Because the server will need to know about them, too, and it won't if they only get registered in the ClientProxy.

  16. You made a simple rookie mistake:

    // Read:
    NBTTagList items = compound.getTagList("ItemBag", NBT.TAG_COMPOUND);
    
    // Write:
    compound.setTag("ItemInventory", items);
    

    Look carefully... what's different? :P

     

    Also, you don't need to read/write in open/closeInventory methods - you've already read the inventory in the constructor which is called when opening the inventory, and any time something changes we already write, so those two calls are superfluous. I just leave my implementations empty.

×
×
  • Create New...

Important Information

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