2
\$\begingroup\$

I am writing a mod for Minecraft (in Java, duh) and want to apply a random potion effect like this:

    private static Effect[] poss_effects = new Effect[]{
        Effects.SPEED,
        Effects.SLOWNESS,
        Effects.HASTE,
        Effects.MINING_FATIGUE,
        Effects.STRENGTH,
        Effects.INSTANT_HEALTH,
        Effects.INSTANT_DAMAGE,
        Effects.JUMP_BOOST,
        Effects.NAUSEA,
        Effects.REGENERATION,
        Effects.RESISTANCE,
        Effects.FIRE_RESISTANCE,
        Effects.WATER_BREATHING,
        Effects.INVISIBILITY,
        Effects.BLINDNESS,
        Effects.NIGHT_VISION,
        Effects.HUNGER,
        Effects.WEAKNESS,
        Effects.POISON,
        Effects.WITHER,
        Effects.HEALTH_BOOST,
        Effects.ABSORPTION,
        Effects.SATURATION,
        Effects.GLOWING,
        Effects.LEVITATION,
        Effects.LUCK,
        Effects.UNLUCK,
        Effects.SLOW_FALLING,
        Effects.CONDUIT_POWER,
        Effects.DOLPHINS_GRACE,
        Effects.BAD_OMEN,
        Effects.HERO_OF_THE_VILLAGE
    };
    
    private long prev_milli = System.currentTimeMillis();

    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
        if (System.currentTimeMillis() - this.prev_milli >= 60000) {
            Effect to_apply = poss_effects[(int) (Math.random() * poss_effects.length)];
            int duration = (int) (Math.random() * 15 * 20);
            int amplifier = (int) (Math.random() * 2);
            playerIn.addPotionEffect(new EffectInstance(to_apply, duration, amplifier));
            this.prev_milli = System.currentTimeMillis();
        }
        return super.onItemRightClick(worldIn, playerIn, handIn);
    }

However, when the timer ticks down to zero on the potion effect, the effect stays there with the timer at 0:00. The first time I right-click it, I get two potion effects: one that works properly and only lasts for the given amount of time and one that has the problem described previously. All subsequent right-clicks produce the latter.

When I do this:

    @Override
    public boolean hitEntity(ItemStack stack, LivingEntity target, LivingEntity attacker) {
        target.addPotionEffect(new EffectInstance(Effects.WITHER, 60, 2));
        target.setHeadRotation((float) (Math.random() * 360), (int) (Math.random() * 180 - 90));
        
        return super.hitEntity(stack, target, attacker);
    }

the effect applies normally and runs out normally every time I hit an entity.

What's wrong?

\$\endgroup\$
  • \$\begingroup\$ Is it wanted to get 2 potion effects on the first click ? \$\endgroup\$ – Samuel Fyckes Oct 5 at 18:45
  • \$\begingroup\$ @SamuelFyckes -- No, just one. \$\endgroup\$ – Voldemort's Wrath Oct 5 at 21:45
  • \$\begingroup\$ and what is the line "if (System.currentTimeMillis() - this.prev_milli >= 60000)" for ? \$\endgroup\$ – Samuel Fyckes Oct 6 at 14:15
  • \$\begingroup\$ @SamuelFyckes -- It makes a 60 second cooldown. \$\endgroup\$ – Voldemort's Wrath Oct 6 at 16:44
  • \$\begingroup\$ Is there a chance that the problem come from the fact that you are trying to interact on the client side instead of the server side ? \$\endgroup\$ – Samuel Fyckes Oct 7 at 14:31
2
+100
\$\begingroup\$

I haven't actually implemented a Minecraft Mod. This answer is a bit of speculation, based on some old tutorials.

Your method onItemRightClick will be called twice. Once for the client, and once for the server. And, this remains true in single player on modern Minecraft, given that it uses an internal server.

On the other hand, hitEntity would run only on the server.

In onItemRightClick, you need to check world.isRemote. More precisely, when world.isRemote is true, you are in the client (then you can play sound effects, and stuff), while the logic (applying a potion effect in this case) should run on the server (that is when world.isRemote is false).

As it stand, you get a real effect applied on the server, and a fake one applied on the client.

It appears that the fake effect keeps being applied while the real one isn't. It makes sense that it does not apply the real effect again, given the time out. And it also makes sense that it does not sync prev_milli between server and client. However that does not explain why it does not timeout on the client. On that part, I have no idea... But a suggestion: use addChatMessage (I think that is the method, should be on the player object) to show the value of prev_milli on the chat and see what you get. Show world.isRemote while you are at it. That should help debugging.


Unless I'm all wrong about this. I also want to mention that I have seen many tutorials not call super.onItemRightClick, I don't know what difference it makes. To guess over my guess, removing it prevents onItemRightClick from running on the client.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer! I'll check it out and get back to you. \$\endgroup\$ – Voldemort's Wrath Oct 7 at 15:25
  • \$\begingroup\$ But also, the "real" effect only applies the first time I right-click, not subsequent times. Do you know why that is? \$\endgroup\$ – Voldemort's Wrath Oct 7 at 15:26
  • \$\begingroup\$ @Voldemort'sWrath I don't know, my suspicions are with the cool down. That is, the server saying the cool down is not over but the client saying it is. \$\endgroup\$ – Theraot Oct 7 at 15:46
  • \$\begingroup\$ I just tried your solution, and it works! Thanks so much! \$\endgroup\$ – Voldemort's Wrath Oct 8 at 21:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.