Rewrote TotemItem methods to simplify usage and keep functionality within the same class.

This commit is contained in:
2026-01-10 19:24:37 +01:00
parent b400f4334a
commit 300e0a940a

View File

@ -10,10 +10,13 @@ import dev.micle.totemofreviving.setup.ModDataComponents;
import dev.micle.totemofreviving.setup.ModKeyMappings; import dev.micle.totemofreviving.setup.ModKeyMappings;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList;
import net.minecraft.stats.Stats; import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -25,6 +28,7 @@ import net.neoforged.api.distmarker.OnlyIn;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -38,125 +42,121 @@ public abstract class TotemItem extends Item {
super(new Properties().stacksTo(1).rarity(rarity).durability(durability)); super(new Properties().stacksTo(1).rarity(rarity).durability(durability));
} }
public abstract boolean isCharge(ItemStack stack);
public abstract Config.TotemConfig getConfig();
private boolean isChargeFull(TotemData totemData) {
return totemData.getCharge() >= getMaxCharge();
}
private int getMaxCharge() {
return getConfig().getChargeCost() == -1
? getConfig().getChargeCostLimit()
: getConfig().getChargeCost();
}
private int getTargetCost(TotemData totemData) {
return getConfig().getChargeCost() != -1
? getConfig().getChargeCost()
: (int)(totemData.getTargetDeaths() * getConfig().getChargeCostMultiplier());
}
private boolean canAffordTarget(TotemData totemData) {
return totemData.getCharge() >= getTargetCost(totemData) || (isChargeFull(totemData) && getConfig().getCanReviveMoreExpensiveTargets());
}
private static TotemData getTotemData(ItemStack itemStack) {
return itemStack.getComponents().get(ModDataComponents.TOTEM_DATA.get());
}
private static void setTotemData(ItemStack itemStack, TotemData totemData) {
itemStack.set(ModDataComponents.TOTEM_DATA.get(), totemData);
}
public static boolean isTotem(ItemStack stack) { public static boolean isTotem(ItemStack stack) {
return (stack.getItem() instanceof TotemItem); return (stack.getItem() instanceof TotemItem);
} }
public abstract boolean isCharge(ItemStack stack); @OnlyIn(Dist.DEDICATED_SERVER)
public static Optional<TotemData> cycleTarget(ItemStack itemStack, PlayerList playerList) {
if (!isTotem(itemStack)) return Optional.empty();
TotemData totemData = getTotemData(itemStack);
public static Optional<Integer> getTargetIndex(ItemStack stack) { int targetIndex = totemData.getTargetIndex() + 1;
return getTotemData(stack).flatMap(totemData -> Optional.of(totemData.getTargetIndex())); targetIndex = targetIndex > playerList.getPlayerCount() ? 0 : targetIndex;
}
public static void setTargetIndex(ItemStack stack, int targetIndex) {
Optional<TotemData> data = getTotemData(stack);
if (data.isEmpty()) { return; }
data.get().setTargetIndex(targetIndex); ServerPlayer target = playerList.getPlayers().get(targetIndex);
stack.set(ModDataComponents.TOTEM_DATA.get(), data.get());
totemData.setTargetIndex(targetIndex);
totemData.setTargetUUID(target.getStringUUID());
totemData.setTargetName(target.getScoreboardName());
totemData.setTargetDeaths(target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)));
setTotemData(itemStack, totemData);
return Optional.of(totemData);
} }
public static Optional<UUID> getTargetUUID(ItemStack stack) { @OnlyIn(Dist.DEDICATED_SERVER)
return getTotemData(stack).flatMap(totemData -> Optional.of(UUID.fromString(totemData.getTargetUUID()))); public static boolean chargeTotem(ItemStack totemStack, ItemStack chargeStack) {
} if (!isTotem(totemStack)) return false;
public static void setTargetUUID(ItemStack stack, UUID targetUUID) { TotemData totemData = getTotemData(totemStack);
Optional<TotemData> data = getTotemData(stack); TotemItem totemItem = ((TotemItem) totemStack.getItem());
if (data.isEmpty()) { return; }
data.get().setTargetUUID(targetUUID.toString()); if (!totemItem.isCharge(chargeStack)) return false;
stack.set(ModDataComponents.TOTEM_DATA.get(), data.get()); if (totemItem.isChargeFull(totemData)) return false;
totemData.setCharge(totemData.getCharge() + 1);
setTotemData(totemStack, totemData);
chargeStack.setCount(chargeStack.getCount() - 1);
return true;
} }
public static Optional<String> getTargetName(ItemStack stack) { @OnlyIn(Dist.DEDICATED_SERVER)
return getTotemData(stack).flatMap(totemData -> Optional.of(totemData.getTargetName())); public static Component reviveTarget(EquipmentSlot slot, ItemStack itemStack, ServerPlayer user, PlayerList playerList) {
} if (!isTotem(itemStack)) return Component.empty();
public static void setTargetName(ItemStack stack, String targetName) { TotemData totemData = getTotemData(itemStack);
Optional<TotemData> data = getTotemData(stack); TotemItem totemItem = ((TotemItem) itemStack.getItem());
if (data.isEmpty()) { return; } Config.TotemConfig config = totemItem.getConfig();
data.get().setTargetName(targetName); ServerPlayer target = playerList.getPlayer(UUID.fromString(totemData.getTargetUUID()));
stack.set(ModDataComponents.TOTEM_DATA.get(), data.get()); if (target == null) {
} return Component.literal(ChatFormatting.WHITE + "Unable to find player!");
}
public static Optional<Integer> getTargetDeaths(ItemStack stack) { totemData.setTargetDeaths(target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)));
return getTotemData(stack).flatMap(totemData -> Optional.of(totemData.getTargetDeaths())); setTotemData(itemStack, totemData);
}
public static void setTargetDeaths(ItemStack stack, ServerPlayer target) {
Optional<TotemData> data = getTotemData(stack);
if (data.isEmpty()) { return; }
data.get().setTargetDeaths(target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS))); if (!target.isSpectator()) {
stack.set(ModDataComponents.TOTEM_DATA.get(), data.get()); return Component.literal(ChatFormatting.GRAY + target.getDisplayName().getString() + ChatFormatting.WHITE + " is not dead!");
} }
public static Optional<Integer> getCharge(ItemStack stack) { try (ServerLevel targetLevel = target.serverLevel()) {
return getTotemData(stack).flatMap(totemData -> Optional.of(totemData.getCharge())); if (!targetLevel.equals(user.serverLevel()) && !config.getCanReviveAcrossDimensions()) {
} return Component.literal(ChatFormatting.GRAY + target.getDisplayName().getString() + ChatFormatting.WHITE + " is in a different dimension!");
public static void setCharge(ItemStack stack, int charge) { }
Optional<TotemData> data = getTotemData(stack); } catch (IOException e) {
if (data.isEmpty()) { return; } return Component.literal(ChatFormatting.WHITE + "Unable to get " + ChatFormatting.GRAY + target.getDisplayName().getString() + "'s " + ChatFormatting.WHITE + " level!");
}
data.get().setCharge(charge); if (!totemItem.canAffordTarget(totemData)) {
stack.set(ModDataComponents.TOTEM_DATA.get(), data.get()); return Component.literal(ChatFormatting.WHITE + "Not enough charge!");
} }
public static Optional<Integer> getTargetCost(ItemStack stack) { try (ServerLevel userLevel = user.serverLevel()) {
Optional<Config.TotemConfig> config = getConfig(stack); target.teleportTo(userLevel, user.position().x, user.position().y, user.position().z, user.getYRot(), user.getXRot());
Optional<Integer> targetDeaths = getTargetDeaths(stack); target.setGameMode(userLevel.getServer().getDefaultGameType());
if (config.isEmpty() || targetDeaths.isEmpty()) { return Optional.empty(); } } catch (IOException e) {
return Component.literal(ChatFormatting.WHITE + "Unable to get your level!");
}
return Optional.of( totemData.setCharge(totemData.getCharge() - totemItem.getTargetCost(totemData));
config.get().getChargeCost() != -1
? config.get().getChargeCost()
: (int)(targetDeaths.get() * config.get().getChargeCostMultiplier())
);
}
public static Optional<Integer> getMaxCharge(ItemStack stack) { setTotemData(itemStack, totemData);
return getConfig(stack).map(totemConfig -> totemConfig.getChargeCost() == -1 itemStack.hurtAndBreak(1, user, slot);
? totemConfig.getChargeCostLimit()
: totemConfig.getChargeCost()
);
}
public static Optional<Boolean> isTotemFull(ItemStack stack) { return Component.literal(ChatFormatting.WHITE + "Successfully revived " + ChatFormatting.GRAY + target.getDisplayName().getString() + "!");
Optional<Config.TotemConfig> config = getConfig(stack);
Optional<Integer> charge = getCharge(stack);
Optional<Integer> maxCharge = getMaxCharge(stack);
if (config.isEmpty() || charge.isEmpty() || maxCharge.isEmpty()) { return Optional.empty(); }
return Optional.of(charge.get().equals(maxCharge.get()));
}
public static Optional<Boolean> canTotemAffordTarget(ItemStack stack) {
Optional<Integer> charge = getCharge(stack);
Optional<Integer> targetCost = getTargetCost(stack);
Optional<Boolean> isTotemFull = isTotemFull(stack);
Optional<Boolean> canReviveMoreExpensiveTargets = canReviveMoreExpensiveTargets(stack);
if (charge.isEmpty() || targetCost.isEmpty() || isTotemFull.isEmpty() || canReviveMoreExpensiveTargets.isEmpty()) { return Optional.empty(); }
return Optional.of(charge.get() >= targetCost.get() || (isTotemFull.get() && canReviveMoreExpensiveTargets.get()));
}
public static Optional<Boolean> canReviveAcrossDimensions(ItemStack stack) {
return getConfig(stack).map(Config.TotemConfig::getCanReviveAcrossDimensions);
}
public static Optional<Boolean> canReviveMoreExpensiveTargets(ItemStack stack) {
return getConfig(stack).map(Config.TotemConfig::getCanReviveMoreExpensiveTargets);
}
private static Optional<TotemData> getTotemData(ItemStack stack) {
return Optional.ofNullable(stack.getComponents().get(ModDataComponents.TOTEM_DATA.get()));
}
private static Optional<Config.TotemConfig> getConfig(ItemStack stack) {
return switch (stack.getItem()) {
case StrawTotemItem ignored -> Optional.of(Config.Server.getStrawTotemConfig());
case IronTotemItem ignored -> Optional.of(Config.Server.getIronTotemConfig());
case DiamondTotemItem ignored -> Optional.of(Config.Server.getDiamondTotemConfig());
case NetheriteTotemItem ignored -> Optional.of(Config.Server.getNetheriteTotemConfig());
default -> Optional.empty();
};
} }
@Override @Override