diff --git a/src/api/java/de/teamlapen/vampirism/api/VampirismDataComponents.java b/src/api/java/de/teamlapen/vampirism/api/VampirismDataComponents.java index 6e1106259..ecb521e7f 100644 --- a/src/api/java/de/teamlapen/vampirism/api/VampirismDataComponents.java +++ b/src/api/java/de/teamlapen/vampirism/api/VampirismDataComponents.java @@ -46,5 +46,6 @@ public static class Keys { public static final ResourceLocation FRUGALITY = VResourceLocation.mod( "frugality"); public static final ResourceLocation IS_FACTION_BANNER = VResourceLocation.mod("is_faction_banner"); public static final ResourceLocation VAMPIRE_FOOD = VResourceLocation.mod("vampire_food"); + public static final ResourceLocation FACTION_RESTRICTION = VResourceLocation.mod("faction_restriction"); } } diff --git a/src/api/java/de/teamlapen/vampirism/api/entity/factions/IFactionRegistry.java b/src/api/java/de/teamlapen/vampirism/api/entity/factions/IFactionRegistry.java index 62d52fa97..0dbcc429a 100755 --- a/src/api/java/de/teamlapen/vampirism/api/entity/factions/IFactionRegistry.java +++ b/src/api/java/de/teamlapen/vampirism/api/entity/factions/IFactionRegistry.java @@ -8,6 +8,7 @@ import net.minecraft.world.entity.ai.targeting.TargetingConditions; import net.minecraft.world.entity.player.Player; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; @@ -18,10 +19,10 @@ public interface IFactionRegistry { - @Nullable + @NotNull Holder> getFaction(Entity entity); - @Nullable + @NotNull Holder> getFaction(Player entity); boolean isEntityOfFaction(Entity entity, Holder> faction); diff --git a/src/api/java/de/teamlapen/vampirism/api/items/IFactionExclusiveItem.java b/src/api/java/de/teamlapen/vampirism/api/items/IFactionExclusiveItem.java deleted file mode 100644 index 97da43f04..000000000 --- a/src/api/java/de/teamlapen/vampirism/api/items/IFactionExclusiveItem.java +++ /dev/null @@ -1,63 +0,0 @@ -package de.teamlapen.vampirism.api.items; - -import de.teamlapen.vampirism.api.VampirismAPI; -import de.teamlapen.vampirism.api.VampirismDataComponents; -import de.teamlapen.vampirism.api.VampirismRegistries; -import de.teamlapen.vampirism.api.components.IAppliedOilContent; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import net.minecraft.ChatFormatting; -import net.minecraft.core.Holder; -import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.ItemLike; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * Should be implemented by all items that are supposed to be used by only a specific faction. - */ -public interface IFactionExclusiveItem extends ItemLike { - - default void addFactionToolTips(@NotNull ItemStack stack, @Nullable Item.TooltipContext context, @NotNull List tooltip, TooltipFlag flagIn, @Nullable Player player) { - addOilDescTooltip(stack, context, tooltip, flagIn, player); - tooltip.add(Component.empty()); - tooltip.add(Component.translatable("text.vampirism.faction_specifics").withStyle(ChatFormatting.GRAY)); - TagKey> factionTag = getExclusiveFaction(stack); - - for (Holder> faction : VampirismRegistries.FACTION.get().getTagOrEmpty(factionTag)) { - var color = ChatFormatting.GRAY; - if (player != null) { - color = IFaction.is(VampirismAPI.factionRegistry().getFaction(player), faction) ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED; - } - tooltip.add(Component.literal(" ").append(faction.value().getName()).withStyle(color)); - } - } - - /** - * In case a faction specific item is applied with oil, this will add the oil specific tooltip at the correct position. - * Otherwise, the default oil tooltip handler {@link de.teamlapen.vampirism.client.core.ClientEventHandler#onItemToolTip(net.neoforged.neoforge.event.entity.player.ItemTooltipEvent)} would put it at the wrong position. - *

- * This must produce the same tooltip line as the default handler. - */ - @SuppressWarnings("JavadocReference") - default void addOilDescTooltip(@NotNull ItemStack stack, @Nullable Item.TooltipContext context, @NotNull List tooltip, TooltipFlag flagIn, @Nullable Player player) { - IAppliedOilContent appliedOil = stack.get(VampirismDataComponents.APPLIED_OIL.get()); - if (appliedOil != null) { - if (appliedOil.duration() > 0) { - appliedOil.oil().value().getToolTipLine(stack, appliedOil.oil().value(), appliedOil.duration(), flagIn).ifPresent(tooltip::add); - } - } - } - - /** - * @return The faction that can use this item or null if any - */ - @NotNull - TagKey> getExclusiveFaction(@NotNull ItemStack stack); -} diff --git a/src/api/java/de/teamlapen/vampirism/api/items/IFactionLevelItem.java b/src/api/java/de/teamlapen/vampirism/api/items/IFactionLevelItem.java deleted file mode 100755 index b6b8844da..000000000 --- a/src/api/java/de/teamlapen/vampirism/api/items/IFactionLevelItem.java +++ /dev/null @@ -1,58 +0,0 @@ -package de.teamlapen.vampirism.api.items; - -import de.teamlapen.vampirism.api.VampirismAPI; -import de.teamlapen.vampirism.api.entity.factions.IFactionPlayerHandler; -import de.teamlapen.vampirism.api.entity.player.IFactionPlayer; -import de.teamlapen.vampirism.api.entity.player.ISkillPlayer; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; -import net.minecraft.ChatFormatting; -import net.minecraft.core.Holder; -import net.minecraft.network.chat.Component; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * Item's implementing this can only be used by players that match the requirements. - * Currently, only affects {@link Player#attack(Entity)} and {@link Player#startUsingItem(InteractionHand)} - */ -public interface IFactionLevelItem & ISkillPlayer> extends IFactionExclusiveItem { - - @Override - default void addFactionToolTips(@NotNull ItemStack stack, Item.@Nullable TooltipContext worldIn, @NotNull List tooltip, TooltipFlag flagIn, @Nullable Player player) { - IFactionPlayerHandler playerHandler = player != null ? VampirismAPI.factionPlayerHandler(player) : null; - - IFactionExclusiveItem.super.addFactionToolTips(stack, worldIn, tooltip, flagIn, player); - - boolean correctFaction = playerHandler != null && playerHandler.isInFaction(getExclusiveFaction(stack)); - int minLevel = getMinLevel(stack); - if (minLevel > 1) { - tooltip.add(Component.literal(" ").append(Component.translatable("text.vampirism.required_level", String.valueOf(minLevel))).withStyle(correctFaction ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED)); - } - Holder> requiredSkill = requiredSkill(stack); - if (requiredSkill != null) { - tooltip.add(Component.literal(" ").append(Component.translatable("text.vampirism.required_skill", requiredSkill.value().getName())).withStyle(correctFaction && playerHandler.getCurrentSkillPlayer().map(p -> p.getSkillHandler().isSkillEnabled(requiredSkill)).orElse(false) ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED)); - } - } - - - /** - * @return The level the player has to be to use this item - */ - int getMinLevel(@NotNull ItemStack stack); - - /** - * @return The skill required to use this or null if none - */ - @Nullable - default Holder> requiredSkill(@NotNull ItemStack stack) { - return null; - } -} diff --git a/src/api/java/de/teamlapen/vampirism/api/items/IRefinementItem.java b/src/api/java/de/teamlapen/vampirism/api/items/IRefinementItem.java index 66f926880..e76d80979 100644 --- a/src/api/java/de/teamlapen/vampirism/api/items/IRefinementItem.java +++ b/src/api/java/de/teamlapen/vampirism/api/items/IRefinementItem.java @@ -5,6 +5,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.util.StringRepresentable; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,7 +14,7 @@ * * @implSpec should only be implemented by {@link net.minecraft.world.item.Item}s */ -public interface IRefinementItem extends IFactionExclusiveItem { +public interface IRefinementItem extends ItemLike { /** * Gets the refinement set that is applied to this refinement item diff --git a/src/api/java/de/teamlapen/vampirism/api/items/IVampirismCrossbowArrow.java b/src/api/java/de/teamlapen/vampirism/api/items/IVampirismCrossbowArrow.java index 0edf1e973..7ce496665 100644 --- a/src/api/java/de/teamlapen/vampirism/api/items/IVampirismCrossbowArrow.java +++ b/src/api/java/de/teamlapen/vampirism/api/items/IVampirismCrossbowArrow.java @@ -12,18 +12,14 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -public interface IVampirismCrossbowArrow extends IFactionExclusiveItem { - - @Override - default @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return VampirismTags.Factions.IS_HUNTER; - } +public interface IVampirismCrossbowArrow extends ItemLike { /** * @return If an arrow of this type can be used in an infinite crossbow diff --git a/src/main/java/de/teamlapen/vampirism/client/core/ClientEventHandler.java b/src/main/java/de/teamlapen/vampirism/client/core/ClientEventHandler.java index 4db15a960..ae90ee9fc 100755 --- a/src/main/java/de/teamlapen/vampirism/client/core/ClientEventHandler.java +++ b/src/main/java/de/teamlapen/vampirism/client/core/ClientEventHandler.java @@ -1,24 +1,16 @@ package de.teamlapen.vampirism.client.core; -import com.google.common.collect.Lists; -import de.teamlapen.vampirism.REFERENCE; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.api.util.VResourceLocation; import de.teamlapen.vampirism.client.VampirismModClient; import de.teamlapen.vampirism.config.VampirismConfig; -import de.teamlapen.vampirism.core.ModBlocks; -import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.data.ClientSkillTreeData; import de.teamlapen.vampirism.effects.VampirismPotion; import de.teamlapen.vampirism.entity.player.LevelAttributeModifier; import de.teamlapen.vampirism.items.component.AppliedOilContent; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.util.Helper; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -35,11 +27,6 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; - /** * Handle general client side events */ @@ -86,24 +73,8 @@ static void onModelRegistry(@NotNull ModelEvent.RegisterAdditional event) { */ @SubscribeEvent public void onItemToolTip(@NotNull ItemTooltipEvent event) { - if (event.getItemStack().getItem() instanceof IFactionExclusiveItem) return; - AppliedOilContent.getAppliedOil(event.getItemStack()).ifPresent(oil -> { - List toolTips = event.getToolTip(); - int position = 1; - if (!event.getItemStack().has(DataComponents.HIDE_ADDITIONAL_TOOLTIP)) { - ArrayList additionalComponents = new ArrayList<>(); - event.getItemStack().getItem().appendHoverText(event.getItemStack(), event.getContext(), additionalComponents, event.getFlags()); - position += additionalComponents.size(); - Optional oilTooltip = oil.oil().value().getToolTipLine(event.getItemStack(), oil.oil().value(), oil.duration(), event.getFlags()); - if (oilTooltip.isPresent()) { - toolTips.add(position++, oilTooltip.get()); - } - } - List factionToolTips = new ArrayList<>(); - factionToolTips.add(Component.empty()); - factionToolTips.add(Component.translatable("text.vampirism.faction_exclusive", ModFactions.HUNTER.get().getName().plainCopy().withStyle(Minecraft.getInstance().player != null ? Helper.isHunter(Minecraft.getInstance().player) ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED : ChatFormatting.GRAY)).withStyle(ChatFormatting.ITALIC).withStyle(ChatFormatting.GRAY)); - toolTips.addAll(Math.min(event.getToolTip().size(), position), factionToolTips); - }); + AppliedOilContent.addTooltipIfExist(event.getEntity(), event.getItemStack(), event.getToolTip(), event.getFlags()); + FactionRestriction.addTooltipIfExist(event.getEntity(), event.getItemStack(), event.getToolTip()); } diff --git a/src/main/java/de/teamlapen/vampirism/core/ModDataComponents.java b/src/main/java/de/teamlapen/vampirism/core/ModDataComponents.java index 25e19f815..e7caf8f8d 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModDataComponents.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModDataComponents.java @@ -34,6 +34,7 @@ public class ModDataComponents { public static final DeferredHolder, DataComponentType> CROSSBOW_FRUGALITY_TRIGGERED = ITEM_DATA_COMPONENTS.registerComponentType("crossbow_frugality_triggered", (builder) -> builder.persistent(Codec.unit(Unit.INSTANCE)).networkSynchronized(StreamCodec.unit(Unit.INSTANCE))); public static final DeferredHolder, DataComponentType> IS_FACTION_BANNER = ITEM_DATA_COMPONENTS.registerComponentType(VampirismDataComponents.Keys.IS_FACTION_BANNER.getPath(), (builder) -> builder.persistent(Unit.CODEC).networkSynchronized(StreamCodec.unit(Unit.INSTANCE))); public static final DeferredHolder, DataComponentType> VAMPIRE_FOOD = ITEM_DATA_COMPONENTS.registerComponentType(VampirismDataComponents.Keys.VAMPIRE_FOOD.getPath(), (builder) -> builder.persistent(BloodFoodProperties.DIRECT_CODEC).networkSynchronized(BloodFoodProperties.DIRECT_STREAM_CODEC)); + public static final DeferredHolder, DataComponentType> FACTION_RESTRICTION = ITEM_DATA_COMPONENTS.registerComponentType(VampirismDataComponents.Keys.FACTION_RESTRICTION.getPath(), builder -> builder.persistent(FactionRestriction.CODEC).networkSynchronized(FactionRestriction.STREAM_CODEC)); static void register(IEventBus eventBus) { ITEM_DATA_COMPONENTS.register(eventBus); diff --git a/src/main/java/de/teamlapen/vampirism/entity/factions/FactionRegistry.java b/src/main/java/de/teamlapen/vampirism/entity/factions/FactionRegistry.java index 68790ab53..8e0d0522b 100755 --- a/src/main/java/de/teamlapen/vampirism/entity/factions/FactionRegistry.java +++ b/src/main/java/de/teamlapen/vampirism/entity/factions/FactionRegistry.java @@ -6,6 +6,7 @@ import de.teamlapen.vampirism.api.entity.factions.IFactionRegistry; import de.teamlapen.vampirism.api.entity.factions.IPlayableFaction; import de.teamlapen.vampirism.api.entity.minion.IMinionEntry; +import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.core.ModRegistries; import net.minecraft.core.Holder; import net.minecraft.core.Registry; @@ -35,6 +36,7 @@ public class FactionRegistry implements IFactionRegistry { private final MinionEntryCallbacks minionEntryCallbacks = new MinionEntryCallbacks(); + @NotNull @Override public Holder> getFaction(Entity entity) { if (entity instanceof Player player) { @@ -42,10 +44,10 @@ public Holder> getFaction(Entity entity) { } else if (entity instanceof IFactionEntity factionEntity) { return factionEntity.getFaction(); } - return ModRegistries.FACTIONS.listElements().filter(s -> s.value().getTag(Registries.ENTITY_TYPE).flatMap(BuiltInRegistries.ENTITY_TYPE::get).filter(tag -> entity.getType().is(tag)).isPresent()).findFirst().orElse(null); + return ModRegistries.FACTIONS.listElements().map(s -> (Holder>)s).filter(s -> s.value().getTag(Registries.ENTITY_TYPE).flatMap(BuiltInRegistries.ENTITY_TYPE::get).filter(tag -> entity.getType().is(tag)).isPresent()).findFirst().orElse((Holder>) (Object) ModFactions.NEUTRAL); } - @Nullable + @NotNull public Holder> getFaction(Player player) { return FactionPlayerHandler.get(player).getFaction(); } diff --git a/src/main/java/de/teamlapen/vampirism/entity/minion/MinionEntity.java b/src/main/java/de/teamlapen/vampirism/entity/minion/MinionEntity.java index aa87d468e..eae8bb4c2 100644 --- a/src/main/java/de/teamlapen/vampirism/entity/minion/MinionEntity.java +++ b/src/main/java/de/teamlapen/vampirism/entity/minion/MinionEntity.java @@ -5,12 +5,10 @@ import de.teamlapen.lib.lib.storage.ISyncable; import de.teamlapen.lib.lib.storage.UpdateParams; import de.teamlapen.vampirism.VampirismMod; -import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.minion.IMinionEntity; import de.teamlapen.vampirism.api.entity.minion.IMinionInventory; import de.teamlapen.vampirism.api.entity.minion.IMinionTask; import de.teamlapen.vampirism.api.entity.player.ILordPlayer; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.api.util.VResourceLocation; import de.teamlapen.vampirism.entity.VampirismEntity; import de.teamlapen.vampirism.entity.ai.goals.ForceLookEntityGoal; @@ -24,6 +22,7 @@ import de.teamlapen.vampirism.entity.minion.management.MinionTasks; import de.teamlapen.vampirism.entity.minion.management.PlayerMinionController; import de.teamlapen.vampirism.inventory.MinionContainer; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.util.IPlayerOverlay; import de.teamlapen.vampirism.util.Permissions; import de.teamlapen.vampirism.util.PlayerModelType; @@ -452,7 +451,7 @@ public void setItemSlot(@NotNull EquipmentSlot slotIn, @NotNull ItemStack stack) } public @NotNull Predicate getEquipmentPredicate(EquipmentSlot slotType) { - return itemStack -> !(itemStack.getItem() instanceof IFactionExclusiveItem) || IFaction.is(this.getFaction(), ((IFactionExclusiveItem) itemStack.getItem()).getExclusiveFaction(itemStack)); + return itemStack -> FactionRestriction.matchFaction(itemStack, getFaction()); } diff --git a/src/main/java/de/teamlapen/vampirism/entity/player/ModPlayerEventHandler.java b/src/main/java/de/teamlapen/vampirism/entity/player/ModPlayerEventHandler.java index 767d85bdc..615837648 100755 --- a/src/main/java/de/teamlapen/vampirism/entity/player/ModPlayerEventHandler.java +++ b/src/main/java/de/teamlapen/vampirism/entity/player/ModPlayerEventHandler.java @@ -7,10 +7,7 @@ import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.factions.IPlayableFaction; import de.teamlapen.vampirism.api.entity.player.actions.IActionHandler; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.entity.vampire.IVampire; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.items.IFactionSlayerItem; import de.teamlapen.vampirism.blockentity.TotemBlockEntity; import de.teamlapen.vampirism.blocks.AltarInspirationBlock; @@ -22,6 +19,7 @@ import de.teamlapen.vampirism.core.ModEffects; import de.teamlapen.vampirism.core.ModFluids; import de.teamlapen.vampirism.core.ModItems; +import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.effects.VampirismPoisonEffect; import de.teamlapen.vampirism.effects.VampirismPotion; import de.teamlapen.vampirism.entity.factions.FactionPlayerHandler; @@ -31,6 +29,7 @@ import de.teamlapen.vampirism.entity.player.vampire.actions.BatVampireAction; import de.teamlapen.vampirism.items.BloodBottleFluidHandler; import de.teamlapen.vampirism.items.GarlicBreadItem; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.items.crossbow.HunterCrossbowItem; import de.teamlapen.vampirism.util.DamageHandler; import de.teamlapen.vampirism.util.Helper; @@ -50,7 +49,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.DamageTypeTags; -import net.minecraft.tags.TagKey; import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -175,7 +173,7 @@ public void onAttackEntity(@NotNull AttackEntityEvent event) { event.setCanceled(true); } HunterPlayer.get(player).breakDisguise(); - if (!checkItemUsePerm(player.getMainHandItem(), player)) { + if (!FactionRestriction.canUse(player, player.getMainHandItem(), true)) { event.setCanceled(true); } } @@ -235,7 +233,7 @@ public void onItemPickupPre(@NotNull ItemEntityPickupEvent.Pre event) { @SubscribeEvent public void onItemRightClick(PlayerInteractEvent.@NotNull RightClickItem event) { - if (!checkItemUsePerm(event.getItemStack(), event.getEntity())) { + if (!FactionRestriction.canUse(event.getEntity(), event.getItemStack(), true)) { event.setCanceled(true); } @@ -251,7 +249,7 @@ public void onItemUse(LivingEntityUseItemEvent.@NotNull Start event) { if (VampirismPlayerAttributes.get(player).getVampSpecial().isCannotInteract()) { event.setCanceled(true); } - if (!checkItemUsePerm(event.getItem(), player)) { + if (!FactionRestriction.canUse(player, event.getItem(), true)) { event.setCanceled(true); } if (event.getItem().getItem() instanceof HunterCrossbowItem && HunterPlayer.get(player).getSkillHandler().isSkillEnabled(HunterSkills.CROSSBOW_TECHNIQUE)) { @@ -422,7 +420,7 @@ public void onPlayerName(PlayerEvent.@NotNull NameFormat event) { if (VampirismConfig.SERVER.factionColorInChat.get()) { FactionPlayerHandler handler = FactionPlayerHandler.get(event.getEntity()); Holder> f = handler.factionPlayer().getDisguise().getViewedFaction(Optional.ofNullable(VampirismMod.proxy.getClientPlayer()).map(FactionPlayerHandler::get).map(FactionPlayerHandler::getFaction).orElse(null)); - if (f != null) { + if (!IFaction.is(f, ModFactionTags.IS_NEUTRAL)) { MutableComponent displayName; displayName = Optional.of(handler).filter(h -> h.getLordLevel() > 0).filter(x -> VampirismConfig.SERVER.lordPrefixInChat.get()).map(FactionPlayerHandler::getLordTitle) .map(x -> Component.literal("[").append(x).append("] ").append(event.getDisplayname())) @@ -471,44 +469,6 @@ public void sleepTimeFinish(@NotNull SleepFinishedTimeEvent event) { } } - /** - * Checks if the player is allowed to use that item ({@link IFactionLevelItem}) and cancels the event if not. - * - * @return If it is allowed to use the item - */ - private boolean checkItemUsePerm(@NotNull ItemStack stack, @NotNull Player player) { - - boolean message = !player.getCommandSenderWorld().isClientSide; - if (!stack.isEmpty() && stack.getItem() instanceof IFactionExclusiveItem factionItem) { - if (!player.isAlive()) return false; - FactionPlayerHandler handler = FactionPlayerHandler.get(player); - TagKey> usingFaction = factionItem.getExclusiveFaction(stack); - if (!handler.isInFaction(usingFaction) && checkExceptions(player, handler.getFaction(), stack)) { - if (message) { - player.displayClientMessage(Component.translatable("text.vampirism.can_not_be_used_faction"), true); - } - return false; - } else if (stack.getItem() instanceof IFactionLevelItem levelItem) { - Holder> requiredSkill = levelItem.requiredSkill(stack); - - if (handler.getCurrentLevel() < levelItem.getMinLevel(stack)) { - if (message) { - player.displayClientMessage(Component.translatable("text.vampirism.can_not_be_used_level"), true); - } - return false; - } else if (requiredSkill != null) { - if (handler.getSkillHandler().map(s -> !s.isSkillEnabled(requiredSkill)).orElse(true)) { - if (message) { - player.displayClientMessage(Component.translatable("text.vampirism.can_not_be_used_skill"), true); - } - return false; - } - } - } - } - return true; - } - private boolean checkExceptions(@NotNull Player player, Holder> currentFaction, @NotNull ItemStack stack) { // stupid implementation. Otherwise we would need a better IFactionExclusiveItem#getExclusiveFaction method. return !stack.is(ModItems.GARLIC_BREAD) || currentFaction != null; } @@ -519,7 +479,7 @@ public void onPlayerAttackCritical(@NotNull CriticalHitEvent event) { ItemStack stack = event.getEntity().getMainHandItem(); if (!stack.isEmpty() && stack.getItem() instanceof IFactionSlayerItem item) { Holder> faction = VampirismAPI.factionRegistry().getFaction(event.getTarget()); - if (faction != null && IFaction.is(faction, item.getSlayedFaction())) { + if (IFaction.is(faction, item.getSlayedFaction())) { event.setDamageMultiplier(event.getDamageMultiplier() + (event.getVanillaMultiplier() * (item.getDamageMultiplierForFaction(stack) - 1))); } } diff --git a/src/main/java/de/teamlapen/vampirism/entity/player/skills/RefinementHandler.java b/src/main/java/de/teamlapen/vampirism/entity/player/skills/RefinementHandler.java index ff41f031a..e8d942abe 100644 --- a/src/main/java/de/teamlapen/vampirism/entity/player/skills/RefinementHandler.java +++ b/src/main/java/de/teamlapen/vampirism/entity/player/skills/RefinementHandler.java @@ -9,6 +9,7 @@ import de.teamlapen.vampirism.api.entity.player.refinement.IRefinementSet; import de.teamlapen.vampirism.api.entity.player.skills.IRefinementHandler; import de.teamlapen.vampirism.api.items.IRefinementItem; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.mixin.accessor.AttributeInstanceAccessor; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; diff --git a/src/main/java/de/teamlapen/vampirism/entity/player/skills/SkillHandler.java b/src/main/java/de/teamlapen/vampirism/entity/player/skills/SkillHandler.java index 95eb9a8d6..6fe85a1c5 100755 --- a/src/main/java/de/teamlapen/vampirism/entity/player/skills/SkillHandler.java +++ b/src/main/java/de/teamlapen/vampirism/entity/player/skills/SkillHandler.java @@ -30,6 +30,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.neoforged.neoforge.common.extensions.IHolderExtension; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/de/teamlapen/vampirism/items/BloodBottleItem.java b/src/main/java/de/teamlapen/vampirism/items/BloodBottleItem.java index 11b4b9b0e..47f9f86b6 100644 --- a/src/main/java/de/teamlapen/vampirism/items/BloodBottleItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/BloodBottleItem.java @@ -2,19 +2,15 @@ import de.teamlapen.lib.lib.util.ModDisplayItemGenerator; import de.teamlapen.vampirism.api.VReference; -import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.vampire.IVampire; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.core.ModDataComponents; import de.teamlapen.vampirism.core.ModItems; -import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.player.vampire.VampirePlayer; import de.teamlapen.vampirism.entity.vampire.DrinkBloodContext; import de.teamlapen.vampirism.fluids.BloodHelper; import de.teamlapen.vampirism.items.component.BottleBlood; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; -import net.minecraft.tags.TagKey; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; @@ -22,7 +18,6 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemUseAnimation; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; @@ -37,7 +32,7 @@ * Currently the only thing that can interact with the players bloodstats. * Can only store blood in {@link BloodBottleItem#CAPACITY} tenth units. */ -public class BloodBottleItem extends Item implements IFactionExclusiveItem, ModDisplayItemGenerator.CreativeTabItemProvider { +public class BloodBottleItem extends Item implements ModDisplayItemGenerator.CreativeTabItemProvider { public static final int AMOUNT = 9; private static final int MULTIPLIER = VReference.FOOD_TO_FLUID_BLOOD; @@ -80,11 +75,6 @@ public void generateCreativeTab(CreativeModeTab.@NotNull ItemDisplayParameters p } } - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_VAMPIRE; - } - @NotNull @Override public ItemStack finishUsingItem(@NotNull ItemStack stack, @NotNull Level worldIn, @NotNull LivingEntity entityLiving) { diff --git a/src/main/java/de/teamlapen/vampirism/items/CrossbowArrowItem.java b/src/main/java/de/teamlapen/vampirism/items/CrossbowArrowItem.java index 36fc88d3e..e69268833 100644 --- a/src/main/java/de/teamlapen/vampirism/items/CrossbowArrowItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/CrossbowArrowItem.java @@ -4,7 +4,9 @@ import de.teamlapen.vampirism.api.items.IEntityCrossbowArrow; import de.teamlapen.vampirism.api.items.IVampirismCrossbowArrow; import de.teamlapen.vampirism.config.VampirismConfig; +import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.CrossbowArrowEntity; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Position; @@ -28,7 +30,7 @@ public class CrossbowArrowItem extends ArrowItem implements IVampirismCrossbowAr public CrossbowArrowItem(ICrossbowArrowBehavior behavior, Properties properties) { - super(properties); + super(FactionRestriction.apply(ModFactionTags.IS_HUNTER, properties)); this.behavior = behavior; } diff --git a/src/main/java/de/teamlapen/vampirism/items/CrucifixItem.java b/src/main/java/de/teamlapen/vampirism/items/CrucifixItem.java index c3a7acb2f..c96c730d0 100644 --- a/src/main/java/de/teamlapen/vampirism/items/CrucifixItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/CrucifixItem.java @@ -1,11 +1,5 @@ package de.teamlapen.vampirism.items; -import de.teamlapen.vampirism.VampirismMod; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.entity.player.hunter.IHunterPlayer; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.items.IItemWithTier; import de.teamlapen.vampirism.api.util.VResourceLocation; import de.teamlapen.vampirism.core.ModEffects; @@ -17,15 +11,14 @@ import de.teamlapen.vampirism.entity.player.vampire.VampirePlayer; import de.teamlapen.vampirism.entity.vampire.AdvancedVampireEntity; import de.teamlapen.vampirism.entity.vampire.VampireBaronEntity; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.mixin.accessor.EntityAccessor; import de.teamlapen.vampirism.util.Helper; -import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.EntityTypeTags; -import net.minecraft.tags.TagKey; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.effect.MobEffectInstance; @@ -46,14 +39,13 @@ import java.util.*; -public class CrucifixItem extends Item implements IItemWithTier, IFactionExclusiveItem, IFactionLevelItem { +public class CrucifixItem extends Item implements IItemWithTier { - private final static String baseRegName = "crucifix"; private final TIER tier; private static final ResourceLocation COOLDOWN_GROUP = VResourceLocation.mod("crucifix"); public CrucifixItem(TIER tier, Item.Properties properties) { - super(properties.stacksTo(1).component(DataComponents.USE_COOLDOWN, new UseCooldown( switch (tier) { + super(FactionRestriction.builder(ModFactionTags.IS_HUNTER).skill(tier ==TIER.ULTIMATE ? HunterSkills.ULTIMATE_CRUCIFIX : HunterSkills.CRUCIFIX_WIELDER).apply(properties).stacksTo(1).component(DataComponents.USE_COOLDOWN, new UseCooldown( switch (tier) { case NORMAL -> 7; case ENHANCED -> 5; case ULTIMATE -> 3; @@ -61,23 +53,6 @@ public CrucifixItem(TIER tier, Item.Properties properties) { this.tier = tier; } - @Override - public int getMinLevel(@NotNull ItemStack stack) { - return 1; - } - - @Nullable - @Override - public Holder> requiredSkill(@NotNull ItemStack stack) { - if (tier == TIER.ULTIMATE) return HunterSkills.ULTIMATE_CRUCIFIX; - return HunterSkills.CRUCIFIX_WIELDER; - } - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_HUNTER; - } - @Override public TIER getVampirismTier() { return tier; @@ -99,7 +74,6 @@ public TIER getVampirismTier() { @Override public void appendHoverText(ItemStack stack, @Nullable TooltipContext context, List tooltip, TooltipFlag flagIn) { this.addTierInformation(tooltip); - this.addFactionToolTips(stack, context, tooltip, flagIn, VampirismMod.proxy.getClientPlayer()); } @Override diff --git a/src/main/java/de/teamlapen/vampirism/items/GarlicBreadItem.java b/src/main/java/de/teamlapen/vampirism/items/GarlicBreadItem.java index 38d7cda71..e060f49a1 100644 --- a/src/main/java/de/teamlapen/vampirism/items/GarlicBreadItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/GarlicBreadItem.java @@ -1,37 +1,33 @@ package de.teamlapen.vampirism.items; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.core.ModEffects; -import de.teamlapen.vampirism.core.ModItems; import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.consume.FactionBasedConsumeEffect; import net.minecraft.core.component.DataComponents; -import net.minecraft.tags.TagKey; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.Consumable; import net.minecraft.world.item.component.Consumables; -import net.minecraft.world.item.consume_effects.ClearAllStatusEffectsConsumeEffect; -import net.minecraft.world.item.consume_effects.ConsumeEffect; +import net.minecraft.world.item.consume_effects.ApplyStatusEffectsConsumeEffect; import net.minecraft.world.item.consume_effects.RemoveStatusEffectsConsumeEffect; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -public class GarlicBreadItem extends Item implements IFactionExclusiveItem { +import java.util.List; + +public class GarlicBreadItem extends Item { public static final Consumable GARLIC = Consumables.defaultFood() - .onConsume(new RemoveStatusEffectsConsumeEffect(ModEffects.SANGUINARE)).build(); + .onConsume(new RemoveStatusEffectsConsumeEffect(ModEffects.SANGUINARE)) + .onConsume(FactionBasedConsumeEffect.build(ModFactionTags.IS_VAMPIRE, new ApplyStatusEffectsConsumeEffect( + List.of( + new MobEffectInstance(ModEffects.GARLIC, 20*30), + new MobEffectInstance(MobEffects.WEAKNESS, 20*30) + ))) + ) + .build(); public GarlicBreadItem(Item.Properties properties) { - super(properties.food((new FoodProperties.Builder()).nutrition(6).saturationModifier(0.7F).build()).component(DataComponents.CONSUMABLE, GARLIC)); - } - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.USE_GARLIC_BREAD; + super(properties.food(new FoodProperties.Builder().nutrition(6).saturationModifier(0.7F).build()).component(DataComponents.CONSUMABLE, GARLIC)); } - } diff --git a/src/main/java/de/teamlapen/vampirism/items/HolyWaterBottleItem.java b/src/main/java/de/teamlapen/vampirism/items/HolyWaterBottleItem.java index c44507a20..3323f6f70 100644 --- a/src/main/java/de/teamlapen/vampirism/items/HolyWaterBottleItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/HolyWaterBottleItem.java @@ -2,12 +2,10 @@ import de.teamlapen.vampirism.api.EnumStrength; import de.teamlapen.vampirism.api.ItemPropertiesExtension; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.api.items.IItemWithTier; import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; @@ -20,11 +18,11 @@ * HolyWaterBottle * Exists in different tiers and as splash versions. */ -public class HolyWaterBottleItem extends Item implements IItemWithTier, IFactionExclusiveItem { +public class HolyWaterBottleItem extends Item implements IItemWithTier { private final TIER tier; public HolyWaterBottleItem(TIER tier, @NotNull Properties props) { - super(ItemPropertiesExtension.descriptionWithout(props, "_normal|_enhanced|_ultimate")); + super(FactionRestriction.apply(ModFactionTags.IS_HUNTER, ItemPropertiesExtension.descriptionWithout(props, "_normal|_enhanced|_ultimate"))); this.tier = tier; } @@ -34,11 +32,6 @@ public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext c addTierInformation(tooltip); } - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_HUNTER; - } - /** * Converts the tier of this bottle into the strength of the applied holy water */ diff --git a/src/main/java/de/teamlapen/vampirism/items/HunterArmorItem.java b/src/main/java/de/teamlapen/vampirism/items/HunterArmorItem.java index d3a2d2c73..b0ea2fe9f 100644 --- a/src/main/java/de/teamlapen/vampirism/items/HunterArmorItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/HunterArmorItem.java @@ -1,19 +1,14 @@ package de.teamlapen.vampirism.items; import de.teamlapen.vampirism.REFERENCE; -import de.teamlapen.vampirism.VampirismMod; import de.teamlapen.vampirism.api.ItemPropertiesExtension; -import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.factions.IPlayableFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.core.ModEffects; import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.player.VampirismPlayerAttributes; -import de.teamlapen.vampirism.util.Helper; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.core.Holder; -import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; @@ -26,26 +21,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * Base class for all hunter only armor tileInventory */ -public abstract class HunterArmorItem extends ArmorItem implements IFactionExclusiveItem { +public abstract class HunterArmorItem extends ArmorItem { public HunterArmorItem(@NotNull ArmorMaterial materialIn, @NotNull ArmorType type, Item.@NotNull Properties props) { - super(materialIn, type, ItemPropertiesExtension.descriptionWithout(props, "_normal|_enhanced|_ultimate")); - } - - @Override - public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext context, @NotNull List tooltip, @NotNull TooltipFlag flagIn) { - this.addFactionToolTips(stack, context, tooltip, flagIn, VampirismMod.proxy.getClientPlayer()); - } - - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_HUNTER; + super(materialIn, type, FactionRestriction.builder(ModFactionTags.IS_HUNTER).apply(ItemPropertiesExtension.descriptionWithout(props, "_normal|_enhanced|_ultimate"))); } @Override @@ -60,7 +42,7 @@ public void inventoryTick(ItemStack pStack, Level pLevel, Entity pEntity, int pS @Override public boolean canEquip(ItemStack stack, EquipmentSlot armorType, LivingEntity entity) { - return super.canEquip(stack, armorType, entity) && Helper.isHunter(entity); + return super.canEquip(stack, armorType, entity) && FactionRestriction.canUse(entity, stack, true); } protected String getTextureLocation(String name, EquipmentSlot slot, @Nullable String type) { diff --git a/src/main/java/de/teamlapen/vampirism/items/HunterAxeItem.java b/src/main/java/de/teamlapen/vampirism/items/HunterAxeItem.java index 194c604e0..aaa5d7c34 100644 --- a/src/main/java/de/teamlapen/vampirism/items/HunterAxeItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/HunterAxeItem.java @@ -4,6 +4,8 @@ import de.teamlapen.vampirism.api.VReference; import de.teamlapen.vampirism.api.items.IItemWithTier; import de.teamlapen.vampirism.core.ModFactions; +import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.ChatFormatting; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.Registries; @@ -29,7 +31,7 @@ public class HunterAxeItem extends HunterSwordItem implements IItemWithTier, Mod private final TIER tier; public HunterAxeItem(ToolMaterial material, TIER tier, Item.Properties properties) { - super(material, 3, -2.9f, properties); + super(material, 3, -2.9f, FactionRestriction.builder(ModFactionTags.IS_HUNTER).minLevel(getMinLevel(tier)).apply(properties)); this.tier = tier; } @@ -60,11 +62,6 @@ public float getDamageMultiplierForFaction(@NotNull ItemStack stack) { return stack; } - @Override - public int getMinLevel(@NotNull ItemStack stack) { - return getMinLevel(); - } - @Override public TIER getVampirismTier() { return tier; @@ -83,7 +80,7 @@ private int getKnockback() { }; } - private int getMinLevel() { + private static int getMinLevel(TIER tier) { return switch (tier) { case ULTIMATE -> 8; case ENHANCED -> 6; diff --git a/src/main/java/de/teamlapen/vampirism/items/HunterSwordItem.java b/src/main/java/de/teamlapen/vampirism/items/HunterSwordItem.java index 1de1d57a7..28021efb5 100755 --- a/src/main/java/de/teamlapen/vampirism/items/HunterSwordItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/HunterSwordItem.java @@ -1,18 +1,12 @@ package de.teamlapen.vampirism.items; -import de.teamlapen.vampirism.VampirismMod; import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.entity.player.hunter.IHunterPlayer; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.items.IFactionSlayerItem; import de.teamlapen.vampirism.api.items.IVampireFinisher; import de.teamlapen.vampirism.core.ModFactions; -import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.core.Holder; import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ToolMaterial; import net.minecraft.world.item.TooltipFlag; @@ -24,28 +18,12 @@ /** * Basic sword for vampire hunters */ -public abstract class HunterSwordItem extends VampirismSwordItem implements IFactionLevelItem, IFactionSlayerItem, IVampireFinisher, IFactionExclusiveItem { +public abstract class HunterSwordItem extends VampirismSwordItem implements IFactionSlayerItem, IVampireFinisher { public HunterSwordItem(@NotNull ToolMaterial material, int attackDamage, float attackSpeed, @NotNull Properties props) { super(material, attackDamage, attackSpeed, props); } - @Override - public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext context, @NotNull List tooltip, @NotNull TooltipFlag flagIn) { - addFactionToolTips(stack, context, tooltip, flagIn, VampirismMod.proxy.getClientPlayer()); - } - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_HUNTER; - } - - @Nullable - @Override - public Holder> requiredSkill(@NotNull ItemStack stack) { - return null; - } - @Override public Holder> getSlayedFaction() { return ModFactions.VAMPIRE; diff --git a/src/main/java/de/teamlapen/vampirism/items/VampireClothingItem.java b/src/main/java/de/teamlapen/vampirism/items/VampireClothingItem.java index 5c48ff6ae..e7a121dfa 100644 --- a/src/main/java/de/teamlapen/vampirism/items/VampireClothingItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/VampireClothingItem.java @@ -1,19 +1,14 @@ package de.teamlapen.vampirism.items; import de.teamlapen.lib.lib.util.UtilLib; -import de.teamlapen.vampirism.VampirismMod; import de.teamlapen.vampirism.api.VampirismAPI; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.core.ModEffects; import de.teamlapen.vampirism.core.ModItems; import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.util.Helper; -import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.network.chat.Component; -import net.minecraft.tags.TagKey; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; @@ -22,34 +17,20 @@ import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.equipment.ArmorMaterial; import net.minecraft.world.item.equipment.ArmorType; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.List; - -public class VampireClothingItem extends ArmorItem implements IFactionExclusiveItem { +public class VampireClothingItem extends ArmorItem { public VampireClothingItem(@NotNull ArmorType type, ArmorMaterial material, Item.Properties properties) { - super(material, type, properties); - } - - @Override - public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext context, @NotNull List tooltip, @NotNull TooltipFlag flagIn) { - this.addFactionToolTips(stack, context, tooltip, flagIn, VampirismMod.proxy.getClientPlayer()); + super(material, type, FactionRestriction.builder(ModFactionTags.IS_VAMPIRE).apply(properties)); } @Override public boolean canEquip(ItemStack stack, EquipmentSlot armorType, LivingEntity entity) { - return super.canEquip(stack, armorType, entity) && Helper.isVampire(entity); - } - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_VAMPIRE; + return super.canEquip(stack, armorType, entity) && FactionRestriction.canUse(entity, stack, true); } @Override diff --git a/src/main/java/de/teamlapen/vampirism/items/VampireSwordItem.java b/src/main/java/de/teamlapen/vampirism/items/VampireSwordItem.java index c32443cd8..b4a7f7d16 100644 --- a/src/main/java/de/teamlapen/vampirism/items/VampireSwordItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/VampireSwordItem.java @@ -3,37 +3,29 @@ import de.teamlapen.lib.lib.util.UtilLib; import de.teamlapen.vampirism.VampirismMod; import de.teamlapen.vampirism.api.VReference; -import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.player.skills.IRefinementHandler; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.entity.player.skills.ISkillHandler; import de.teamlapen.vampirism.api.entity.player.vampire.IVampirePlayer; import de.teamlapen.vampirism.api.items.IBloodChargeable; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.util.VResourceLocation; import de.teamlapen.vampirism.config.VampirismConfig; -import de.teamlapen.vampirism.core.ModDataComponents; -import de.teamlapen.vampirism.core.ModParticles; -import de.teamlapen.vampirism.core.ModRefinements; +import de.teamlapen.vampirism.core.*; import de.teamlapen.vampirism.core.tags.ModEntityTags; -import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.player.vampire.VampirePlayer; import de.teamlapen.vampirism.entity.player.vampire.skills.VampireSkills; import de.teamlapen.vampirism.items.component.BloodCharged; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.items.component.SwordTraining; import de.teamlapen.vampirism.particle.FlyingBloodParticleOptions; import de.teamlapen.vampirism.particle.GenericParticleOptions; import de.teamlapen.vampirism.util.DamageHandler; import de.teamlapen.vampirism.util.Helper; import net.minecraft.ChatFormatting; -import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.TagKey; import net.minecraft.util.Unit; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -50,7 +42,7 @@ import java.util.List; -public abstract class VampireSwordItem extends VampirismSwordItem implements IBloodChargeable, IFactionExclusiveItem, IFactionLevelItem { +public abstract class VampireSwordItem extends VampirismSwordItem implements IBloodChargeable { /** * Speed modifier on max training @@ -58,7 +50,7 @@ public abstract class VampireSwordItem extends VampirismSwordItem implements IBl private final float trainedAttackSpeedIncrease; public VampireSwordItem(@NotNull ToolMaterial material, int attackDamage, float trainSpeedIncrease, @NotNull Properties prop) { - super(material, attackDamage, material.speed(), prop); + super(material, attackDamage, material.speed(), FactionRestriction.apply(ModFactions.VAMPIRE, prop)); this.trainedAttackSpeedIncrease = trainSpeedIncrease; } @@ -70,7 +62,6 @@ public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext c tooltip.add(Component.translatable("text.vampirism.sword_trained").append(Component.literal(" " + ((int) Math.ceil(trained * 100f)) + "%")).withStyle(ChatFormatting.DARK_AQUA)); super.appendHoverText(stack, context, tooltip, flagIn); - this.addFactionToolTips(stack, context, tooltip, flagIn, VampirismMod.proxy.getClientPlayer()); } @Override @@ -94,22 +85,6 @@ public void doNotName(@NotNull ItemStack stack) { stack.set(ModDataComponents.DO_NOT_NAME, Unit.INSTANCE); } - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_VAMPIRE; - } - - @Override - public int getMinLevel(@NotNull ItemStack stack) { - return 0; - } - - @Nullable - @Override - public Holder> requiredSkill(@NotNull ItemStack stack) { - return null; - } - @Override public int getUseDuration(@NotNull ItemStack pStack, @NotNull LivingEntity p_344979_) { return 40; diff --git a/src/main/java/de/teamlapen/vampirism/items/component/AppliedOilContent.java b/src/main/java/de/teamlapen/vampirism/items/component/AppliedOilContent.java index 97bf04871..70fa73726 100644 --- a/src/main/java/de/teamlapen/vampirism/items/component/AppliedOilContent.java +++ b/src/main/java/de/teamlapen/vampirism/items/component/AppliedOilContent.java @@ -3,18 +3,29 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.teamlapen.vampirism.VampirismMod; import de.teamlapen.vampirism.api.VampirismRegistries; import de.teamlapen.vampirism.api.components.IAppliedOilContent; import de.teamlapen.vampirism.api.items.oil.IApplicableOil; import de.teamlapen.vampirism.api.items.oil.IOil; import de.teamlapen.vampirism.core.ModDataComponents; +import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.core.ModRegistries; +import net.minecraft.ChatFormatting; import net.minecraft.core.Holder; import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Optional; public record AppliedOilContent(Holder oil, int duration) implements IAppliedOilContent { @@ -28,6 +39,7 @@ public record AppliedOilContent(Holder oil, int duration) implem public static final StreamCodec STREAM_CODEC = StreamCodec.composite( ByteBufCodecs.holderRegistry(VampirismRegistries.Keys.OIL).map(s -> (Holder) (Object) s, l -> (Holder) (Object) l), AppliedOilContent::oil, ByteBufCodecs.VAR_INT, AppliedOilContent::duration, AppliedOilContent::new ); + public static final FactionRestriction HUNTER_RESTRICTION = FactionRestriction.builder(ModFactions.HUNTER).build(); public static ItemStack apply(ItemStack stack, Holder oil) { return apply(stack, oil, oil.value().getMaxDuration(stack)); @@ -49,4 +61,32 @@ public static ItemStack remove(ItemStack stack) { public static Optional getAppliedOil(ItemStack stack) { return Optional.ofNullable(stack.get(ModDataComponents.APPLIED_OIL)); } + + public static void addTooltipIfExist(ItemStack stack, List tooltip, @NotNull TooltipFlag flag) { + addTooltipIfExist(VampirismMod.proxy.getClientPlayer(), stack, tooltip, flag); + } + + + public static void addTooltipIfExist(@Nullable Player player, ItemStack stack, List tooltip, @NotNull TooltipFlag flag) { + AppliedOilContent appliedOilContent = stack.get(ModDataComponents.APPLIED_OIL); + if (appliedOilContent != null) { + appliedOilContent.addTooltip(stack, tooltip, flag); + } + } + + public void addTooltip(ItemStack stack, List tooltip, @NotNull TooltipFlag flag) { + ResourceLocation id = oil().getKey().location(); + MutableComponent component = Component.translatable(String.format("oil.%s.%s", id.getNamespace(), id.getPath())).withStyle(ChatFormatting.LIGHT_PURPLE); + if (oil().value().hasDuration()) { + int maxDuration = oil().value().getMaxDuration(stack); + float perc = duration / (float) maxDuration; + ChatFormatting status = perc > 0.5 ? ChatFormatting.GREEN : perc > 0.25 ? ChatFormatting.GOLD : ChatFormatting.RED; + if (flag.isAdvanced()) { + component.append(" ").append(Component.literal("%s/%s".formatted(duration, maxDuration)).withStyle(status)); + } else { + component.append(" ").append(Component.translatable("text.vampirism.oil.wetting_status").withStyle(status)); + } + } + tooltip.add(component); + } } diff --git a/src/main/java/de/teamlapen/vampirism/items/component/FactionRestriction.java b/src/main/java/de/teamlapen/vampirism/items/component/FactionRestriction.java new file mode 100644 index 000000000..308b5c6fc --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/items/component/FactionRestriction.java @@ -0,0 +1,225 @@ +package de.teamlapen.vampirism.items.component; + +import com.google.common.base.Preconditions; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.teamlapen.vampirism.VampirismMod; +import de.teamlapen.vampirism.api.VampirismAPI; +import de.teamlapen.vampirism.api.VampirismRegistries; +import de.teamlapen.vampirism.api.entity.factions.IFaction; +import de.teamlapen.vampirism.api.entity.player.skills.ISkill; +import de.teamlapen.vampirism.core.ModDataComponents; +import de.teamlapen.vampirism.core.ModRegistries; +import de.teamlapen.vampirism.entity.factions.FactionPlayerHandler; +import net.minecraft.ChatFormatting; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.*; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.*; +import java.util.stream.Stream; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public record FactionRestriction(HolderSet> factions, Optional>> skills, Optional minLevel) { + + public static final Codec CODEC = RecordCodecBuilder.create(inst -> { + return inst.group( + RegistryCodecs.homogeneousList(VampirismRegistries.Keys.FACTION).fieldOf("factions").forGetter(FactionRestriction::factions), + RegistryCodecs.homogeneousList(VampirismRegistries.Keys.SKILL).optionalFieldOf("skills").forGetter(FactionRestriction::skills), + Codec.INT.optionalFieldOf("min_level").forGetter(FactionRestriction::minLevel) + ).apply(inst, FactionRestriction::new); + }); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.holderSet(VampirismRegistries.Keys.FACTION), FactionRestriction::factions, + ByteBufCodecs.optional(ByteBufCodecs.holderSet(VampirismRegistries.Keys.SKILL)), FactionRestriction::skills, + ByteBufCodecs.optional(ByteBufCodecs.INT), FactionRestriction::minLevel, + FactionRestriction::new + ); + + public FactionRestriction(HolderSet> factions) { + this(factions, Optional.empty(), Optional.empty()); + } + + public FactionRestriction(Holder> faction) { + this(HolderSet.direct(faction)); + } + + public static , Z extends Holder> boolean matchFaction(ItemStack stack, Z faction) { + FactionRestriction factionRestriction = stack.get(ModDataComponents.FACTION_RESTRICTION); + if (factionRestriction != null) { + return IFaction.contains(factionRestriction.factions(), faction); + } + return true; + } + + public static Builder builder(TagKey> tagKey) { + return new Builder(tagKey); + } + + @SuppressWarnings("unchecked") + public static , Z extends Holder> Builder builder(Z faction) { + return new Builder((Holder>) faction); + } + + @SuppressWarnings("unchecked") + public static , Z extends Holder> Item.Properties apply(Z faction, Item.Properties properties) { + return new Builder((Holder>) faction).apply(properties); + } + + public static Item.Properties apply(TagKey> faction, Item.Properties properties) { + return new Builder(faction).apply(properties); + } + + public static boolean canUse(Player player, ItemStack stack, boolean message) { + var result = canUse(player, stack, message, stack.get(ModDataComponents.FACTION_RESTRICTION)); + if (result && stack.has(ModDataComponents.APPLIED_OIL)) { + result = canUse(player, stack, message, AppliedOilContent.HUNTER_RESTRICTION); + } + return result; + } + + private static boolean canUse(Player player, ItemStack stack, boolean message, @Nullable FactionRestriction restriction) { + if (restriction != null) { + FactionPlayerHandler factionPlayerHandler = FactionPlayerHandler.get(player); + Result result = restriction.canUse(factionPlayerHandler); + if (message) { + result.message().ifPresent(s -> player.displayClientMessage(s, true)); + } + return result.success(); + } + return true; + } + + public static boolean canUse(LivingEntity entity, ItemStack stack, boolean message) { + if (entity instanceof Player player) { + return canUse(player, stack, message); + } else { + Holder> faction = VampirismAPI.factionRegistry().getFaction(entity); + FactionRestriction restriction = stack.get(ModDataComponents.FACTION_RESTRICTION); + if (restriction != null && IFaction.contains(restriction.factions(), faction)) { + return true; + } + return stack.has(ModDataComponents.APPLIED_OIL) && IFaction.contains(AppliedOilContent.HUNTER_RESTRICTION.factions(), faction); + } + } + + public static void addTooltipIfExist(ItemStack stack, List tooltip) { + addTooltipIfExist(VampirismMod.proxy.getClientPlayer(), stack, tooltip); + } + + + public static void addTooltipIfExist(@Nullable Player player, ItemStack stack, List tooltip) { + Stream factionRestrictionStream = Stream.of(stack.get(ModDataComponents.FACTION_RESTRICTION)); + if (stack.has(ModDataComponents.APPLIED_OIL)) { + factionRestrictionStream = Stream.concat(factionRestrictionStream, Stream.of(AppliedOilContent.HUNTER_RESTRICTION)); + } + List list = factionRestrictionStream.filter(Objects::nonNull).toList(); + if (!list.isEmpty()) { + addTooltip(tooltip, player == null ? null : FactionPlayerHandler.get(player), list); + } + } + + public Result canUse(FactionPlayerHandler player) { + if (!IFaction.contains(factions, player.getFaction())) { + return Result.WRONG_FACTION; + } + if (skills().isPresent() && player.getSkillHandler().map(s -> !s.areSkillsEnabled(skills().get().stream().toList())).orElse(true)) { + return Result.MISSING_SKILLS; + } + if (minLevel().isPresent() && player.getCurrentLevel() < minLevel().get()) { + return Result.MISSING_LEVEL; + } + return Result.SUCCESS; + } + + public static void addTooltip(List tooltips, @Nullable FactionPlayerHandler player, List restrictions) { + tooltips.add(Component.empty()); + tooltips.add(Component.translatable("text.vampirism.faction_specifics").withStyle(ChatFormatting.GRAY)); + tooltips.addAll(restrictions.stream().map(FactionRestriction::factions).flatMap(HolderSet::stream).distinct().map(faction -> { + var color = player == null ? ChatFormatting.GRAY : restrictions.stream().allMatch(factions -> IFaction.contains(factions.factions(), player.getFaction())) ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED; + return faction.value().getName().copy().withStyle(color); + }).map(x -> Component.literal(" ").append(x)).toList()); + restrictions.stream().map(FactionRestriction::minLevel).flatMap(Optional::stream).mapToInt(s -> s).max().ifPresent(minLevel -> { + var color = player == null ? ChatFormatting.GRAY : player.getCurrentLevel() >= minLevel ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED; + tooltips.add(Component.literal(" ").append(Component.translatable("text.vampirism.required_level", String.valueOf(minLevel)).withStyle(color))); + }); + restrictions.stream().map(FactionRestriction::skills).flatMap(Optional::stream).flatMap(HolderSet::stream).map(skill -> + { + var color = player == null ? ChatFormatting.GRAY : player.getSkillHandler().map(s -> s.isSkillEnabled(skill)).orElse(false) ? ChatFormatting.DARK_GREEN : ChatFormatting.DARK_RED; + return Component.translatable("text.vampirism.required_skill", skill.value().getName()).withStyle(color); + }).map(s -> Component.literal(" ").append(s)).forEach(tooltips::add); + } + + public record Result(Optional message, boolean success) { + public static final Result SUCCESS = new Result(Optional.empty(), true); + public static final Result WRONG_FACTION = new Result(Optional.of(Component.translatable("text.vampirism.can_not_be_used_faction")), false); + public static final Result MISSING_SKILLS = new Result(Optional.of(Component.translatable("text.vampirism.can_not_be_used_skill")), false); + public static final Result MISSING_LEVEL = new Result(Optional.of(Component.translatable("text.vampirism.can_not_be_used_level")), false); + } + + public static class Builder { + + private TagKey> factionTag; + private final List>> factionHolder = new ArrayList<>(); + private TagKey> skillTag; + private final List>> skillHolder = new ArrayList<>(); + private Integer minLevel; + + public Builder(TagKey> tagKey) { + this.factionTag = tagKey; + } + + @SuppressWarnings("unchecked") + public Builder(Holder>... faction) { + this.factionHolder.addAll(Arrays.asList(faction)); + } + + public Builder skill(TagKey> skillTag) { + this.skillTag = skillTag; + return this; + } + + public Builder skill(Holder> skill) { + this.skillHolder.add(skill); + return this; + } + + @SuppressWarnings("unchecked") + public Builder skill(Holder>... skill) { + this.skillHolder.addAll(Arrays.asList(skill)); + return this; + } + + public Builder minLevel(int minLevel) { + this.minLevel = minLevel; + return this; + } + + public FactionRestriction build() { + HolderGetter> factions = BuiltInRegistries.acquireBootstrapRegistrationLookup(ModRegistries.FACTIONS); + HolderGetter> skills = BuiltInRegistries.acquireBootstrapRegistrationLookup(ModRegistries.SKILLS); + Preconditions.checkArgument((this.factionTag != null && this.factionHolder.isEmpty() )|| (this.factionTag == null && !this.factionHolder.isEmpty()), "You need to provide either a faction tag or a list of factions"); + Preconditions.checkArgument(!(this.skillTag != null && !this.skillHolder.isEmpty()), "You can only supply a skill tag or a list of skills or not skills at all"); + return new FactionRestriction(factionTag != null ? factions.getOrThrow(factionTag) : HolderSet.direct(factionHolder), skillTag != null ? Optional.of(skillTag).map(skills::getOrThrow) : !skillHolder.isEmpty() ? Optional.of(HolderSet.direct(skillHolder)) : Optional.empty(), Optional.ofNullable(minLevel)); + } + + public Item.Properties apply(Item.Properties properties) { + return properties.component(ModDataComponents.FACTION_RESTRICTION, build()); + } + + + } + +} diff --git a/src/main/java/de/teamlapen/vampirism/items/consume/FactionBasedConsumeEffect.java b/src/main/java/de/teamlapen/vampirism/items/consume/FactionBasedConsumeEffect.java index 778f3f511..a4d3b425e 100644 --- a/src/main/java/de/teamlapen/vampirism/items/consume/FactionBasedConsumeEffect.java +++ b/src/main/java/de/teamlapen/vampirism/items/consume/FactionBasedConsumeEffect.java @@ -1,5 +1,6 @@ package de.teamlapen.vampirism.items.consume; +import com.google.common.base.Preconditions; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import de.teamlapen.vampirism.api.VampirismAPI; @@ -7,33 +8,44 @@ import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.core.ModItems; +import de.teamlapen.vampirism.core.ModRegistries; import net.minecraft.core.Holder; +import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderSet; import net.minecraft.core.RegistryCodecs; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.tags.TagKey; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.consume_effects.ConsumeEffect; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -public record FactionBasedConsumeEffect(HolderSet> faction, ConsumeEffect effects) implements ConsumeEffect { +import java.util.ArrayList; +import java.util.List; + +public record FactionBasedConsumeEffect(HolderSet> faction, List effects) implements ConsumeEffect { public static final MapCodec CODEC = MapCodec.assumeMapUnsafe(RecordCodecBuilder.create(inst -> { return inst.group( RegistryCodecs.homogeneousList(VampirismRegistries.Keys.FACTION).fieldOf("faction").forGetter(FactionBasedConsumeEffect::faction), - ConsumeEffect.CODEC.fieldOf("effect").forGetter(FactionBasedConsumeEffect::effects) + ConsumeEffect.CODEC.listOf().fieldOf("effect").forGetter(FactionBasedConsumeEffect::effects) ).apply(inst, FactionBasedConsumeEffect::new); })); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( ByteBufCodecs.fromCodec(RegistryCodecs.homogeneousList(VampirismRegistries.Keys.FACTION)), FactionBasedConsumeEffect::faction, - ConsumeEffect.STREAM_CODEC, FactionBasedConsumeEffect::effects, + ConsumeEffect.STREAM_CODEC.apply(ByteBufCodecs.list()), FactionBasedConsumeEffect::effects, FactionBasedConsumeEffect::new ); + public FactionBasedConsumeEffect(HolderSet> faction, ConsumeEffect effects) { + this(faction, List.of(effects)); + } + @Override public @NotNull Type getType() { return ModItems.FACTION_BASED.get(); @@ -42,12 +54,38 @@ public record FactionBasedConsumeEffect(HolderSet> faction, ConsumeE @Override public boolean apply(@NotNull Level level, @NotNull ItemStack stack, @NotNull LivingEntity entity) { Holder> faction1 = VampirismAPI.factionRegistry().getFaction(entity); - if (faction1 == null) { - faction1 = ModFactions.NEUTRAL; - } if (IFaction.contains(faction, faction1)) { - return effects.apply(level, stack, entity); + return effects.stream().allMatch(s -> s.apply(level, stack, entity)); } return false; } + + public static Builder builder(TagKey> faction) { + return new Builder(faction); + } + + public static FactionBasedConsumeEffect build(TagKey> faction, ConsumeEffect effect) { + return builder(faction).add(effect).build(); + } + + public static class Builder { + + private final TagKey> faction; + private final List effects = new ArrayList<>(); + + public Builder(TagKey> faction) { + this.faction = faction; + } + + public Builder add(ConsumeEffect effect) { + effects.add(effect); + return this; + } + + public FactionBasedConsumeEffect build() { + HolderGetter> factions = BuiltInRegistries.acquireBootstrapRegistrationLookup(ModRegistries.FACTIONS); + Preconditions.checkArgument(!this.effects.isEmpty()); + return new FactionBasedConsumeEffect(factions.getOrThrow(this.faction), effects.stream().toList()); + } + } } diff --git a/src/main/java/de/teamlapen/vampirism/items/crossbow/DoubleCrossbowItem.java b/src/main/java/de/teamlapen/vampirism/items/crossbow/DoubleCrossbowItem.java index dee203868..60d12e3e3 100644 --- a/src/main/java/de/teamlapen/vampirism/items/crossbow/DoubleCrossbowItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/crossbow/DoubleCrossbowItem.java @@ -3,7 +3,10 @@ import de.teamlapen.vampirism.api.entity.player.hunter.IHunterPlayer; import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.items.IVampirismCrossbowArrow; +import de.teamlapen.vampirism.core.ModDataComponents; +import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.player.hunter.skills.HunterSkills; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.core.Holder; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; @@ -19,7 +22,7 @@ public class DoubleCrossbowItem extends HunterCrossbowItem { public DoubleCrossbowItem(Item.Properties properties, float arrowVelocity, int chargeTime, ToolMaterial itemTier, Holder> requiredSkill) { - super(properties, arrowVelocity, chargeTime, itemTier, requiredSkill); + super(properties.component(ModDataComponents.FACTION_RESTRICTION, FactionRestriction.builder(ModFactionTags.IS_HUNTER).skill(requiredSkill).build()), arrowVelocity, chargeTime, itemTier); } @Override diff --git a/src/main/java/de/teamlapen/vampirism/items/crossbow/HunterCrossbowItem.java b/src/main/java/de/teamlapen/vampirism/items/crossbow/HunterCrossbowItem.java index 57ef48775..c1d7464ba 100644 --- a/src/main/java/de/teamlapen/vampirism/items/crossbow/HunterCrossbowItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/crossbow/HunterCrossbowItem.java @@ -1,24 +1,17 @@ package de.teamlapen.vampirism.items.crossbow; -import de.teamlapen.vampirism.VampirismMod; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.entity.player.hunter.IHunterPlayer; -import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.items.IArrowContainer; import de.teamlapen.vampirism.api.items.IEntityCrossbowArrow; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.items.IHunterCrossbow; import de.teamlapen.vampirism.core.ModDataComponents; -import de.teamlapen.vampirism.core.ModTasks; -import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.core.tags.ModItemTags; import de.teamlapen.vampirism.entity.player.hunter.HunterPlayer; import de.teamlapen.vampirism.entity.player.hunter.skills.HunterSkills; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.items.component.SelectedAmmunition; import de.teamlapen.vampirism.util.ModEnchantmentHelper; import net.minecraft.ChatFormatting; import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; @@ -28,10 +21,8 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.stats.Stats; -import net.minecraft.tags.TagKey; import net.minecraft.util.Unit; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; @@ -41,7 +32,6 @@ import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; -import net.neoforged.neoforge.common.Tags; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,31 +40,23 @@ import java.util.Optional; import java.util.function.Predicate; -public abstract class HunterCrossbowItem extends CrossbowItem implements IFactionLevelItem, IHunterCrossbow { +public abstract class HunterCrossbowItem extends CrossbowItem implements IHunterCrossbow { protected final ToolMaterial itemTier; - private final Holder> requiredSkill; protected final float arrowVelocity; protected final int chargeTime; - public HunterCrossbowItem(Properties properties, float arrowVelocity, int chargeTime, ToolMaterial itemTier, @NotNull Holder<@Nullable ISkill> requiredSkill) { + public HunterCrossbowItem(Properties properties, float arrowVelocity, int chargeTime, ToolMaterial itemTier) { super(properties.repairable(ModItemTags.CROSSBOW_REPAIRABLE).enchantable(itemTier.enchantmentValue())); this.arrowVelocity = arrowVelocity; this.chargeTime = chargeTime; this.itemTier = itemTier; - this.requiredSkill = requiredSkill; - } - - @Override - public @Nullable Holder> requiredSkill(@NotNull ItemStack stack) { - return this.requiredSkill; } @Override public void appendHoverText(@NotNull ItemStack stack, @Nullable TooltipContext context, @NotNull List tooltips, @NotNull TooltipFlag flag) { super.appendHoverText(stack, context, tooltips, flag); this.addAmmunitionTypeHoverText(stack, context, tooltips, flag); - this.addFactionToolTips(stack, context, tooltips, flag, VampirismMod.proxy.getClientPlayer()); } protected void addAmmunitionTypeHoverText(@NotNull ItemStack stack, @Nullable TooltipContext context, @NotNull List tooltips, @NotNull TooltipFlag flag) { @@ -93,16 +75,6 @@ protected void addAmmunitionTypeHoverText(@NotNull ItemStack stack, @Nullable To return getSupportedProjectiles(stack); } - @Override - public int getMinLevel(@NotNull ItemStack stack) { - return 0; - } - - @Override - public @NotNull TagKey> getExclusiveFaction(@NotNull ItemStack stack) { - return ModFactionTags.IS_HUNTER; - } - @NotNull @Override public Predicate getSupportedHeldProjectiles() { diff --git a/src/main/java/de/teamlapen/vampirism/items/crossbow/SingleCrossbowItem.java b/src/main/java/de/teamlapen/vampirism/items/crossbow/SingleCrossbowItem.java index c5b7175f6..b08846ad8 100644 --- a/src/main/java/de/teamlapen/vampirism/items/crossbow/SingleCrossbowItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/crossbow/SingleCrossbowItem.java @@ -3,6 +3,10 @@ import de.teamlapen.vampirism.api.entity.player.hunter.IHunterPlayer; import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.items.IVampirismCrossbowArrow; +import de.teamlapen.vampirism.core.ModDataComponents; +import de.teamlapen.vampirism.core.ModTasks; +import de.teamlapen.vampirism.core.tags.ModFactionTags; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.core.Holder; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -17,7 +21,7 @@ public class SingleCrossbowItem extends HunterCrossbowItem { public SingleCrossbowItem(Item.Properties properties, float arrowVelocity, int chargeTime, ToolMaterial itemTier, Holder> requiredSkill) { - super(properties, arrowVelocity, chargeTime, itemTier, requiredSkill); + super(properties.component(ModDataComponents.FACTION_RESTRICTION, FactionRestriction.builder(ModFactionTags.IS_HUNTER).skill(requiredSkill).build()), arrowVelocity, chargeTime, itemTier); } @Override @@ -25,12 +29,6 @@ public SingleCrossbowItem(Item.Properties properties, float arrowVelocity, int c return (stack -> stack.getItem() instanceof IVampirismCrossbowArrow); } - @Nullable - @Override - public Holder> requiredSkill(@Nonnull ItemStack stack) { - return null; - } - @Override public float getInaccuracy(ItemStack stack, boolean doubleCrossbow) { return doubleCrossbow ? 2f : 0.4f; diff --git a/src/main/java/de/teamlapen/vampirism/items/crossbow/TechCrossbowItem.java b/src/main/java/de/teamlapen/vampirism/items/crossbow/TechCrossbowItem.java index 2002f300f..17b585094 100644 --- a/src/main/java/de/teamlapen/vampirism/items/crossbow/TechCrossbowItem.java +++ b/src/main/java/de/teamlapen/vampirism/items/crossbow/TechCrossbowItem.java @@ -3,8 +3,10 @@ import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.items.IArrowContainer; import de.teamlapen.vampirism.core.ModDataComponents; +import de.teamlapen.vampirism.core.tags.ModFactionTags; import de.teamlapen.vampirism.entity.player.hunter.HunterPlayer; import de.teamlapen.vampirism.entity.player.hunter.skills.HunterSkills; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.util.ModEnchantmentHelper; import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; @@ -25,10 +27,9 @@ public class TechCrossbowItem extends HunterCrossbowItem { public TechCrossbowItem(Item.Properties properties, float arrowVelocity, int chargeTime, ToolMaterial itemTier, Holder> requiredSkill) { - super(properties.repairable(Tags.Items.INGOTS_IRON), arrowVelocity, chargeTime, itemTier, requiredSkill); + super(properties.repairable(Tags.Items.INGOTS_IRON).component(ModDataComponents.FACTION_RESTRICTION, FactionRestriction.builder(ModFactionTags.IS_HUNTER).skill(requiredSkill).build()), arrowVelocity, chargeTime, itemTier); } - @Nonnull @Override public Predicate getAllSupportedProjectiles() { diff --git a/src/main/java/de/teamlapen/vampirism/mixin/EquippableMixin.java b/src/main/java/de/teamlapen/vampirism/mixin/EquippableMixin.java index 8fa47139d..953fb4598 100644 --- a/src/main/java/de/teamlapen/vampirism/mixin/EquippableMixin.java +++ b/src/main/java/de/teamlapen/vampirism/mixin/EquippableMixin.java @@ -1,14 +1,10 @@ package de.teamlapen.vampirism.mixin; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; -import de.teamlapen.vampirism.entity.player.IVampirismPlayer; -import net.minecraft.tags.TagKey; +import de.teamlapen.vampirism.items.component.FactionRestriction; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.equipment.Equippable; -import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -19,11 +15,8 @@ public class EquippableMixin { @Inject(method = "swapWithEquipmentSlot" , at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getItemBySlot(Lnet/minecraft/world/entity/EquipmentSlot;)Lnet/minecraft/world/item/ItemStack;"), cancellable = true) private void checkFactionCheck(ItemStack newItem, Player player, CallbackInfoReturnable cir) { - if (newItem.getItem() instanceof IFactionExclusiveItem item) { - @NotNull TagKey> exclusiveFaction = item.getExclusiveFaction(newItem); - if (!IFaction.is(((IVampirismPlayer) player).getVampAtts().faction(), exclusiveFaction)) { - cir.setReturnValue(InteractionResult.FAIL); - } + if (FactionRestriction.canUse(player, newItem, true)) { + cir.setReturnValue(InteractionResult.FAIL); } } } diff --git a/src/main/java/de/teamlapen/vampirism/mixin/MixinPlayerEntity.java b/src/main/java/de/teamlapen/vampirism/mixin/MixinPlayerEntity.java index 5265c8745..ae8646354 100644 --- a/src/main/java/de/teamlapen/vampirism/mixin/MixinPlayerEntity.java +++ b/src/main/java/de/teamlapen/vampirism/mixin/MixinPlayerEntity.java @@ -1,25 +1,14 @@ package de.teamlapen.vampirism.mixin; -import com.mojang.datafixers.util.Either; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.entity.player.IVampirismPlayer; import de.teamlapen.vampirism.entity.player.VampirismPlayerAttributes; -import net.minecraft.core.BlockPos; -import net.minecraft.tags.TagKey; -import net.minecraft.util.Unit; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Player.class) public abstract class MixinPlayerEntity extends LivingEntity implements IVampirismPlayer { diff --git a/src/main/java/de/teamlapen/vampirism/modcompat/jei/VampirismJEIPlugin.java b/src/main/java/de/teamlapen/vampirism/modcompat/jei/VampirismJEIPlugin.java index d8b1c4cd7..d72ab0c9c 100755 --- a/src/main/java/de/teamlapen/vampirism/modcompat/jei/VampirismJEIPlugin.java +++ b/src/main/java/de/teamlapen/vampirism/modcompat/jei/VampirismJEIPlugin.java @@ -6,7 +6,6 @@ import de.teamlapen.vampirism.api.VampirismAPI; import de.teamlapen.vampirism.api.entity.factions.IFaction; import de.teamlapen.vampirism.api.entity.player.task.Task; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.api.items.IWeaponTableRecipe; import de.teamlapen.vampirism.api.items.oil.IApplicableOil; import de.teamlapen.vampirism.api.util.VResourceLocation; diff --git a/src/main/java/de/teamlapen/vampirism/recipes/ApplicableOilRecipe.java b/src/main/java/de/teamlapen/vampirism/recipes/ApplicableOilRecipe.java index 69e07ad2a..c76c58b0b 100644 --- a/src/main/java/de/teamlapen/vampirism/recipes/ApplicableOilRecipe.java +++ b/src/main/java/de/teamlapen/vampirism/recipes/ApplicableOilRecipe.java @@ -1,13 +1,12 @@ package de.teamlapen.vampirism.recipes; -import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.items.IFactionExclusiveItem; import de.teamlapen.vampirism.api.items.IOilItem; import de.teamlapen.vampirism.api.items.oil.IApplicableOil; import de.teamlapen.vampirism.api.items.oil.IOil; import de.teamlapen.vampirism.core.ModFactions; import de.teamlapen.vampirism.core.ModRecipes; import de.teamlapen.vampirism.items.component.AppliedOilContent; +import de.teamlapen.vampirism.items.component.FactionRestriction; import de.teamlapen.vampirism.items.component.OilContent; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; @@ -44,7 +43,7 @@ public boolean matches(@NotNull CraftingInput inventory, @NotNull Level world) { } } } - return oil != null && tool != null && (!(tool.getItem() instanceof IFactionExclusiveItem) || IFaction.is(ModFactions.HUNTER, ((IFactionExclusiveItem) tool.getItem()).getExclusiveFaction(tool))) && oil.canBeApplied(tool); + return oil != null && tool != null && FactionRestriction.matchFaction(tool, ModFactions.HUNTER) && oil.canBeApplied(tool); } @NotNull diff --git a/src/main/java/de/teamlapen/vampirism/util/Helper.java b/src/main/java/de/teamlapen/vampirism/util/Helper.java index 062cb8966..da8e84d17 100644 --- a/src/main/java/de/teamlapen/vampirism/util/Helper.java +++ b/src/main/java/de/teamlapen/vampirism/util/Helper.java @@ -4,15 +4,12 @@ import de.teamlapen.vampirism.api.EnumStrength; import de.teamlapen.vampirism.api.VampirismAPI; import de.teamlapen.vampirism.api.entity.factions.IFaction; -import de.teamlapen.vampirism.api.entity.factions.IFactionPlayerHandler; import de.teamlapen.vampirism.api.entity.hunter.IHunterMob; import de.teamlapen.vampirism.api.entity.player.IFactionPlayer; -import de.teamlapen.vampirism.api.entity.player.ISkillPlayer; import de.teamlapen.vampirism.api.entity.player.skills.ISkill; import de.teamlapen.vampirism.api.entity.player.skills.ISkillHandler; import de.teamlapen.vampirism.api.entity.player.vampire.IVampirePlayer; import de.teamlapen.vampirism.api.entity.vampire.IVampire; -import de.teamlapen.vampirism.api.items.IFactionLevelItem; import de.teamlapen.vampirism.api.items.IVampireFinisher; import de.teamlapen.vampirism.config.VampirismConfig; import de.teamlapen.vampirism.core.ModFactions; @@ -33,16 +30,13 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.DamageTypeTags; -import net.minecraft.tags.TagKey; import net.minecraft.util.Mth; -import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.*; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.state.BlockState; @@ -227,19 +221,6 @@ public static ResourceLocation getBiomeId(@NotNull CommonLevelAccessor world, @N return biome.unwrap().map(ResourceKey::location, b -> world.registryAccess().lookupOrThrow(Registries.BIOME).getKey(b)); } - /** - * Checks if the given {@link IFactionLevelItem} can be used by the given player - */ - public static & ISkillPlayer> boolean canUseFactionItem(@NotNull ItemStack stack, @NotNull IFactionLevelItem item, @NotNull IFactionPlayerHandler playerHandler) { - @NotNull TagKey> usingFaction = item.getExclusiveFaction(stack); - Holder> requiredSkill = item.requiredSkill(stack); - int reqLevel = item.getMinLevel(stack); - if (!playerHandler.isInFaction(usingFaction)) return false; - if (playerHandler.getCurrentLevel() < reqLevel) return false; - if (requiredSkill == null) return true; - return playerHandler.getSkillHandler().map(s -> s.isSkillEnabled(requiredSkill)).orElse(false); - } - /** * Returns false on client side * Determines the gender of the player by checking the skin and assuming 'slim'->female.