Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. Where do you register your projectile entity? It should be done during pre-init:

    // increment the index for each entity you register
    int modEntityIndex = 0;
    
    // last 3 parameters are tracking range, tracking frequency, and whether to send tracking updates or not
    // check the vanilla EntityList (I think) to find a similar entity class and use the same values
    // in this case, throwable entities all use '64, 10, true' so I recommend you do the same
    EntityRegistry.registerModEntity(YourEntityClass.class, "Your Entity", ++modEntityIndex, this, 64, 10, true);
    

  2. If vanilla XP is kept in sync by vanilla Minecraft, then no, you don't need any additional packets for that particular aspect of your code, but if you are displaying the cost of spells or whatever like it seems you are doing with your arrays, and those values are configurable, then you will most definitely need to send that data to the clients when they connect or they will likely have incorrect values displayed to them in the GUI.

     

    Same goes for any other data that is not kept in sync for you by Minecraft, so pretty much everything you add via your mod and a hefty portion of vanilla fields if you want to use them client side.

  3. This is all from memory, so it may not be entirely accurate: when the player takes damage, there is a field that gets set to true - something like #velocityChanged - that acts as a flag for the server to notify the client of specific motion changes.

     

    You can accomplish the same thing by sending a motion packet to the client or running your code on both sides.

  4. Yes. Extend EntityThrowable and override #getGravityVelocity to return 0.01F or some such - I don't recommend negating gravity entirely, however, or going much below that threshold unless you plan to limit the flight time in some way; otherwise your projectiles can travel forever.

     

    As for the time on the ground, you could spawn it as an EntityItem with a custom lifespan, or do the much more difficult but cooler effect of figuring out how to place your projectile in an immobile state at the point of impact and render it correctly on that side of the block hit, in which case you have complete control over when the projectile entity despawns.

  5. When #isRemote is true, that means your code is currently on the logical client side, and is NOT when you want to open container-based GUIs.

     

    Entity#interact is called on BOTH client and server side during the interaction process - first on the client during the initial mouse-click, then again on the server after the server receives a packet. You should open the GUI when the world is not remote, i.e. on the server side, since the GuiHandler will open both the Container (server side) and the GUI (client side) automatically when invoked on the server.

     

    If you were in a situation that didn't have Minecraft automatically sending packets for you, say you wanted to open your Container-based GUI by a key press instead of entity interaction, then you'd have to do as Ernio said and send your own packet from the client requesting the server to open the GUI.

     

    The only time you should open a GUI directly on/from the client side is when there is only a GUI component (no Container) and there are not any important conditions to the GUI being opened. If, for a non-Container based GUI, it is important to know for sure the player is e.g. close enough to the entity, then you should send a packet from the server to the client to open the GUI.

  6. This is exactly the type of situation that PlayerLoggedInEvent was made for - send the packet from there.

     

    Do keep in mind that the client-side values are for display purposes only - any time you use them that will have a real effect, such as casting a spell or crafting something, you should only use the values on the server side.

  7. You can put as many values in a packet as you want, but I would only do so if you don't anticipate needing to send any of them individually. E.g. if you need to be able to sync just one xp type (e.g. when that type is gained), then you should have a packet for just that type.

     

    Nothing is stopping you from having both, though - one packet containing all the values to be used in the 'sync everything' situations, and one packet per xp type for times when you just want to sync that specific type.

  8. Check your entity registration code and make sure you are using the same tracking values as the vanilla arrow, i.e.:

    int index = 0;
    EntityRegistry.registerModEntity(EntityArrowCustom.class, "Custom Arrow", index++, YourMod.instance, 64, 20, true);
    

  9. Minecraft model rotation 'angles' are in radians, not degrees, so you'll need to convert them.

     

    As for 'how' - look at some vanilla mob model classes and check out their setRotationAngles and setLivingAnimation methods.

     

    If you want to use the values from Tabula, you can make an array containing them converted to radians, where each element is a 'frame', and then interpolate the value each render tick based on the animation progress. Or you can get super complicated and have an entire framework set up to help you, so that you end up with something like this:

    // helper method
    public static boolean applyAnimation(IAnimation animation, int frame, float partialTick, float speed, float multiplier, float offset, boolean invert) {
    if (animation.shouldApply(frame, partialTick, speed)) {
    	animation.apply(frame, partialTick, speed, multiplier, offset, invert);
    	return true;
    }
    return false;
    }
    
    // called in the model class
    private void animateActions(EntityWithAnimationInterface entity, float par2, float par3, float partialTick) {
    Entity target = entity.getCurrentTarget();
    List<EntityAction> actions = entity.getActiveActions();
    for (EntityAction action : actions) {
    	int frame = entity.getActionTime(action.id);
    	if (frame > 0) {
    		float speed = entity.getActionSpeed(action.id);
    		float offset = entity.getActionOffset(action.id);
    		IAnimation.Helper.applyAnimation(getAnimation(action), frame, partialTick, speed, 1.0F, offset, false);
    	}
    }
    }
    

    Where an animation might look something like this:

    READY_ANIMATION = new ImmutableList.Builder<IAnimation>()
    	.add(new AnimationTargetAngle(stem1, RotationAxis.X, -15.0F, 5, 10, true))
    	.add(new AnimationTargetAngle(stem2, RotationAxis.X, 20.0F, 5, 10, true))
    	.add(new AnimationTargetAngle(stem3, RotationAxis.X, 30.0F, 5, 10, true))
    	.add(new AnimationTargetAngle(head_base, RotationAxis.X, 60.0F, 5, 10, true))
    	.build();
    

    Note that those are the same values as from Tabula and the animation code converts them to radians internally.

     

    But anyway, that kind of thing takes an entire framework to support it, whereas you can get by doing things more like vanilla especially if your animations are not too complicated (which they don't appear to be).

  10. Anyone know how to make animation APIs? I'm still very new to APIs and animatoins

    You don't need to write an API to make animations. Look at vanilla - they hard-coded all of their animations using math within the context of the model and renderer frameworks. You can do that, too.

     

    Or you can try to write an 'API', but people throw that term around without really thinking about it. Do you know what it means? What would be your goals in making such an API? Who is the target audience? How, exactly, would it work? Is your API going to read in the animation frames from Tabula, for example? Or are users of the API going to need to do some coding and math of their own? This is a HUGE task no matter which approach you decide to take.

     

    Also, why do you want to write your own animation 'API' instead of using ones that are available? I believe TheHippoMaster wrote one, and then BobMowzie has one that is adapted from the first, and I think there is even one that does allow you to import / read animations from the Tabula files.

     

    If you still want to write your own API, that's fine - I did. But I did it for fun and also so that my mod wouldn't have any dependencies. Is it the best animation API out there? Probably not, but that was never its goal. It does what I need it to do and I enjoyed creating it.

     

    Anyway, think about why you think you need to write an animation API. You probably don't need to, but if you do, be prepared for a pretty monumental task and read up on your math.

  11. You can avoid the crash by using your proxy:

    EntityPlayer player =  Main.proxy.getPlayerEntity(ctx);
    
    // Common / Server Proxy:
    public EntityPlayer getPlayerEntity(MessageContext ctx) {
    return ctx.getServerHandler().playerEntity;
    }
    
    // Client Proxy:
    @Override
    public EntityPlayer getPlayerEntity(MessageContext ctx) {
    return (ctx.side.isClient() ? mc.thePlayer : super.getPlayerEntity(ctx));
    }
    

     

    If you are changing mana values from that many places, you are generally doing something wrong. Consolidate those into one setter, if you can. Have different types of mana? No problem, add an argument to the method:

    public void setMana(EnumManaType type, int amount) {
    switch (type) {
    case BLUE: this.blueMana = amount; break;
    case RED: this.redMana = amount; break;
    }
    network.sendPacketTo(new SyncManaPacket(type, amount), this.player);
    }
    

    That's just pseudo-code, but you get the idea. If you ever find yourself doing the same thing in more than one place (e.g. sending the same sync packet), that's a big hint that you need to centralize that shit.

  12. That's a LOT of places, which is a big clue your design is poor. Sync from one place and one place only, but don't send more than you need to.

     

    Sync ALL data that you need on the client side (for rendering such as in a GUI) when the player joins the world. Easiest is EntityJoinWorldEvent. This takes care of things such as changing dimensions and respawning.

     

    Sync current / max mana from the only logical place to do so, i.e. the method you use to set it. You ARE using a setter, right? And that is the only way you ever change your mana values, right? Right?!?! This takes care of when the player consumes or regains mana through the normal course of play.

     

    Again, only send what you need, so when the mana changes, only send the mana value, not the entire IEEP. This means make a separate packet for when you just want to sync mana.

     

    Also, you don't need to make a separate 'Handler' class for every single event you handle - every one of those adds an entry to the list of handlers Forge must iterate through. You can if you really want to, but you can also put them all in the same class. If it starts getting unwieldy, group them by macro category (e.g. combat, entity, item, or whatever).

  13. Unless you are doing some fancy rendering for other players based on these IEEP values, this is entirely unnecessary - you're handling the message client side, so the only possible player is the client player, i.e. Minecraft.getMinecraft().thePlayer.

     

    Where are you sending the sync message from?

     

    Also, all of these and the other similar fields should be static and all uppercase, since you are defining constants. The reason they should be static is you don't need a unique instance of each of those values for every player IEEP - they are always the same, so you only need one of each, i.e. static.

  14. Also, after the player respawns, the client side IEEP will be out of sync unless you send a packet to fill in its data, but you can't do that from the Clone event, you have to do it when the player joins the world via EntityJoinWorldEvent or the Player RespawnEvent (I think that's what it's called...).

     

    Check [ur=http://www.minecraftforum.net/forums/mapping-and-modding/mapping-and-modding-tutorials/1571567-forge-1-6-4-1-8-eventhandler-and?comment=2l]here[/url] for more information.

  15. Please, READ the crash log. Actually read it. Find the line that says something like "Caused by... at line xyz". Now compare that line number to the line numbers of the method you are trying to fix. Hm, not the same, are they?

     

    And please, take a few hours of your time and learn a little about Java. Search 'Java check for null' or 'Java null pointer exception' and surely you will find a solution.

     

    Or even just READ the code I wrote. Seriously, the solution is already there in one of the examples. Null check. Check for null. If null don't try to use the null to do stuff. Phrased another way, if not null, do stuff.

     

    We're not trying to be mean, but you need to show that you are putting in some effort.

  16. heldItem.getItem().getUnlocalizedName() == NFItems.transmutator.getUnlocalizedName()
    

    No. For one, you typically do not want to compare Strings using the == operator, though it would probably work in this case. Secondly, why are you comparing the unlocalized name, rather than the item instance?

    heldItem.getItem() == NFItems.transmutator
    

    That is much clearer, more efficient, and the standard way everyone checks to see if an ItemStack contains the item they want.

     

    Also, it looks like you are storing local variables in your Block class, specifically 'cooldown' - there is only ever ONE instance of your block, so all of those blocks in the entire world will have the same value for cooldown all the time. Is that really what you want? If you want independent cooldowns, you need to store them either as metadata (similar to crop growth stages) or in a TileEntity.

     

    Finally, setting the held item to null is easier using the #setCurrentItemOrArmor method:

    player.setCurrentItemOrArmor(0, null);
    

    However, I suggest you redo your code - start out simple, make sure it works, and add complexity one piece at a time, otherwise you have no idea what is not working.

  17. In onBlockActivated method of my block class.

    That method is called on both sides, so theoretically it should work, but even still, you would only want to set inventory contents on the server side, i.e. when the world is NOT remote.

     

    Also, without seeing your code, it's possible you are doing something that forces it to be done on the client side. Show your code.

  18. Yeah, of course it crashes. You copied and pasted code that crashes. Don't do that.

     

    Read the code, read the crash report, and figure out why the code as written is crashing (hint: ItemStack's nbt tag is usually null). If you don't know how to handle the case where a field might be null, I suggest you take some time to learn up on basic programming skills.

  19. How do you retrieve the TileEntity contents when the block is right-clicked? How do you do the same in the rendering class?

     

    If there is any difference, that's the source of your problem. If they are exactly the same, how are you keeping the client (renderer) data synced with the server data? How are you adding items to your TileEntity in the first place? Hopefully only on the server.

     

    Show some current code for the above things and it will be easier to help you.

  20. I already told you: store some kind of flag in the ItemStack's NBT compound onRightClick, then only apply the motionY when that flag exists. You can remove the flag at any time, too, e.g. after 10 ticks or whatever.

    # onRightClick
    stack.getTagCompound().setInteger("float_time", 20);
    
    #onUpdate
    NBTTagCompound tag = stack.getTagCompound();
    if (tag != null && tag.getInteger("float_time") > 0) {
      tag.setInteger("float_time", tag.getInteger("float_time") - 1); // decrement float time
      player.motionY = 0.1F;
    }
    

×
×
  • Create New...

Important Information

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