Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. It sounds to me like the code you have to determine if you are landing on another entity is client side only - this happens, for example, if you use things like Minecraft.getMinecraft() to do anything, and they will crash your game if you run it on a server.

     

    Show some code and we can tell you more specifically what is going on.

  2. I'm using Forge 10.13.0.1180. I think this is a fairly early version, were there known issues with it?

    I don't remember, but when having issues that don't seem related directly to your mod, one of the first things to try is almost always updating to a more recent version of Forge. 1180 is pretty dang old.

  3. #onItemRightClick is called on both client and server - only send the chat on one side or the other by checking if the world is remote or not:

    if (world.isRemote) {
    // on client
    } else {
    // on server
    }
    

     

    EDIT: Also, you are just asking to crash your game by putting @SideOnly(Side.CLIENT) above that method - I suggest you remove it, as it doesn't do what you think it does.

  4. If you're not using an Item with #onItemRightClick, you can override the #interact method in your Entity class instead - this method is called when a player right-clicks on the entity, and you can then check if the interacting player is sneaking (i.e. they are holding SHIFT).

     

    If neither of those work for you, you have a lot more work to do: subscribe to MouseEvent AND KeyInputEvent (to handle cases where players may have re-bound the use item key), listen for the use-item key (typically right-click), and then, since this is all on the client side, send a packet to the server to trigger your code.

  5. When the golem attacks (which happens on the server), it calls #setEntityState with flag '4' - this gets sent to the client-side version of the golem via #handleHealthUpdate; when it receives the flag '4', it sets the golem's attackTimer to 10 on the client side, which is visible to the the golem's model. In the model class, the attackTimer is used to animate the golem's swinging arms.

     

    The most important point is you need a way to notify the client to perform the animation, and that's where those 2 methods come in super handy.

  6. I find #setEntityState in combination with #handleHealthUpdate to be useful methods of triggering animations. In a nutshell, #setEntityState takes an integer and sends it over the network to the client which then calls #handleHealthUpdate with that integer as an argument, so you can use different values to trigger different animations.

     

    Take a look at EntityIronGolem to see an example.

  7. You need to find a way to specify the model resource location's path; the only way I know of to do this is to use ModelBakeEvent to swap out the default /items/model.json for your item model with a new one that has the correct path.

     

    You can also register item variants using

    ModelBakery.addVariantName(Item, String...)

    - it may be possible to add in the extra directories this way, e.g.:

    String model_path = "modid:relative/path/to/model/model_name";
    ModelBakery.addVariantName(this, model_path);
    

     

    Remember also you will probably need to register the item renderer using your new path (in fact, this may be the only thing required - haven't tested it personally):

    mesher.register(this, 0, new ModelResourceLocation(model_path, "inventory"));
    

  8. I didn't actually offer a solution in the previous post - I only explained the problem.

    // what's with the 'effectDuration = 50'  where is 'effectDuration' coming from?
    player.addPotionEffect(new PotionEffect(Potion.regeneration.id, effectDuration = 50, 0));
      if ((effectDuration % 50) == 0) // what's this for???
    

    No, the solution is 2-fold:

     

    1. Only apply the potion effect for ONE of the armor pieces, e.g.

    @Override
    public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
      if (this != UselessItems.useless_boots) { // only one piece needs to tick - why do the same thing 4 times?
         return;
      }
      // rest of onArmorTick code, except you already know the player is wearing the right boots 
    }
    

     

    2. Only perform the check once every so many ticks, probably 50 to match the regeneration potion's rate of application

    @Override
    public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
      if (world.getWorldTime() % 50 > 0) {
         return; // it has not yet been 50 ticks since the last time your update tick code ran
      }
      // rest of onArmorTick code
    }
    

    Of course, #2 means you potentially have to wait 50 ticks before you receive regeneration upon donning the last piece of armor, so you may want to apply it immediately if the player does not already have the regen potion effect.

  9. If you use Thornack's method, you store a lot of potentially unnecessary data, but on the other hand, you do store everything about the entity (including any active potion effects, extended properties, etc.).

     

    Depending on how your system works, that may be a bane or a boon.

     

    Also, if you do it that way, it is very important to set the entity's position before/when you spawn it (as shown in Thornack's code example), otherwise it will spawn in its previous position.

  10. Part of the problem is you are adding the potion effect FOUR times per tick, once for each piece of armor (assuming they all belong to the same class, but even then you are adding it once every single tick). This means that the regen effect is constantly combining with itself, resetting the duration each time.

     

    Regeneration level 1 heals 1/2 heart every 50 ticks, but since your duration is reset every single tick, it never gets a chance to do so, UNTIL you set the duration to a multiple of 50, in which case it regens you every single tick because (duration % 50) will always equal zero with a full duration.

     

    In other words:

    // with duration not a multiple of 50
    tick effect
      1  add regen with duration 20
      1  check regen (duration % 50) == 0 ? no, it's 20
      2  decrement regen duration
      2  add regen with duration 20, again, resetting current duration to 20
      2  check regen (duration % 50) == 0 ? no, it's 20
      3  and so on
    
    // with duration = 50, 100, 150, or any multiple of 50
    tick effect
      1  add regen with duration 50
      1  check regen (duration % 50) == 0 ? yep! regen!!!
      2  decrement regen duration
      2  add regen with duration 50, again, resetting current duration to 50
      2  check regen (duration % 50) == 0 ? yep! regen!!!
      3  and so on
    

    The order of the potion effect check and duration decrement may be off, but the idea is the same.

  11. Entity#getLookVec returns a normalized vector, which means the 'length' of the vector should equal 1. X, Y, and Z should all be values between -1.0F and 1.0F, i.e. values on the unit circle.

     

    The look vector is determined using the entity's head rotation, not their body rotation - these are separate values. If you want to use the entity's body rotation to determine the path of the attack, you will need to copy the Entity#getLook method and swap in this.rotationYaw in place of this.rotationYawHead:

    // from Entity#getLook(float) when the parameter = 1.0F, which is what is called from #getLookVec
    return this.getVectorForRotation(this.rotationPitch, this.rotationYawHead); // note it uses HEAD yaw
    

    Using #getVectorForRotation with the entity's body rotation should work, I would imagine.

  12. Is your 'Pokémon'-like entity already coded?

    Do you have a spawn egg for your entity?

    Do you understand how ItemStack NBT works?

     

    If you can answer yes to all 3, then the solution should be pretty straightforward:

     

    Basically, when you spawn the entity with your egg (or similar item), if the ItemStack has an NBTTagCompound and that tag has a key for 'health' (aka 'durability'), retrieve the value and set the entity's current health to that value after it is spawned.

     

    When you snatch the entity into your Pokéball or whatever on right click, store the entity class/type just as the spawn eggs do, and add an NBTTagCompound with the entity's current health as a tag.

  13. Ray tracing is available on the server side as well...

    MovingObjectPosition mop = world.rayTraceBlocks(vec3OriginPosition, vec3TargetPosition);
    

    Where both arguments are a Vec3, the first being the point of origin, and the second being some location off in the distance you are trying to reach - if the mop is null, there is nothing in the way; otherwise it will have information about the first block encountered between the two positions.

     

    Like I mentioned above, you don't want any of your logic that is responsible for affecting the world to run on the client - this includes setting blocks on fire, spawning blocks, etc. Do ALL of that on the server.

     

    For your visuals, if you don't need them to be super precise, you can do what the Explosion class does and allow the code to run on the client, too, for the sole purpose of spawning particles. The affected block positions will not necessarily be identical to what the server decides was affected, so there can/will be some mismatch. If you need the positions to be exact, then you will probably need to send a packet with each or all of the affected positions to notify the client where to spawn the particles.

     

    Note how the above solution is 'server affects blocks, sends notification to client' rather than 'client determines affected blocks, sends list to server'. That is always the flow you should aim for.

     

    As for targeting code, what exactly are you trying to do? What I mean is, non-player entities don't aim, they target whatever you tell them to target, so I'm not sure what problem you are trying to solve here. Do you only want your entity to be able to attack players in front of it? Are you having issues finding a player to attack? I need more information.

  14. #getArmorModel is called before the model is rendered, obviously, which means that ModelBiped#setRotationAngles is called AFTER the model has been retrieved, so you shouldn't need to manually set any of those fields.

     

    You can call ModelBiped#setModelAttributes(ModelBase model) using the _default ModelBiped parameter passed to you from #getArmorModel and it will copy the needed values over to your model.

     

    Also, ModelBiped is CLIENT side only, so this:

    private ModelBiped armorModel = new ModelBiped(scale);
    

    will crash your game if you run your mod on a server. You need to either lazy initialize the field when you retrieve the model for the first time, or find some other way of doing it (such as initializing the models to use for each item in your ClientProxy).

     

    If you want to store the field as a class field, you will need to add @SideOnly(Side.CLIENT) annotation above it so it is stripped from the server jar:

    @SideOnly(Side.CLIENT)
    private ModelBiped armorModel; // cannot inline initialize without crashing the server
    

  15. Its not just the aiming however but ok ill try youre suggestion and maybe see if i can only use server side values

    Okay, so what other reasons do you have for wanting your code to run on the client side?

     

    Keep in mind that the client is ONLY responsible for things like rendering the world, displaying GUIs on the screen, and taking input from the player and sending it to the server. Some methods run on both sides to make the interaction smoother, but the server is the final arbiter of the outcome.

     

    E.g. when you (a player) attack an entity, the client also runs the code so that the player can immediately see the visible result of their action (the attacked entity appearing to take damage, the sword losing durability, etc.) without waiting for a response from the server, but that is only for visuals - the server is the one that actually determines if the entity takes damage, how much, etc., and the sword's new durability, etc. The client side values are irrelevant except for that immediate feedback to the player.

     

    Look at every other mob's AI / attack code and you will see it only runs on the server. At most, the entity will send a packet to notify the client that it is attacking so that it can perform an animation or spawn particles, nothing more.

     

    LivingAttackEvent, LivingHurtEvent, etc. all only fire on the server side, with the sole exception of when the aggressor is an EntityPlayer, in which case some of those events fire on both sides.

     

    My point is that even if you allow the code to run on both sides, it sounds like you are using it wrong. 'Aiming' only occurs due to player input on the client - every other entity determines what it can strike on the server.

     

    If you have animations or particles that you want to happen, use #setEntityState on the server at the appropriate time to send a custom flag to #handleHealthUpdate - open up the call hierarchy of both methods to see how they are used in many entities, e.g. EntityIronGolem, EntityVillager, etc.

  16. The Minecraft class is CLIENT side only, and the player returned by Minecraft.getMinecraft().thePlayer is the client player - of course this is crashing when you try to run it on the SERVER.

     

    I'm not sure why the x coordinate would be off by one only in single player, but I can imagine that it may instead have to do with the player's position and the bed position not matching entirely: a bed is 2 blocks and may be oriented along either the x or z axis, whereas the player position will only ever give you 1 block coordinate.

     

    Given that, I don't find it hard to believe that the player position will sometimes not be exactly what you'd expect the bed to be. Why don't you use EntityPlayer#getBedLocation to get their bed's actual location, rather than expecting the player's position to match perfectly?

  17. Many Forge mods alter vanilla behaviors and characteristics using hooks that Forge provides, such as the wonderful @SubscribeEvent system.

     

    Most mods do not directly alter any vanilla class files; those that do tend to use what's known as byte code manipulation to dynamically modify the .jar file so that their mod is more likely to be compatible with others.

     

    99.9999999% of the time, you do not need to modify any vanilla class files.

     

    In your case, Forge provides the AnvilUpdateEvent; this has a public field called 'cost' which is the amount of levels the transaction requires, and you can listen to the event, check the anvil contents, and modify the cost to whatever you want.

     

    If you truly do have plenty of Java experience, then once you get a basic modding workspace set up, this should be pretty straightforward for you to accomplish.

  18. Why not start by looking at slabs? Specifically, look at the model .json and Block class files.

     

    In the model .json, you will have the block's rendering bounds described, as well as the rotations for different states (such as facing north-south or east-west).

     

    Then in your Block class, you will need to make sure that the block's physical bounds match based on its current state, etc.

     

    I recommend you Google a basic 1.8 block tutorial and make some basic blocks first, then practice making blocks with different sizes, such as a small cube. Just play with the values in the .json and Block class, fire up your IDE's test environment, and see how it looks in game. Then quit, change the values, see how it looks again, rinse and repeat. That is how modding generally works.

  19. I still need to figure out how to get the aiming code working (that would require the invnetory to be on client side also so that the onItemRightClick method can be called on client and server just like the player one does

    Is the aiming code the reason you think you need the code to run client side? If so, you don't. You can write aiming code that works just fine on the server - the only reason the player has code running on the client side is because that's where player input (i.e. mouse and keyboard) comes from, so it makes sense to say 'hey client, where is the player's mouse pointing right now?'.

     

    In the context of a non-player entity, however, that doesn't make much sense. Much better to use the server side values for the entity to determine if it can attack the player or not, using the entity's look vector to determine what it is looking at, geometry based on the entity's rotation vs. the player's position, or even just proximity as most vanilla mobs do.

×
×
  • Create New...

Important Information

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