diff --git a/build.gradle b/build.gradle index a4d3d709d..d860a24ca 100644 --- a/build.gradle +++ b/build.gradle @@ -111,6 +111,8 @@ allprojects { includeGroup "cpw.mods" } } + maven { url 'https://maven.wispforest.io/releases' } + maven { url 'https://maven.su5ed.dev/releases' } } tasks.withType(JavaCompile) { diff --git a/common/build.gradle b/common/build.gradle index b885c75d7..ce9ec788b 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -20,4 +20,12 @@ dependencies { modCompileOnly "be.florens:expandability-fabric:${rootProject.expandability_version}" compileOnly "com.electronwill.night-config:toml:${rootProject.night_config_version}" + + modCompileOnly("io.wispforest:accessories-common:${project.accessories_version}"){ + exclude(group: "net.fabricmc.fabric-api") + } + + modCompileOnly("dev.emi:trinkets:${rootProject.trinkets_version}"){ + exclude(group: "net.fabricmc.fabric-api") + } } diff --git a/common/src/main/java/artifacts/Artifacts.java b/common/src/main/java/artifacts/Artifacts.java index da9aa423d..f407aa305 100644 --- a/common/src/main/java/artifacts/Artifacts.java +++ b/common/src/main/java/artifacts/Artifacts.java @@ -5,7 +5,10 @@ import artifacts.config.ModConfig; import artifacts.entity.MimicEntity; import artifacts.event.ArtifactEvents; +import artifacts.integration.EquipmentIntegrationUtils; +import artifacts.integration.VanillaEquipmentIntegration; import artifacts.network.NetworkHandler; +import artifacts.platform.PlatformServices; import artifacts.registry.*; import dev.architectury.event.events.common.LifecycleEvent; import dev.architectury.event.events.common.PlayerEvent; @@ -38,6 +41,8 @@ public static ResourceKey key(ResourceKey> registry public static void init() { CONFIG = new ModConfig(); + setupIntegrations(); + NetworkHandler.register(); ModDataComponents.register(); @@ -64,4 +69,12 @@ public static void init() { public static void setupConfigs() { CONFIG.setup(); } + + public static void setupIntegrations() { + PlatformServices.platformHelper.setupIntegrations(); + + VanillaEquipmentIntegration.INSTANCE.registerIntegration(); + + EquipmentIntegrationUtils.setupIntegrations(); + } } diff --git a/common/src/main/java/artifacts/ArtifactsClient.java b/common/src/main/java/artifacts/ArtifactsClient.java index 947357da6..adbf61e42 100644 --- a/common/src/main/java/artifacts/ArtifactsClient.java +++ b/common/src/main/java/artifacts/ArtifactsClient.java @@ -6,6 +6,8 @@ import artifacts.client.mimic.MimicRenderer; import artifacts.client.mimic.model.MimicChestLayerModel; import artifacts.client.mimic.model.MimicModel; +import artifacts.platform.PlatformHelper; +import artifacts.platform.PlatformServices; import artifacts.registry.ModEntityTypes; import artifacts.registry.ModItems; import artifacts.registry.ModKeyMappings; @@ -24,6 +26,8 @@ public static void init() { registerLayerDefinitions(); registerRenderers(); ClientLifecycleEvent.CLIENT_STARTED.register(clientState -> onClientStarted()); + + PlatformServices.platformHelper.setupClientIntegratons(); } public static void onClientStarted() { diff --git a/common/src/main/java/artifacts/ability/TeleportOnDeathAbility.java b/common/src/main/java/artifacts/ability/TeleportOnDeathAbility.java index a7949056a..226dd43b5 100644 --- a/common/src/main/java/artifacts/ability/TeleportOnDeathAbility.java +++ b/common/src/main/java/artifacts/ability/TeleportOnDeathAbility.java @@ -2,6 +2,7 @@ import artifacts.config.value.Value; import artifacts.config.value.ValueTypes; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import artifacts.registry.ModAbilities; import artifacts.util.AbilityHelper; @@ -54,8 +55,7 @@ public static ItemStack findTotem(LivingEntity entity) { } } - return PlatformServices.platformHelper - .findAllEquippedBy(entity, stack -> AbilityHelper.hasAbility(ModAbilities.TELEPORT_ON_DEATH.value(), stack) + return EquipmentIntegrationUtils.findAllEquippedBy(entity, stack -> AbilityHelper.hasAbility(ModAbilities.TELEPORT_ON_DEATH.value(), stack) && !(entity instanceof Player player && player.getCooldowns().isOnCooldown(stack.getItem()))) .findFirst() .orElse(ItemStack.EMPTY); diff --git a/fabric/src/main/java/artifacts/fabric/client/CosmeticsHelper.java b/common/src/main/java/artifacts/client/CosmeticsHelper.java similarity index 64% rename from fabric/src/main/java/artifacts/fabric/client/CosmeticsHelper.java rename to common/src/main/java/artifacts/client/CosmeticsHelper.java index bcf74e2b8..c4b29b96b 100644 --- a/fabric/src/main/java/artifacts/fabric/client/CosmeticsHelper.java +++ b/common/src/main/java/artifacts/client/CosmeticsHelper.java @@ -1,19 +1,19 @@ -package artifacts.fabric.client; +package artifacts.client; -import artifacts.fabric.registry.ModDataComponentsFabric; import artifacts.item.ArtifactItem; +import artifacts.registry.ModDataComponents; import net.minecraft.world.item.ItemStack; public class CosmeticsHelper { public static boolean areCosmeticsToggledOffByPlayer(ItemStack stack) { - Boolean enabled = stack.get(ModDataComponentsFabric.COSMETICS_ENABLED.get()); + Boolean enabled = stack.get(ModDataComponents.COSMETICS_ENABLED.get()); return enabled != null && !enabled && !isCosmeticOnly(stack); } public static void toggleCosmetics(ItemStack stack) { if (!isCosmeticOnly(stack)) { - stack.set(ModDataComponentsFabric.COSMETICS_ENABLED.get(), areCosmeticsToggledOffByPlayer(stack)); + stack.set(ModDataComponents.COSMETICS_ENABLED.get(), areCosmeticsToggledOffByPlayer(stack)); } } diff --git a/common/src/main/java/artifacts/client/item/ArtifactRenderers.java b/common/src/main/java/artifacts/client/item/ArtifactRenderers.java index e42b1549b..f33fd8096 100644 --- a/common/src/main/java/artifacts/client/item/ArtifactRenderers.java +++ b/common/src/main/java/artifacts/client/item/ArtifactRenderers.java @@ -2,6 +2,7 @@ import artifacts.client.item.model.*; import artifacts.client.item.renderer.*; +import artifacts.integration.client.ClientEquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import artifacts.registry.ModItems; import net.minecraft.client.Minecraft; @@ -78,6 +79,6 @@ public static ModelPart bakeLayer(ModelLayerLocation layerLocation) { } public static void register(Item item, Supplier rendererSupplier) { - PlatformServices.platformHelper.registerArtifactRenderer(item, rendererSupplier); + ClientEquipmentIntegrationUtils.registerArtifactRenderer(item, rendererSupplier); } } diff --git a/common/src/main/java/artifacts/client/item/renderer/GloveArtifactRenderer.java b/common/src/main/java/artifacts/client/item/renderer/GloveArtifactRenderer.java index 05522bac0..cf0b217a7 100644 --- a/common/src/main/java/artifacts/client/item/renderer/GloveArtifactRenderer.java +++ b/common/src/main/java/artifacts/client/item/renderer/GloveArtifactRenderer.java @@ -1,6 +1,7 @@ package artifacts.client.item.renderer; import artifacts.client.item.model.ArmsModel; +import artifacts.integration.client.ClientEquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -45,7 +46,7 @@ public GloveArtifactRenderer(ResourceLocation wideTexture, ResourceLocation slim @Nullable public static GloveArtifactRenderer getGloveRenderer(ItemStack stack) { - if (!stack.isEmpty() && PlatformServices.platformHelper.getArtifactRenderer(stack.getItem()) instanceof GloveArtifactRenderer gloveRenderer) { + if (!stack.isEmpty() && ClientEquipmentIntegrationUtils.getArtifactRenderer(stack.getItem()) instanceof GloveArtifactRenderer gloveRenderer) { return gloveRenderer; } return null; diff --git a/common/src/main/java/artifacts/event/ArtifactEvents.java b/common/src/main/java/artifacts/event/ArtifactEvents.java index 0a600325d..8f07bc11a 100644 --- a/common/src/main/java/artifacts/event/ArtifactEvents.java +++ b/common/src/main/java/artifacts/event/ArtifactEvents.java @@ -9,6 +9,7 @@ import artifacts.ability.mobeffect.AttacksInflictMobEffectAbility; import artifacts.ability.retaliation.RetaliationAbility; import artifacts.attribute.DynamicAttributeModifier; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.item.UmbrellaItem; import artifacts.mixin.accessors.MobAccessor; import artifacts.platform.PlatformServices; @@ -98,7 +99,7 @@ public static void onItemTick(LivingEntity entity) { if (entity.level().isClientSide()) { return; } - PlatformServices.platformHelper.findAllEquippedBy(entity, stack -> stack.has(ModDataComponents.ABILITIES.value())) + EquipmentIntegrationUtils.findAllEquippedBy(entity, stack -> stack.has(ModDataComponents.ABILITIES.value())) .forEach(stack -> { for (ArtifactAbility ability : AbilityHelper.getAbilities(stack)) { boolean isActive = ability.isActive(entity); diff --git a/common/src/main/java/artifacts/integration/BaseEquipmentIntegration.java b/common/src/main/java/artifacts/integration/BaseEquipmentIntegration.java new file mode 100644 index 000000000..9b822d0d8 --- /dev/null +++ b/common/src/main/java/artifacts/integration/BaseEquipmentIntegration.java @@ -0,0 +1,45 @@ +package artifacts.integration; + +import artifacts.item.WearableArtifactItem; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public abstract class BaseEquipmentIntegration { + + protected BaseEquipmentIntegration() {} + + public final void registerIntegration() { + EquipmentIntegrationUtils.registerIntegration(this); + } + + //-- + + public abstract void setup(); + + public void processWearableArtifactBuilder(WearableArtifactItem.Builder builder) { /* NO-OP */ } + + public void addCosmeticToggleTooltip(List tooltip, ItemStack stack) { /* NO-OP */ } + + //-- + + public abstract Stream findAllEquippedBy(LivingEntity entity, Predicate predicate); + + public abstract void iterateEquippedAccessories(LivingEntity entity, Consumer consumer); + + public abstract T reduceAccessories(LivingEntity entity, T init, BiFunction f); + + public abstract boolean equipAccessory(LivingEntity entity, ItemStack stack); + + public abstract boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item); + + public abstract String name(); +} diff --git a/common/src/main/java/artifacts/integration/EquipmentIntegrationUtils.java b/common/src/main/java/artifacts/integration/EquipmentIntegrationUtils.java new file mode 100644 index 000000000..977e35f96 --- /dev/null +++ b/common/src/main/java/artifacts/integration/EquipmentIntegrationUtils.java @@ -0,0 +1,72 @@ +package artifacts.integration; + +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public class EquipmentIntegrationUtils { + + private static final Map INTEGRATIONS = new LinkedHashMap<>(); + + public static void setupIntegrations() { + INTEGRATIONS.values().forEach(BaseEquipmentIntegration::setup); + } + + public static void registerIntegration(BaseEquipmentIntegration integration) { + var name = integration.name(); + + if (INTEGRATIONS.containsKey(name)) throw new IllegalStateException("Duplicate Equipment Integration detected! [Name: " + name + "]"); + + INTEGRATIONS.put(name, integration); + } + + public static Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { + var allEquippedStacks = Stream.of(); + + for (var integration : INTEGRATIONS.values()) { + allEquippedStacks = Stream.concat(allEquippedStacks, integration.findAllEquippedBy(entity, predicate)); + } + + return allEquippedStacks; + } + + public static void iterateEquippedAccessories(LivingEntity entity, Consumer consumer) { + for (var integration : INTEGRATIONS.values()) { + integration.iterateEquippedAccessories(entity, consumer); + } + } + + public static T reduceAccessories(LivingEntity entity, T init, BiFunction f) { + for (var integration : INTEGRATIONS.values()) { + init = integration.reduceAccessories(entity, init, f); + } + + return init; + } + + public static boolean equipAccessory(LivingEntity entity, ItemStack stack) { + for (var integration : INTEGRATIONS.values()) { + if (integration.equipAccessory(entity, stack)) return true; + } + + return false; + } + + public static boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { + for (var integration : INTEGRATIONS.values()) { + if (integration.isVisibleOnHand(entity, hand, item)) return true; + } + + return false; + } +} diff --git a/common/src/main/java/artifacts/integration/VanillaEquipmentIntegration.java b/common/src/main/java/artifacts/integration/VanillaEquipmentIntegration.java new file mode 100644 index 000000000..38417885d --- /dev/null +++ b/common/src/main/java/artifacts/integration/VanillaEquipmentIntegration.java @@ -0,0 +1,55 @@ +package artifacts.integration; + +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class VanillaEquipmentIntegration extends BaseEquipmentIntegration { + + public static final VanillaEquipmentIntegration INSTANCE = new VanillaEquipmentIntegration(); + + @Override + public void setup() {} + + @Override + public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { + return StreamSupport.stream(entity.getArmorAndBodyArmorSlots().spliterator(), false).filter(predicate); + } + + @Override + public void iterateEquippedAccessories(LivingEntity entity, Consumer consumer) { + for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { + if (!item.isEmpty()) consumer.accept(item); + } + } + + @Override + public T reduceAccessories(LivingEntity entity, T init, BiFunction f) { + for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { + if (!item.isEmpty()) init = f.apply(item, init); + } + return init; + } + + @Override + public boolean equipAccessory(LivingEntity entity, ItemStack stack) { + return false; + } + + @Override + public boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { + return false; + } + + @Override + public String name() { + return "vanilla"; + } +} diff --git a/common/src/main/java/artifacts/integration/client/BaseClientEquipmentIntegration.java b/common/src/main/java/artifacts/integration/client/BaseClientEquipmentIntegration.java new file mode 100644 index 000000000..06a6acc2d --- /dev/null +++ b/common/src/main/java/artifacts/integration/client/BaseClientEquipmentIntegration.java @@ -0,0 +1,23 @@ +package artifacts.integration.client; + +import artifacts.client.item.renderer.ArtifactRenderer; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public abstract class BaseClientEquipmentIntegration { + + protected BaseClientEquipmentIntegration() {} + + public final void registerIntegration() { + ClientEquipmentIntegrationUtils.registerIntegration(this); + } + + public abstract void registerArtifactRenderer(Item item, Supplier rendererSupplier); + + @Nullable + public abstract ArtifactRenderer getArtifactRenderer(Item item); + + public abstract String name(); +} diff --git a/common/src/main/java/artifacts/integration/client/ClientEquipmentIntegrationUtils.java b/common/src/main/java/artifacts/integration/client/ClientEquipmentIntegrationUtils.java new file mode 100644 index 000000000..c6fdf1151 --- /dev/null +++ b/common/src/main/java/artifacts/integration/client/ClientEquipmentIntegrationUtils.java @@ -0,0 +1,39 @@ +package artifacts.integration.client; + +import artifacts.client.item.renderer.ArtifactRenderer; +import net.minecraft.world.item.Item; +import org.jetbrains.annotations.Nullable; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +public class ClientEquipmentIntegrationUtils { + + private static final Map INTEGRATIONS = new LinkedHashMap<>(); + + public static void registerIntegration(BaseClientEquipmentIntegration integration) { + var name = integration.name(); + + if (INTEGRATIONS.containsKey(name)) throw new IllegalStateException("Duplicate Equipment Integration detected! [Name: " + name + "]"); + + INTEGRATIONS.put(name, integration); + } + + public static void registerArtifactRenderer(Item item, Supplier rendererSupplier) { + for (var value : INTEGRATIONS.values()) { + value.registerArtifactRenderer(item, rendererSupplier); + } + } + + @Nullable + public static ArtifactRenderer getArtifactRenderer(Item item) { + for (var value : INTEGRATIONS.values()) { + var renderer = value.getArtifactRenderer(item); + + if (renderer != null) return renderer; + } + + return null; + } +} diff --git a/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesClientIntegration.java b/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesClientIntegration.java new file mode 100644 index 000000000..37d1f9783 --- /dev/null +++ b/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesClientIntegration.java @@ -0,0 +1,50 @@ +package artifacts.integration.impl.accessories; + +import artifacts.client.CosmeticsHelper; +import artifacts.client.item.renderer.ArtifactRenderer; +import artifacts.integration.client.BaseClientEquipmentIntegration; +import com.mojang.blaze3d.vertex.PoseStack; +import io.wispforest.accessories.api.client.AccessoriesRendererRegistry; +import io.wispforest.accessories.api.client.AccessoryRenderer; +import io.wispforest.accessories.api.slot.SlotReference; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public class AccessoriesClientIntegration extends BaseClientEquipmentIntegration { + + public static final AccessoriesClientIntegration INSTANCE = new AccessoriesClientIntegration(); + + @Override + public void registerArtifactRenderer(Item item, Supplier rendererSupplier) { + AccessoriesRendererRegistry.registerRenderer(item, () -> new ArtifactAccessoryRenderer(rendererSupplier.get())); + } + + @Override + public @Nullable ArtifactRenderer getArtifactRenderer(Item item) { + var renderer = AccessoriesRendererRegistry.getRender(item); + if (renderer instanceof ArtifactAccessoryRenderer artifactAccessoryRenderer) { + return artifactAccessoryRenderer.renderer(); + } + return null; + } + + @Override + public String name() { + return "accessories"; + } + + public record ArtifactAccessoryRenderer(ArtifactRenderer renderer) implements AccessoryRenderer { + @Override + public void render(ItemStack stack, SlotReference reference, PoseStack matrices, EntityModel model, MultiBufferSource multiBufferSource, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) return; + renderer.render(stack, reference.entity(), reference.slot(), matrices, multiBufferSource, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch); + } + } +} diff --git a/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesIntegration.java b/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesIntegration.java new file mode 100644 index 000000000..ff02cba38 --- /dev/null +++ b/common/src/main/java/artifacts/integration/impl/accessories/AccessoriesIntegration.java @@ -0,0 +1,147 @@ +package artifacts.integration.impl.accessories; + +import artifacts.event.ArtifactEvents; +import artifacts.integration.BaseEquipmentIntegration; +import artifacts.item.WearableArtifactItem; +import artifacts.platform.PlatformServices; +import artifacts.util.DamageSourceHelper; +import io.wispforest.accessories.api.*; +import io.wispforest.accessories.api.events.AccessoryChangeCallback; +import io.wispforest.accessories.api.slot.SlotEntryReference; +import io.wispforest.accessories.api.slot.SlotReference; +import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +public class AccessoriesIntegration extends BaseEquipmentIntegration { + + public static final AccessoriesIntegration INSTANCE = new AccessoriesIntegration(); + + @Override + public void setup() { + PlatformServices.platformHelper.registryEntryAddCallback(item -> { + if (item instanceof WearableArtifactItem wearableArtifactItem) { + AccessoriesAPI.registerAccessory(item, new WearableArtifactAccessory(wearableArtifactItem)); + } + }); + + AccessoryChangeCallback.EVENT.register((prevStack, currentStack, slotReference, slotStateChange) -> { + ArtifactEvents.onItemChanged(slotReference.entity(), prevStack, currentStack); + }); + } + + @Override + public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { + var capability = AccessoriesCapability.get(entity); + + var stacks = Stream.empty(); + + if (capability != null) { + stacks = capability.getEquipped(predicate).stream().map(SlotEntryReference::stack); + } + + return stacks; + } + + @Override + public void iterateEquippedAccessories(LivingEntity entity, Consumer consumer) { + var capability = AccessoriesCapability.get(entity); + + if(capability == null) return; + + capability.getAllEquipped().forEach(slotEntryReference -> consumer.accept(slotEntryReference.stack())); + } + + @Override + public T reduceAccessories(LivingEntity entity, T init, BiFunction f) { + var capability = AccessoriesCapability.get(entity); + + if (capability != null) { + for (var slotEntryReference : capability.getAllEquipped()) { + init = f.apply(slotEntryReference.stack(), init); + } + } + + return init; + } + + @Override + public boolean equipAccessory(LivingEntity entity, ItemStack stack) { + var capability = AccessoriesCapability.get(entity); + + if (capability != null) { + var possibleLocation = capability.canEquipAccessory(stack, false); + + if (possibleLocation != null) { + possibleLocation.second().equipStack(stack); + return true; + } + } + + return false; + } + + @Override + public boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { + var capability = AccessoriesCapability.get(entity); + + if (capability != null) { + var container = capability.getContainers().get("hand"); + + if (container != null) { + var accessories = container.getAccessories(); + var cosmetics = container.getCosmeticAccessories(); + + int startSlot = hand == InteractionHand.MAIN_HAND ? 0 : 1; + + for (int slot = startSlot; slot < container.getSize(); slot += 2) { + if (container.shouldRender(slot)) continue; + + var stack = cosmetics.getItem(slot); + + if (stack.isEmpty()) stack = accessories.getItem(slot); + + if (stack.getItem() == item) return true; + } + } + } + + return false; + } + + @Override + public String name() { + return "accessories"; + } + + public record WearableArtifactAccessory(WearableArtifactItem item) implements Accessory { + @Override + public DropRule getDropRule(ItemStack stack, SlotReference reference, DamageSource source) { + if (DamageSourceHelper.shouldDestroyWornItemsOnDeath(reference.entity())) { + return DropRule.DESTROY; + } + return Accessory.super.getDropRule(stack, reference, source); + } + + @Override + @Nullable + public SoundEventData getEquipSound(ItemStack stack, SlotReference reference) { + return new SoundEventData(Holder.direct(item.getEquipSound()), 1, item.getEquipSoundPitch()); + } + + @Override + public boolean canEquipFromUse(ItemStack stack) { + return stack.get(DataComponents.FOOD) == null; + } + } +} diff --git a/common/src/main/java/artifacts/integration/impl/trinkets/TrinketClientIntegration.java b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketClientIntegration.java new file mode 100644 index 000000000..c209d4e5e --- /dev/null +++ b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketClientIntegration.java @@ -0,0 +1,51 @@ +package artifacts.integration.impl.trinkets; + +import artifacts.client.CosmeticsHelper; +import artifacts.client.item.renderer.ArtifactRenderer; +import artifacts.integration.client.BaseClientEquipmentIntegration; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.emi.trinkets.api.SlotReference; +import dev.emi.trinkets.api.client.TrinketRenderer; +import dev.emi.trinkets.api.client.TrinketRendererRegistry; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.function.Supplier; + +public class TrinketClientIntegration extends BaseClientEquipmentIntegration { + + public static final TrinketClientIntegration INSTANCE = new TrinketClientIntegration(); + + @Override + public void registerArtifactRenderer(Item item, Supplier rendererSupplier) { + TrinketRendererRegistry.registerRenderer(item, new ArtifactTrinketRenderer(rendererSupplier.get())); + } + + @Override + public @Nullable ArtifactRenderer getArtifactRenderer(Item item) { + Optional renderer = TrinketRendererRegistry.getRenderer(item); + if (renderer.isPresent() && renderer.get() instanceof ArtifactTrinketRenderer artifactTrinketRenderer) { + return artifactTrinketRenderer.renderer(); + } + return null; + } + + @Override + public String name() { + return "trinkets"; + } + + public record ArtifactTrinketRenderer(ArtifactRenderer renderer) implements TrinketRenderer { + @Override + public void render(ItemStack stack, SlotReference slotReference, EntityModel entityModel, PoseStack poseStack, MultiBufferSource multiBufferSource, int light, LivingEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) return; + int index = slotReference.index() + (slotReference.inventory().getSlotType().getGroup().equals("hand") ? 0 : 1); + renderer.render(stack, entity, index, poseStack, multiBufferSource, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch); + } + } +} diff --git a/fabric/src/main/java/artifacts/fabric/integration/TrinketsIntegration.java b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketIntegration.java similarity index 51% rename from fabric/src/main/java/artifacts/fabric/integration/TrinketsIntegration.java rename to common/src/main/java/artifacts/integration/impl/trinkets/TrinketIntegration.java index 4a922e077..a97d35045 100644 --- a/fabric/src/main/java/artifacts/fabric/integration/TrinketsIntegration.java +++ b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketIntegration.java @@ -1,50 +1,46 @@ -package artifacts.fabric.integration; +package artifacts.integration.impl.trinkets; -import artifacts.client.item.renderer.ArtifactRenderer; +import artifacts.client.CosmeticsHelper; import artifacts.event.ArtifactEvents; -import artifacts.fabric.client.CosmeticsHelper; -import artifacts.fabric.trinket.WearableArtifactTrinket; +import artifacts.integration.BaseEquipmentIntegration; import artifacts.item.WearableArtifactItem; -import com.mojang.blaze3d.vertex.PoseStack; +import artifacts.platform.PlatformServices; +import artifacts.util.DamageSourceHelper; import dev.emi.trinkets.api.*; -import dev.emi.trinkets.api.client.TrinketRenderer; -import dev.emi.trinkets.api.client.TrinketRendererRegistry; import dev.emi.trinkets.api.event.TrinketEquipCallback; import dev.emi.trinkets.api.event.TrinketUnequipCallback; -import net.minecraft.client.model.EntityModel; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.util.Tuple; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.function.Predicate; import java.util.stream.Stream; -public class TrinketsIntegration { +public class TrinketIntegration extends BaseEquipmentIntegration { - public static void setup() { - BuiltInRegistries.ITEM.stream() - .filter(item -> item instanceof WearableArtifactItem) - .forEach(item -> TrinketsApi.registerTrinket(item, new WearableArtifactTrinket((WearableArtifactItem) item))); + public static final TrinketIntegration INSTANCE = new TrinketIntegration(); + + @Override + public void setup() { + PlatformServices.platformHelper.registryEntryAddCallback(item -> { + if (item instanceof WearableArtifactItem wearableArtifactItem) { + TrinketsApi.registerTrinket(item, new WearableArtifactTrinket(wearableArtifactItem)); + } + }); TrinketEquipCallback.EVENT.register((stack, slot, entity) -> ArtifactEvents.onItemChanged(entity, ItemStack.EMPTY, stack)); TrinketUnequipCallback.EVENT.register((stack, slot, entity) -> ArtifactEvents.onItemChanged(entity, stack, ItemStack.EMPTY)); } - public static boolean equipTrinket(LivingEntity entity, ItemStack stack) { - return TrinketItem.equipItem(entity, stack); - } - - public static Stream findAllEquippedBy(LivingEntity entity) { + @Override + public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { return TrinketsApi.getTrinketComponent(entity) .map(TrinketComponent::getAllEquipped) .orElse(List.of()) @@ -52,7 +48,8 @@ public static Stream findAllEquippedBy(LivingEntity entity) { .map(Tuple::getB); } - public static void iterateEquippedTrinkets(LivingEntity entity, Consumer consumer) { + @Override + public void iterateEquippedAccessories(LivingEntity entity, Consumer consumer) { TrinketsApi.getTrinketComponent(entity).ifPresent(component -> { for (Map map : component.getInventory().values()) { for (TrinketInventory inventory : map.values()) { @@ -67,7 +64,8 @@ public static void iterateEquippedTrinkets(LivingEntity entity, Consumer T reduceTrinkets(LivingEntity entity, T init, BiFunction f) { + @Override + public T reduceAccessories(LivingEntity entity, T init, BiFunction f) { Optional component = TrinketsApi.getTrinketComponent(entity); if (component.isPresent()) { for (Map map : component.get().getInventory().values()) { @@ -84,7 +82,13 @@ public static T reduceTrinkets(LivingEntity entity, T init, BiFunction component.getAllEquipped().stream()) .filter(tuple -> tuple.getA().inventory().getSlotType().getGroup().equals( @@ -95,28 +99,19 @@ public static boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, .anyMatch(tuple -> true); } - public static void registerArtifactRenderer(Item item, Supplier rendererSupplier) { - TrinketRendererRegistry.registerRenderer(item, new ArtifactTrinketRenderer(rendererSupplier.get())); - } - - @Nullable - public static ArtifactRenderer getArtifactRenderer(Item item) { - Optional renderer = TrinketRendererRegistry.getRenderer(item); - if (renderer.isPresent() && renderer.get() instanceof ArtifactTrinketRenderer artifactTrinketRenderer) { - return artifactTrinketRenderer.renderer(); - } - return null; + @Override + public String name() { + return "trinkets"; } - private record ArtifactTrinketRenderer(ArtifactRenderer renderer) implements TrinketRenderer { + public static record WearableArtifactTrinket(WearableArtifactItem item) implements Trinket { @Override - public void render(ItemStack stack, SlotReference slotReference, EntityModel entityModel, PoseStack poseStack, MultiBufferSource multiBufferSource, int light, LivingEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { - if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) { - return; + public TrinketEnums.DropRule getDropRule(ItemStack stack, SlotReference slot, LivingEntity entity) { + if (DamageSourceHelper.shouldDestroyWornItemsOnDeath(entity)) { + return TrinketEnums.DropRule.DESTROY; } - int index = slotReference.index() + (slotReference.inventory().getSlotType().getGroup().equals("hand") ? 0 : 1); - renderer.render(stack, entity, index, poseStack, multiBufferSource, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch); + return Trinket.super.getDropRule(stack, slot, entity); } } } diff --git a/common/src/main/java/artifacts/integration/impl/trinkets/TrinketRenderersReloadHook.java b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketRenderersReloadHook.java new file mode 100644 index 000000000..820f30088 --- /dev/null +++ b/common/src/main/java/artifacts/integration/impl/trinkets/TrinketRenderersReloadHook.java @@ -0,0 +1,21 @@ +package artifacts.integration.impl.trinkets; + +import artifacts.Artifacts; +import artifacts.client.item.ArtifactRenderers; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; + +public class TrinketRenderersReloadHook implements ResourceManagerReloadListener { + + public static final TrinketRenderersReloadHook INSTANCE = new TrinketRenderersReloadHook(); + + public static final ResourceLocation ID = Artifacts.id("trinket_renderers"); + + private TrinketRenderersReloadHook(){} + + @Override + public void onResourceManagerReload(ResourceManager resourceManager) { + ArtifactRenderers.register(); + } +} diff --git a/common/src/main/java/artifacts/mixin/item/NaturalSpawnerMixin.java b/common/src/main/java/artifacts/mixin/item/NaturalSpawnerMixin.java index 20c9e1478..9512283fa 100644 --- a/common/src/main/java/artifacts/mixin/item/NaturalSpawnerMixin.java +++ b/common/src/main/java/artifacts/mixin/item/NaturalSpawnerMixin.java @@ -1,6 +1,7 @@ package artifacts.mixin.item; import artifacts.Artifacts; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import artifacts.registry.ModLootTables; import com.llamalad7.mixinextras.sugar.Local; @@ -32,7 +33,7 @@ private static void spawnCategoryForPosition(MobCategory mobCategory, ServerLeve LootParams lootparams = params.create(LootContextParamSets.EMPTY); loottable.getRandomItems(lootparams, mob.getLootTableSeed(), stack -> { - if (!PlatformServices.platformHelper.tryEquipInFirstSlot(mob, stack)) { + if (!EquipmentIntegrationUtils.equipAccessory(mob, stack)) { Artifacts.LOGGER.warn("Could not equip item '{}' on spawned entity '{}'", stack, mob); } }); diff --git a/common/src/main/java/artifacts/platform/PlatformHelper.java b/common/src/main/java/artifacts/platform/PlatformHelper.java index 5bb1ecd4c..ea15081b3 100644 --- a/common/src/main/java/artifacts/platform/PlatformHelper.java +++ b/common/src/main/java/artifacts/platform/PlatformHelper.java @@ -1,10 +1,21 @@ package artifacts.platform; +import artifacts.Artifacts; +import artifacts.client.CosmeticsHelper; import artifacts.client.item.renderer.ArtifactRenderer; import artifacts.component.AbilityToggles; import artifacts.component.SwimData; +import artifacts.integration.EquipmentIntegrationUtils; +import artifacts.integration.client.ClientEquipmentIntegrationUtils; +import artifacts.integration.impl.accessories.AccessoriesClientIntegration; +import artifacts.integration.impl.accessories.AccessoriesIntegration; +import artifacts.integration.impl.trinkets.TrinketClientIntegration; +import artifacts.integration.impl.trinkets.TrinketIntegration; import artifacts.item.WearableArtifactItem; +import artifacts.registry.ModDataComponents; +import net.minecraft.ChatFormatting; import net.minecraft.core.Holder; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; @@ -24,14 +35,6 @@ public interface PlatformHelper { - Stream findAllEquippedBy(LivingEntity entity, Predicate predicate); - - void iterateEquippedItems(LivingEntity entity, Consumer consumer); - - T reduceItems(LivingEntity entity, T init, BiFunction f); - - boolean tryEquipInFirstSlot(LivingEntity entity, ItemStack item); - @Nullable AbilityToggles getAbilityToggles(LivingEntity entity); @@ -43,24 +46,57 @@ public interface PlatformHelper { // TODO register attributes properly Holder registerAttribute(String name, Supplier supplier); - void processWearableArtifactBuilder(WearableArtifactItem.Builder builder); - - void registerAdditionalDataComponents(); - - void addCosmeticToggleTooltip(List tooltip, ItemStack stack); + default void processWearableArtifactBuilder(WearableArtifactItem.Builder builder) { + builder.properties(properties -> properties.component(ModDataComponents.COSMETICS_ENABLED.get(), true)); + } + + default void addCosmeticToggleTooltip(List tooltip, ItemStack stack) { + if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) { + tooltip.add( + Component.translatable("%s.tooltip.cosmetics_disabled".formatted(Artifacts.MOD_ID)) + .withStyle(ChatFormatting.ITALIC) + ); + } else { + tooltip.add( + Component.translatable("%s.tooltip.cosmetics_enabled".formatted(Artifacts.MOD_ID)) + .withStyle(ChatFormatting.ITALIC) + ); + } + } boolean isEyeInWater(Player player); - boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item); + default boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { + return EquipmentIntegrationUtils.isVisibleOnHand(entity, hand, item); + } boolean areBootsHidden(LivingEntity entity); boolean isFishingRod(ItemStack stack); - void registerArtifactRenderer(Item item, Supplier rendererSupplier); + Path getConfigDir(); - @Nullable - ArtifactRenderer getArtifactRenderer(Item item); + void registryEntryAddCallback(Consumer consumer); - Path getConfigDir(); + boolean isModLoaded(String modid); + + default void setupIntegrations() { + if (PlatformServices.platformHelper.isModLoaded("trinkets") && !PlatformServices.platformHelper.isModLoaded("tclayer")) { + TrinketIntegration.INSTANCE.registerIntegration(); + } + + if (PlatformServices.platformHelper.isModLoaded("accessories")) { + AccessoriesIntegration.INSTANCE.registerIntegration(); + } + } + + default void setupClientIntegratons() { + if (PlatformServices.platformHelper.isModLoaded("trinkets") && !PlatformServices.platformHelper.isModLoaded("tclayer")) { + TrinketClientIntegration.INSTANCE.registerIntegration(); + } + + if (PlatformServices.platformHelper.isModLoaded("accessories")) { + AccessoriesClientIntegration.INSTANCE.registerIntegration(); + } + } } diff --git a/common/src/main/java/artifacts/registry/ModDataComponents.java b/common/src/main/java/artifacts/registry/ModDataComponents.java index e2b06f4ed..b7489ccd5 100644 --- a/common/src/main/java/artifacts/registry/ModDataComponents.java +++ b/common/src/main/java/artifacts/registry/ModDataComponents.java @@ -3,7 +3,9 @@ import artifacts.Artifacts; import artifacts.ability.ArtifactAbility; import artifacts.platform.PlatformServices; +import com.mojang.serialization.Codec; import dev.architectury.registry.registries.DeferredRegister; +import dev.architectury.registry.registries.RegistrySupplier; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; @@ -16,6 +18,14 @@ public class ModDataComponents { public static final DeferredRegister> DATA_COMPONENT_TYPES = DeferredRegister.create(Artifacts.MOD_ID, Registries.DATA_COMPONENT_TYPE); + // TODO: [PR] Adjust to be configurable if such is enabled or disabled I guess? + public static final RegistrySupplier> COSMETICS_ENABLED = DATA_COMPONENT_TYPES.register("cosmetic_toggle", () -> + DataComponentType.builder() + .persistent(Codec.BOOL) + .networkSynchronized(ByteBufCodecs.BOOL) + .build() + ); + public static final Holder>> ABILITIES = DATA_COMPONENT_TYPES.register("abilities", () -> DataComponentType.>builder() .persistent(ArtifactAbility.CODEC.sizeLimitedListOf(256)) @@ -25,7 +35,6 @@ public class ModDataComponents { ); public static void register() { - PlatformServices.platformHelper.registerAdditionalDataComponents(); DATA_COMPONENT_TYPES.register(); } } diff --git a/common/src/main/java/artifacts/util/AbilityHelper.java b/common/src/main/java/artifacts/util/AbilityHelper.java index 67b151253..8430ec99c 100644 --- a/common/src/main/java/artifacts/util/AbilityHelper.java +++ b/common/src/main/java/artifacts/util/AbilityHelper.java @@ -2,6 +2,7 @@ import artifacts.ability.ArtifactAbility; import artifacts.component.AbilityToggles; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import artifacts.registry.ModAbilities; import artifacts.registry.ModDataComponents; @@ -19,7 +20,7 @@ public class AbilityHelper { public static T reduce(ArtifactAbility.Type type, LivingEntity entity, boolean skipItemsOnCooldown, T init, BiFunction f) { - return PlatformServices.platformHelper.reduceItems(entity, init, (stack, init_) -> { + return EquipmentIntegrationUtils.reduceAccessories(entity, init, (stack, init_) -> { for (ArtifactAbility ability : getAbilities(stack)) { if (ability.getType() == type && (!skipItemsOnCooldown || !isOnCooldown(entity, stack))) { //noinspection unchecked @@ -124,7 +125,7 @@ public static int minInt(ArtifactAbility.Type typ public static void addCooldown(ArtifactAbility.Type type, LivingEntity entity, int ticks) { if (ticks > 0 && !entity.level().isClientSide() && entity instanceof Player player) { - PlatformServices.platformHelper.findAllEquippedBy(entity, stack -> hasAbility(type, stack)) + EquipmentIntegrationUtils.findAllEquippedBy(entity, stack -> hasAbility(type, stack)) .forEach(stack -> player.getCooldowns().addCooldown(stack.getItem(), ticks)); } } @@ -145,7 +146,7 @@ public static void forEach(ArtifactAbility.Type t } public static void forEach(ArtifactAbility.Type type, LivingEntity entity, BiConsumer consumer, boolean skipItemsOnCooldown) { - PlatformServices.platformHelper.findAllEquippedBy(entity, stack -> hasAbility(type, stack)) + EquipmentIntegrationUtils.findAllEquippedBy(entity, stack -> hasAbility(type, stack)) .forEach(stack -> getAbilities(type, stack) .filter(ArtifactAbility::isEnabled) .filter(ability -> !skipItemsOnCooldown || !(entity instanceof Player player) || !player.getCooldowns().isOnCooldown(stack.getItem())) diff --git a/common/src/main/resources/data/accessories/tags/item/belt.json b/common/src/main/resources/data/accessories/tags/item/belt.json new file mode 100644 index 000000000..db0a3e79f --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/belt.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/belt" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/data/accessories/tags/item/charm.json b/common/src/main/resources/data/accessories/tags/item/charm.json new file mode 100644 index 000000000..2ff5417a8 --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/charm.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/all" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/data/accessories/tags/item/hand.json b/common/src/main/resources/data/accessories/tags/item/hand.json new file mode 100644 index 000000000..08b836c2c --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/hand.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/hands" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/data/accessories/tags/item/hat.json b/common/src/main/resources/data/accessories/tags/item/hat.json new file mode 100644 index 000000000..653f2de1f --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/hat.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/head" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/data/accessories/tags/item/necklace.json b/common/src/main/resources/data/accessories/tags/item/necklace.json new file mode 100644 index 000000000..b2f733b1a --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/necklace.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/necklace" + ] +} \ No newline at end of file diff --git a/common/src/main/resources/data/accessories/tags/item/shoes.json b/common/src/main/resources/data/accessories/tags/item/shoes.json new file mode 100644 index 000000000..7a23794d9 --- /dev/null +++ b/common/src/main/resources/data/accessories/tags/item/shoes.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#artifacts:slot/feet" + ] +} \ No newline at end of file diff --git a/fabric/build.gradle b/fabric/build.gradle index d59271f96..d375a89e3 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -47,6 +47,8 @@ dependencies { // Compat & integration modCompileOnly("io.github.apace100:apoli:2.12.0-alpha.11+mc.1.21.x") + + modImplementation("io.wispforest:accessories-fabric:${project.accessories_version}") } processResources { diff --git a/fabric/src/main/java/artifacts/fabric/ArtifactsFabric.java b/fabric/src/main/java/artifacts/fabric/ArtifactsFabric.java index 09028f904..07abdb2e6 100644 --- a/fabric/src/main/java/artifacts/fabric/ArtifactsFabric.java +++ b/fabric/src/main/java/artifacts/fabric/ArtifactsFabric.java @@ -3,7 +3,6 @@ import artifacts.Artifacts; import artifacts.fabric.event.SwimEventsFabric; import artifacts.fabric.integration.CompatHandler; -import artifacts.fabric.integration.TrinketsIntegration; import artifacts.fabric.registry.ModFeatures; import artifacts.fabric.registry.ModLootTablesFabric; import artifacts.registry.ModItems; @@ -23,10 +22,6 @@ public void onInitialize() { Artifacts.init(); register(BuiltInRegistries.ITEM, ModItems.ITEMS); - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - TrinketsIntegration.setup(); - } - SwimEventsFabric.register(); ModFeatures.register(); diff --git a/fabric/src/main/java/artifacts/fabric/ArtifactsFabricClient.java b/fabric/src/main/java/artifacts/fabric/ArtifactsFabricClient.java index 6ec399489..2aa022542 100644 --- a/fabric/src/main/java/artifacts/fabric/ArtifactsFabricClient.java +++ b/fabric/src/main/java/artifacts/fabric/ArtifactsFabricClient.java @@ -1,12 +1,16 @@ package artifacts.fabric; import artifacts.ArtifactsClient; -import artifacts.fabric.client.TrinketRenderers; import artifacts.fabric.client.UmbrellaModelLoadingPlugin; +import artifacts.integration.impl.trinkets.TrinketRenderersReloadHook; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.resources.ResourceManager; public class ArtifactsFabricClient implements ClientModInitializer { @@ -14,7 +18,19 @@ public class ArtifactsFabricClient implements ClientModInitializer { public void onInitializeClient() { ArtifactsClient.init(); - ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new TrinketRenderers()); + if (FabricLoader.getInstance().isModLoaded("trinkets")) { + ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() { + @Override + public ResourceLocation getFabricId() { + return TrinketRenderersReloadHook.ID; + } + + @Override + public void onResourceManagerReload(ResourceManager resourceManager) { + TrinketRenderersReloadHook.INSTANCE.onResourceManagerReload(resourceManager); + } + }); + } ModelLoadingPlugin.register(new UmbrellaModelLoadingPlugin()); } } diff --git a/fabric/src/main/java/artifacts/fabric/client/TrinketRenderers.java b/fabric/src/main/java/artifacts/fabric/client/TrinketRenderers.java deleted file mode 100644 index 9f342e3d5..000000000 --- a/fabric/src/main/java/artifacts/fabric/client/TrinketRenderers.java +++ /dev/null @@ -1,20 +0,0 @@ -package artifacts.fabric.client; - -import artifacts.Artifacts; -import artifacts.client.item.ArtifactRenderers; -import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; - -public class TrinketRenderers implements SimpleSynchronousResourceReloadListener { - - @Override - public void onResourceManagerReload(ResourceManager resourceManager) { - ArtifactRenderers.register(); - } - - @Override - public ResourceLocation getFabricId() { - return Artifacts.id("trinket_renderers"); - } -} diff --git a/fabric/src/main/java/artifacts/fabric/mixin/client/GuiMixin.java b/fabric/src/main/java/artifacts/fabric/mixin/client/GuiMixin.java index 5c4e79325..0d8a82ade 100644 --- a/fabric/src/main/java/artifacts/fabric/mixin/client/GuiMixin.java +++ b/fabric/src/main/java/artifacts/fabric/mixin/client/GuiMixin.java @@ -1,6 +1,7 @@ package artifacts.fabric.mixin.client; import artifacts.Artifacts; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.platform.PlatformServices; import artifacts.registry.ModDataComponents; import net.minecraft.client.DeltaTracker; @@ -46,7 +47,7 @@ private void renderHotbarAndDecorations(GuiGraphics guiGraphics, DeltaTracker de } MutableInt k = new MutableInt(0); - PlatformServices.platformHelper.iterateEquippedItems(player, stack -> { + EquipmentIntegrationUtils.iterateEquippedAccessories(player, stack -> { if (!stack.isEmpty() && stack.has(ModDataComponents.ABILITIES.value()) && player.getCooldowns().isOnCooldown(stack.getItem())) { int x = start + step * k.intValue(); k.add(1); diff --git a/fabric/src/main/java/artifacts/fabric/mixin/compat/trinkets/client/PlayerRendererMixin.java b/fabric/src/main/java/artifacts/fabric/mixin/compat/trinkets/client/PlayerRendererMixin.java index 8bf697509..e3505a8a5 100644 --- a/fabric/src/main/java/artifacts/fabric/mixin/compat/trinkets/client/PlayerRendererMixin.java +++ b/fabric/src/main/java/artifacts/fabric/mixin/compat/trinkets/client/PlayerRendererMixin.java @@ -2,7 +2,7 @@ import artifacts.Artifacts; import artifacts.client.item.renderer.GloveArtifactRenderer; -import artifacts.fabric.client.CosmeticsHelper; +import artifacts.client.CosmeticsHelper; import artifacts.item.WearableArtifactItem; import com.mojang.blaze3d.vertex.PoseStack; import dev.emi.trinkets.api.SlotReference; diff --git a/fabric/src/main/java/artifacts/fabric/mixin/item/WearableArtifactItemMixin.java b/fabric/src/main/java/artifacts/fabric/mixin/item/WearableArtifactItemMixin.java index c767a77ba..11ff1ac7f 100644 --- a/fabric/src/main/java/artifacts/fabric/mixin/item/WearableArtifactItemMixin.java +++ b/fabric/src/main/java/artifacts/fabric/mixin/item/WearableArtifactItemMixin.java @@ -1,7 +1,7 @@ package artifacts.fabric.mixin.item; -import artifacts.fabric.client.CosmeticsHelper; -import artifacts.fabric.integration.TrinketsIntegration; +import artifacts.client.CosmeticsHelper; +import artifacts.integration.impl.trinkets.TrinketIntegration; import artifacts.item.WearableArtifactItem; import artifacts.util.AbilityHelper; import net.fabricmc.loader.api.FabricLoader; @@ -38,7 +38,7 @@ public InteractionResultHolder use(Level level, Player player, Intera ItemStack stack = player.getItemInHand(hand); if (!stack.has(DataComponents.FOOD) && FabricLoader.getInstance().isModLoaded("trinkets") - && TrinketsIntegration.equipTrinket(player, stack) + && TrinketIntegration.INSTANCE.equipAccessory(player, stack) ) { player.playSound(getEquipSound(), 1, getEquipSoundPitch()); diff --git a/fabric/src/main/java/artifacts/fabric/platform/FabricPlatformHelper.java b/fabric/src/main/java/artifacts/fabric/platform/FabricPlatformHelper.java index b6e8d2f7f..1cba0a9a0 100644 --- a/fabric/src/main/java/artifacts/fabric/platform/FabricPlatformHelper.java +++ b/fabric/src/main/java/artifacts/fabric/platform/FabricPlatformHelper.java @@ -1,26 +1,18 @@ package artifacts.fabric.platform; import artifacts.Artifacts; -import artifacts.client.item.renderer.ArtifactRenderer; import artifacts.component.AbilityToggles; import artifacts.component.SwimData; -import artifacts.fabric.client.CosmeticsHelper; -import artifacts.fabric.integration.TrinketsIntegration; import artifacts.fabric.registry.ModAttributesFabric; import artifacts.fabric.registry.ModComponents; -import artifacts.fabric.registry.ModDataComponentsFabric; -import artifacts.item.WearableArtifactItem; import artifacts.platform.PlatformHelper; +import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback; import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.ChatFormatting; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.tags.FluidTags; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.player.Player; @@ -30,60 +22,11 @@ import org.jetbrains.annotations.Nullable; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.function.Predicate; import java.util.function.Supplier; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; public class FabricPlatformHelper implements PlatformHelper { - @Override - public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { - Stream armor = StreamSupport.stream(entity.getArmorAndBodyArmorSlots().spliterator(), false).filter(predicate); - - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - return Stream.concat(TrinketsIntegration.findAllEquippedBy(entity).filter(predicate), armor); - } - return armor; - } - - @Override - public void iterateEquippedItems(LivingEntity entity, Consumer consumer) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - TrinketsIntegration.iterateEquippedTrinkets(entity, consumer); - } - for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { - if (!item.isEmpty()) { - consumer.accept(item); - } - } - } - - @Override - public T reduceItems(LivingEntity entity, T init, BiFunction f) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - init = TrinketsIntegration.reduceTrinkets(entity, init, f); - } - for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { - if (!item.isEmpty()) { - init = f.apply(item, init); - } - } - return init; - } - - @Override - public boolean tryEquipInFirstSlot(LivingEntity entity, ItemStack item) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - return TrinketsIntegration.equipTrinket(entity, item); - } - return false; - } - @Nullable @Override public AbilityToggles getAbilityToggles(LivingEntity entity) { @@ -106,44 +49,11 @@ public Holder registerAttribute(String name, Supplier properties.component(ModDataComponentsFabric.COSMETICS_ENABLED.get(), true)); - } - - @Override - public void registerAdditionalDataComponents() { - ModDataComponentsFabric.register(); - } - - @Override - public void addCosmeticToggleTooltip(List tooltip, ItemStack stack) { - if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) { - tooltip.add( - Component.translatable("%s.tooltip.cosmetics_disabled".formatted(Artifacts.MOD_ID)) - .withStyle(ChatFormatting.ITALIC) - ); - } else { - tooltip.add( - Component.translatable("%s.tooltip.cosmetics_enabled".formatted(Artifacts.MOD_ID)) - .withStyle(ChatFormatting.ITALIC) - ); - } - } - @Override public boolean isEyeInWater(Player player) { return player.isEyeInFluid(FluidTags.WATER); } - @Override - public boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - return TrinketsIntegration.isVisibleOnHand(entity, hand, item); - } - return false; - } - @Override public boolean areBootsHidden(LivingEntity entity) { return false; @@ -155,23 +65,18 @@ public boolean isFishingRod(ItemStack stack) { } @Override - public void registerArtifactRenderer(Item item, Supplier rendererSupplier) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - TrinketsIntegration.registerArtifactRenderer(item, rendererSupplier); - } + public Path getConfigDir() { + return FabricLoader.getInstance().getConfigDir(); } - @Nullable @Override - public ArtifactRenderer getArtifactRenderer(Item item) { - if (FabricLoader.getInstance().isModLoaded("trinkets")) { - return TrinketsIntegration.getArtifactRenderer(item); - } - return null; + public void registryEntryAddCallback(Consumer consumer) { + RegistryEntryAddedCallback.event(BuiltInRegistries.ITEM) + .register((i, resourceLocation, item) -> consumer.accept(item)); } @Override - public Path getConfigDir() { - return FabricLoader.getInstance().getConfigDir(); + public boolean isModLoaded(String modid) { + return FabricLoader.getInstance().isModLoaded(modid); } } diff --git a/fabric/src/main/java/artifacts/fabric/registry/ModDataComponentsFabric.java b/fabric/src/main/java/artifacts/fabric/registry/ModDataComponentsFabric.java deleted file mode 100644 index 7577018d4..000000000 --- a/fabric/src/main/java/artifacts/fabric/registry/ModDataComponentsFabric.java +++ /dev/null @@ -1,21 +0,0 @@ -package artifacts.fabric.registry; - -import artifacts.registry.ModDataComponents; -import com.mojang.serialization.Codec; -import dev.architectury.registry.registries.RegistrySupplier; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.network.codec.ByteBufCodecs; - -public class ModDataComponentsFabric { - - public static final RegistrySupplier> COSMETICS_ENABLED = ModDataComponents.DATA_COMPONENT_TYPES.register("cosmetic_toggle", () -> - DataComponentType.builder() - .persistent(Codec.BOOL) - .networkSynchronized(ByteBufCodecs.BOOL) - .build() - ); - - public static void register() { - // no-op - } -} diff --git a/fabric/src/main/java/artifacts/fabric/trinket/WearableArtifactTrinket.java b/fabric/src/main/java/artifacts/fabric/trinket/WearableArtifactTrinket.java deleted file mode 100644 index 46d7f9603..000000000 --- a/fabric/src/main/java/artifacts/fabric/trinket/WearableArtifactTrinket.java +++ /dev/null @@ -1,20 +0,0 @@ -package artifacts.fabric.trinket; - -import artifacts.item.WearableArtifactItem; -import artifacts.util.DamageSourceHelper; -import dev.emi.trinkets.api.SlotReference; -import dev.emi.trinkets.api.Trinket; -import dev.emi.trinkets.api.TrinketEnums; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; - -public record WearableArtifactTrinket(WearableArtifactItem item) implements Trinket { - - @Override - public TrinketEnums.DropRule getDropRule(ItemStack stack, SlotReference slot, LivingEntity entity) { - if (DamageSourceHelper.shouldDestroyWornItemsOnDeath(entity)) { - return TrinketEnums.DropRule.DESTROY; - } - return Trinket.super.getDropRule(stack, slot, entity); - } -} diff --git a/gradle.properties b/gradle.properties index 39b782889..94b9f18c0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-Xmx2048M +org.gradle.jvmargs=-Xmx4096M minecraft_version=1.21 enabled_platforms=fabric,neoforge @@ -22,6 +22,7 @@ trinkets_version=3.10.0 mod_menu_version=11.0.0-beta.2 cardinal_components_version=6.1.0 curious_armor_stands_version=8.0.0 +accessories_version=1.1.0-beta.7+1.21.1 night_config_version=3.8.0 diff --git a/neoforge/build.gradle b/neoforge/build.gradle index dafb21ca4..c6efcbc23 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -44,6 +44,13 @@ dependencies { modCompileOnly("curse.maven:cosmetic-armor-reworked-237307:5082294") modRuntimeOnly("maven.modrinth:curious-armor-stands:${rootProject.curious_armor_stands_version}") + + modImplementation("io.wispforest:accessories-neoforge:${project.accessories_version}") + + // Required due to issues with JIJ dependency resolving in arch or something + forgeRuntimeLibrary("io.wispforest:endec:0.1.8") + forgeRuntimeLibrary("io.wispforest.endec:gson:0.1.5") + forgeRuntimeLibrary("io.wispforest.endec:netty:0.1.4") } processResources { diff --git a/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForge.java b/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForge.java index 534be0809..5a08b5ce4 100644 --- a/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForge.java +++ b/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForge.java @@ -4,7 +4,6 @@ import artifacts.config.screen.ArtifactsConfigScreen; import artifacts.neoforge.event.ArtifactEventsNeoForge; import artifacts.neoforge.event.SwimEventsNeoForge; -import artifacts.neoforge.integration.curios.CuriosIntegration; import artifacts.neoforge.registry.ModAttachmentTypes; import artifacts.neoforge.registry.ModLootModifiers; import artifacts.registry.ModAttributes; @@ -15,7 +14,6 @@ import net.minecraft.resources.ResourceKey; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.ModList; import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.common.Mod; import net.neoforged.fml.loading.FMLEnvironment; @@ -45,10 +43,6 @@ public ArtifactsNeoForge(IEventBus modBus) { registerConfig(); ArtifactEventsNeoForge.register(); SwimEventsNeoForge.register(); - - if (ModList.get().isLoaded("curios")) { - CuriosIntegration.setup(modBus); - } } private void registerConfig() { diff --git a/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForgeClient.java b/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForgeClient.java index 844c4dfef..783811174 100644 --- a/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForgeClient.java +++ b/neoforge/src/main/java/artifacts/neoforge/ArtifactsNeoForgeClient.java @@ -3,10 +3,11 @@ import artifacts.Artifacts; import artifacts.ArtifactsClient; import artifacts.client.item.ArtifactRenderers; +import artifacts.integration.impl.trinkets.TrinketRenderersReloadHook; import artifacts.neoforge.client.ArtifactCooldownOverlayRenderer; import artifacts.neoforge.client.HeliumFlamingoOverlayRenderer; import artifacts.neoforge.client.UmbrellaArmPoseHandler; -import artifacts.neoforge.integration.curios.CuriosIntegrationClient; +import artifacts.neoforge.integration.curios.CuriosClientIntegration; import artifacts.registry.ModItems; import net.minecraft.client.renderer.item.ItemProperties; import net.neoforged.bus.api.IEventBus; @@ -14,6 +15,7 @@ import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent; import net.neoforged.neoforge.client.gui.VanillaGuiLayers; +import net.neoforged.neoforge.event.AddReloadListenerEvent; public class ArtifactsNeoForgeClient { @@ -23,9 +25,11 @@ public ArtifactsNeoForgeClient(IEventBus modBus) { modBus.addListener(this::onClientSetup); modBus.addListener(this::onRegisterGuiOverlays); - if (ModList.get().isLoaded("curios")) { - CuriosIntegrationClient.setup(modBus); - } + modBus.addListener((AddReloadListenerEvent event) -> { + if (ModList.get().isLoaded("trinkets")) { + event.addListener(TrinketRenderersReloadHook.INSTANCE); + } + }); } public void onClientSetup(FMLClientSetupEvent event) { diff --git a/neoforge/src/main/java/artifacts/neoforge/client/ArtifactCooldownOverlayRenderer.java b/neoforge/src/main/java/artifacts/neoforge/client/ArtifactCooldownOverlayRenderer.java index b7d83c21d..d0a2f1be8 100644 --- a/neoforge/src/main/java/artifacts/neoforge/client/ArtifactCooldownOverlayRenderer.java +++ b/neoforge/src/main/java/artifacts/neoforge/client/ArtifactCooldownOverlayRenderer.java @@ -1,6 +1,7 @@ package artifacts.neoforge.client; import artifacts.Artifacts; +import artifacts.integration.EquipmentIntegrationUtils; import artifacts.item.WearableArtifactItem; import artifacts.platform.PlatformServices; import net.minecraft.client.DeltaTracker; @@ -31,7 +32,7 @@ public static void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { MutableInt k = new MutableInt(0); - PlatformServices.platformHelper.iterateEquippedItems(player, stack -> { + EquipmentIntegrationUtils.iterateEquippedAccessories(player, stack -> { if (!stack.isEmpty() && stack.getItem() instanceof WearableArtifactItem && player.getCooldowns().isOnCooldown(stack.getItem())) { int x = start + step * k.intValue(); k.add(1); diff --git a/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegrationClient.java b/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosClientIntegration.java similarity index 79% rename from neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegrationClient.java rename to neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosClientIntegration.java index 123b32358..aac821c8c 100644 --- a/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegrationClient.java +++ b/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosClientIntegration.java @@ -1,6 +1,8 @@ package artifacts.neoforge.integration.curios; +import artifacts.client.CosmeticsHelper; import artifacts.client.item.renderer.ArtifactRenderer; +import artifacts.integration.client.BaseClientEquipmentIntegration; import artifacts.mixin.accessors.client.LivingEntityRendererAccessor; import artifacts.neoforge.client.ArmRenderHandler; import artifacts.registry.ModLootTables; @@ -17,6 +19,7 @@ import net.minecraft.world.item.ItemStack; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.client.event.EntityRenderersEvent; +import org.jetbrains.annotations.Nullable; import top.theillusivec4.curios.api.SlotContext; import top.theillusivec4.curios.api.client.CuriosRendererRegistry; import top.theillusivec4.curios.api.client.ICurioRenderer; @@ -26,10 +29,12 @@ import java.util.Set; import java.util.function.Supplier; -public class CuriosIntegrationClient { +public class CuriosClientIntegration extends BaseClientEquipmentIntegration { + + public static final CuriosClientIntegration INSTANCE = new CuriosClientIntegration(); public static void setup(IEventBus modBus) { - modBus.addListener(CuriosIntegrationClient::onAddLayers); + modBus.addListener(CuriosClientIntegration::onAddLayers); ArmRenderHandler.setup(); } @@ -52,11 +57,13 @@ public static void onAddLayers(EntityRenderersEvent.AddLayers event) { } } - public static void registerArtifactRenderer(Item item, Supplier rendererSupplier) { - CuriosRendererRegistry.register(item, () -> new CuriosIntegrationClient.ArtifactCurioRenderer(rendererSupplier.get())); + @Override + public void registerArtifactRenderer(Item item, Supplier rendererSupplier) { + CuriosRendererRegistry.register(item, () -> new ArtifactCurioRenderer(rendererSupplier.get())); } - public static ArtifactRenderer getArtifactRenderer(Item item) { + @Override + public @Nullable ArtifactRenderer getArtifactRenderer(Item item) { Optional renderer = CuriosRendererRegistry.getRenderer(item); if (renderer.isPresent() && renderer.get() instanceof ArtifactCurioRenderer artifactTrinketRenderer) { return artifactTrinketRenderer.renderer(); @@ -64,10 +71,15 @@ public static ArtifactRenderer getArtifactRenderer(Item item) { return null; } - public record ArtifactCurioRenderer(ArtifactRenderer renderer) implements ICurioRenderer { + @Override + public String name() { + return "curios"; + } + public record ArtifactCurioRenderer(ArtifactRenderer renderer) implements ICurioRenderer { @Override public > void render(ItemStack stack, SlotContext slotContext, PoseStack poseStack, RenderLayerParent renderLayerParent, MultiBufferSource multiBufferSource, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { + if (CosmeticsHelper.areCosmeticsToggledOffByPlayer(stack)) return; renderer.render(stack, slotContext.entity(), slotContext.index(), poseStack, multiBufferSource, light, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch); } } diff --git a/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegration.java b/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegration.java index 25ec04c35..134b95617 100644 --- a/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegration.java +++ b/neoforge/src/main/java/artifacts/neoforge/integration/curios/CuriosIntegration.java @@ -1,16 +1,13 @@ package artifacts.neoforge.integration.curios; import artifacts.event.ArtifactEvents; +import artifacts.integration.BaseEquipmentIntegration; import artifacts.item.WearableArtifactItem; -import artifacts.neoforge.curio.WearableArtifactCurio; -import artifacts.registry.ModItems; +import artifacts.platform.PlatformServices; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.ModList; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.common.NeoForge; import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.SlotContext; @@ -27,35 +24,32 @@ import java.util.function.Predicate; import java.util.stream.Stream; -public class CuriosIntegration { +public class CuriosIntegration extends BaseEquipmentIntegration { - public static void setup(IEventBus modBus) { - modBus.addListener(CuriosIntegration::registerCapabilities); - NeoForge.EVENT_BUS.addListener(CuriosIntegration::onCurioChanged); - } - - private static void registerCapabilities(@SuppressWarnings("unused") RegisterCapabilitiesEvent event) { - if (ModList.get().isLoaded("curios")) { - ModItems.ITEMS.forEach(entry -> { - if (entry.get() instanceof WearableArtifactItem item) { - CuriosApi.registerCurio(item, new WearableArtifactCurio(item)); - } - }); - } - } + public static final CuriosIntegration INSTANCE = new CuriosIntegration(); - private static void onCurioChanged(CurioChangeEvent event) { - ArtifactEvents.onItemChanged(event.getEntity(), event.getFrom(), event.getTo()); + @Override + public void setup() { + PlatformServices.platformHelper.registryEntryAddCallback(item -> { + if (item instanceof WearableArtifactItem wearableArtifactItem) { + CuriosApi.registerCurio(wearableArtifactItem, new WearableArtifactCurio(wearableArtifactItem)); + } + }); + NeoForge.EVENT_BUS.addListener((CurioChangeEvent event) -> { + ArtifactEvents.onItemChanged(event.getEntity(), event.getFrom(), event.getTo()); + }); } - public static Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { + @Override + public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { return CuriosApi.getCuriosInventory(entity) .map(inv -> inv.findCurios(predicate)) .orElse(List.of()).stream() .map(SlotResult::stack); } - public static void iterateEquippedCurios(LivingEntity entity, Consumer consumer) { + @Override + public void iterateEquippedAccessories(LivingEntity entity, Consumer consumer) { Optional itemHandler = CuriosApi.getCuriosInventory(entity); if (itemHandler.isPresent()) { for (ICurioStacksHandler stacksHandler : itemHandler.get().getCurios().values()) { @@ -69,7 +63,8 @@ public static void iterateEquippedCurios(LivingEntity entity, Consumer T reduceCurios(LivingEntity entity, T init, BiFunction f) { + @Override + public T reduceAccessories(LivingEntity entity, T init, BiFunction f) { Optional itemHandler = CuriosApi.getCuriosInventory(entity); if (itemHandler.isPresent()) { for (ICurioStacksHandler stacksHandler : itemHandler.get().getCurios().values()) { @@ -84,7 +79,8 @@ public static T reduceCurios(LivingEntity entity, T init, BiFunction optional = CuriosApi.getCuriosInventory(entity); if (optional.isPresent()) { ICuriosItemHandler handler = optional.get(); @@ -92,8 +88,8 @@ public static boolean tryEquipInFirstSlot(LivingEntity entity, ItemStack item) { for (int i = 0; i < entry.getValue().getSlots(); i++) { SlotContext slotContext = new SlotContext(entry.getKey(), entity, i, false, true); //noinspection ConstantConditions - if (CuriosApi.isStackValid(slotContext, item) && entry.getValue().getStacks().getStackInSlot(i).isEmpty()) { - entry.getValue().getStacks().setStackInSlot(i, item); + if (CuriosApi.isStackValid(slotContext, stack) && entry.getValue().getStacks().getStackInSlot(i).isEmpty()) { + entry.getValue().getStacks().setStackInSlot(i, stack); return true; } } @@ -102,7 +98,8 @@ public static boolean tryEquipInFirstSlot(LivingEntity entity, ItemStack item) { return false; } - public static boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { + @Override + public boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { return CuriosApi.getCuriosInventory(entity) .flatMap(handler -> Optional.ofNullable(handler.getCurios().get("hands"))) .map(stacksHandler -> { @@ -120,4 +117,9 @@ public static boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, return false; }).orElse(false); } + + @Override + public String name() { + return "curios"; + } } diff --git a/neoforge/src/main/java/artifacts/neoforge/curio/WearableArtifactCurio.java b/neoforge/src/main/java/artifacts/neoforge/integration/curios/WearableArtifactCurio.java similarity index 96% rename from neoforge/src/main/java/artifacts/neoforge/curio/WearableArtifactCurio.java rename to neoforge/src/main/java/artifacts/neoforge/integration/curios/WearableArtifactCurio.java index 35c1fe6a5..edae89088 100644 --- a/neoforge/src/main/java/artifacts/neoforge/curio/WearableArtifactCurio.java +++ b/neoforge/src/main/java/artifacts/neoforge/integration/curios/WearableArtifactCurio.java @@ -1,4 +1,4 @@ -package artifacts.neoforge.curio; +package artifacts.neoforge.integration.curios; import artifacts.item.WearableArtifactItem; import artifacts.util.DamageSourceHelper; diff --git a/neoforge/src/main/java/artifacts/neoforge/platform/NeoForgePlatformHelper.java b/neoforge/src/main/java/artifacts/neoforge/platform/NeoForgePlatformHelper.java index 84a20ed65..bf374ba9a 100644 --- a/neoforge/src/main/java/artifacts/neoforge/platform/NeoForgePlatformHelper.java +++ b/neoforge/src/main/java/artifacts/neoforge/platform/NeoForgePlatformHelper.java @@ -1,21 +1,19 @@ package artifacts.neoforge.platform; import artifacts.Artifacts; -import artifacts.client.item.renderer.ArtifactRenderer; import artifacts.component.AbilityToggles; import artifacts.component.SwimData; -import artifacts.item.WearableArtifactItem; import artifacts.neoforge.integration.cosmeticarmor.CosmeticArmorCompat; +import artifacts.neoforge.integration.curios.CuriosClientIntegration; import artifacts.neoforge.integration.curios.CuriosIntegration; -import artifacts.neoforge.integration.curios.CuriosIntegrationClient; import artifacts.neoforge.registry.ModAttachmentTypes; import artifacts.platform.PlatformHelper; +import artifacts.platform.PlatformServices; import artifacts.registry.ModAttributes; import artifacts.registry.RegistryHolder; import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.player.Player; @@ -25,63 +23,15 @@ import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.common.ItemAbilities; import net.neoforged.neoforge.common.NeoForgeMod; +import net.neoforged.neoforge.registries.callback.AddCallback; import org.jetbrains.annotations.Nullable; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.function.Predicate; import java.util.function.Supplier; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; public class NeoForgePlatformHelper implements PlatformHelper { - @Override - public Stream findAllEquippedBy(LivingEntity entity, Predicate predicate) { - Stream armor = StreamSupport.stream(entity.getArmorAndBodyArmorSlots().spliterator(), false).filter(predicate); - if (ModList.get().isLoaded("curios")) { - return Stream.concat(CuriosIntegration.findAllEquippedBy(entity, predicate), armor); - } - return armor; - } - - @Override - public void iterateEquippedItems(LivingEntity entity, Consumer consumer) { - if (ModList.get().isLoaded("curios")) { - CuriosIntegration.iterateEquippedCurios(entity, consumer); - } - for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { - if (!item.isEmpty()) { - consumer.accept(item); - } - } - } - - @Override - public T reduceItems(LivingEntity entity, T init, BiFunction f) { - if (ModList.get().isLoaded("curios")) { - init = CuriosIntegration.reduceCurios(entity, init, f); - } - - for (ItemStack item : entity.getArmorAndBodyArmorSlots()) { - if (!item.isEmpty()) { - init = f.apply(item, init); - } - } - return init; - } - - @Override - public boolean tryEquipInFirstSlot(LivingEntity entity, ItemStack item) { - if (ModList.get().isLoaded("curios")) { - return CuriosIntegration.tryEquipInFirstSlot(entity, item); - } - return false; - } - @Nullable @Override public AbilityToggles getAbilityToggles(LivingEntity entity) { @@ -106,34 +56,11 @@ public Holder registerAttribute(String name, Supplier tooltip, ItemStack stack) { - - } - @Override public boolean isEyeInWater(Player player) { return player.isEyeInFluidType(NeoForgeMod.WATER_TYPE.value()); } - @Override - public boolean isVisibleOnHand(LivingEntity entity, InteractionHand hand, Item item) { - if (ModList.get().isLoaded("curios")) { - return CuriosIntegration.isVisibleOnHand(entity, hand, item); - } - return false; - } - @Override public boolean areBootsHidden(LivingEntity entity) { if (entity instanceof Player player && ModList.get().isLoaded("cosmeticarmorreworked")) { @@ -148,23 +75,34 @@ public boolean isFishingRod(ItemStack stack) { } @Override - public void registerArtifactRenderer(Item item, Supplier rendererSupplier) { - if (ModList.get().isLoaded("curios")) { - CuriosIntegrationClient.registerArtifactRenderer(item, rendererSupplier); - } + public Path getConfigDir() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public void registryEntryAddCallback(Consumer consumer) { + BuiltInRegistries.ITEM.addCallback((AddCallback) (registry, i, key, item) -> consumer.accept(item)); } - @Nullable @Override - public ArtifactRenderer getArtifactRenderer(Item item) { - if (ModList.get().isLoaded("curios")) { - return CuriosIntegrationClient.getArtifactRenderer(item); + public boolean isModLoaded(String modid) { + return ModList.get().isLoaded(modid); + } + + public void setupIntegrations() { + PlatformHelper.super.setupIntegrations(); + + if (PlatformServices.platformHelper.isModLoaded("curios") && !PlatformServices.platformHelper.isModLoaded("cclayer")) { + CuriosIntegration.INSTANCE.registerIntegration(); } - return null; } @Override - public Path getConfigDir() { - return FMLPaths.CONFIGDIR.get(); + public void setupClientIntegratons() { + PlatformHelper.super.setupClientIntegratons(); + + if (PlatformServices.platformHelper.isModLoaded("curios") && !PlatformServices.platformHelper.isModLoaded("cclayer")) { + CuriosClientIntegration.INSTANCE.registerIntegration(); + } } }