Healing Campfire (Fabric)

Healing Campfire (Fabric)

374k Downloads

Bottle Your XP doesn't decrease levels if level curve is changed

Partonetrain opened this issue ยท 3 comments

commented

Information

Minecraft version: 1.20.1
Modloader: Fabric
Fabric loader version: 0.15.11
Environment: Both Singleplayer / Multiplayer

Mod name: Bottle Your XP
Mod version: 3.3

Collective version 1.20.1-7.6.1 (I think this is where the issue lies ... seems like experience curve is hardcoded here instead of referencing Player#getXpNeededForNextLevel)

Description

When experience level curve is changed, Bottling does not decrease level amount, only points, making experience dupable. To reproduce, set own level with commands, then shift-click glass bottle

No crash.

commented

I am unsure how to fix this. I see you're the author of the mod, could you help me out?

I'm already checking for player.getXpNeededForNextLevel():

https://github.com/Serilum/Collective/blob/1.21.0/Common/src/main/java/com/natamus/collective/functions/ExperienceFunctions.java#L31

But I guess this is hardcoded?

https://github.com/Serilum/Collective/blob/1.21.0/Common/src/main/java/com/natamus/collective/functions/ExperienceFunctions.java#L70

commented

Unfortunately I don't think there's a better way to re-implement getExperienceForLevel than just making it build a list of level->exp conversions (using player.getXpNeededForNextLevel())

commented

I was having the same issue with Fixed Levels, where I have all the levels set to cost the same amount of xp.
I don't know java but I guess the collective library is using the vanilla curve? what functions should I edit so it recognizes that my levels take 30 points of xp?

edit: I gave it a shot to edit ExperienceFunctions but I don't know how to build the project.

Here's my code:
package com.natamus.collective.functions;

import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;

public class ExperienceFunctions {
   public static boolean canConsumeXp(final Player ep, final int xp) {
   	if (ep.isCreative()) {
   		return true;
   	}
   	return xp <= 0 || getPlayerXP(ep) >= xp;
   }

   public static void consumeXp(final Player ep, final int xp) {
   	if (xp <= 0) {
   		return;
   	}

   	final int playerXP = getPlayerXP(ep);
   	if (playerXP >= xp) {
   		addPlayerXP(ep, -xp);
   	}

   	if (ep instanceof ServerPlayer) {
   		((ServerPlayer) ep).connection.send(new ClientboundEntityEventPacket(ep, (byte) 9));
   	}
   }

   public static int getPlayerXP(final Player player) {
   	return (int) (getExperienceForLevel(player.experienceLevel) + player.experienceProgress);
   }

   public static void addPlayerXP(final Player player, final int amount) {
   	final int experience = getPlayerXP(player) + amount;
   	player.totalExperience = experience;
   	player.experienceLevel = getLevelForExperience(experience);
   	final int expForLevel = getExperienceForLevel(player.experienceLevel);
   	player.experienceProgress = (float) (experience - expForLevel);
   }

   public static int getLevelForExperience(int targetXp) {
   	int target = targetXp / 30;
   	return target;
   }

   public static int getExperienceForLevel(final int level) {
   	if (level == 0) {
   		return 0;
   	} else {
   		return level * 30;
   	}
   }
}