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\$
5
  • \$\begingroup\$ Is it wanted to get 2 potion effects on the first click ? \$\endgroup\$ Commented Oct 5, 2020 at 18:45
  • \$\begingroup\$ @SamuelFyckes -- No, just one. \$\endgroup\$ Commented Oct 5, 2020 at 21:45
  • \$\begingroup\$ and what is the line "if (System.currentTimeMillis() - this.prev_milli >= 60000)" for ? \$\endgroup\$ Commented Oct 6, 2020 at 14:15
  • \$\begingroup\$ @SamuelFyckes -- It makes a 60 second cooldown. \$\endgroup\$ Commented Oct 6, 2020 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\$ Commented Oct 7, 2020 at 14:31

1 Answer 1

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.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks for the answer! I'll check it out and get back to you. \$\endgroup\$ Commented Oct 7, 2020 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\$ Commented Oct 7, 2020 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
    Commented Oct 7, 2020 at 15:46
  • \$\begingroup\$ I just tried your solution, and it works! Thanks so much! \$\endgroup\$ Commented Oct 8, 2020 at 21:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .