diff --git a/CHANGELOG.md b/CHANGELOG.md index 28a732e19..73a3c3e31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 2.0.10 + +- Fixed crash related to rascal spawns in mineshafts +- Added anger particles to rascal to indicate that hitting it is not an option +- Added missing charm slot for curios +- Added missing translations for BetterF3 mod +- Improved trigger logic for totems +- Improved compatibility with the curios mod and other totems +- Improved compatibility with the trinkets mod and other totems +- Improved catalogue compatibility +- Updated translations + ## 2.0.9 - Fixed Glare follow logic when tamed diff --git a/common/src/main/java/com/faboslav/friendsandfoes/FriendsAndFoes.java b/common/src/main/java/com/faboslav/friendsandfoes/FriendsAndFoes.java index 5a62e815a..1ac6d2e52 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/FriendsAndFoes.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/FriendsAndFoes.java @@ -7,6 +7,7 @@ import com.faboslav.friendsandfoes.events.lifecycle.RegisterReloadListenerEvent; import com.faboslav.friendsandfoes.events.lifecycle.SetupEvent; import com.faboslav.friendsandfoes.init.*; +import com.faboslav.friendsandfoes.modcompat.ModChecker; import com.faboslav.friendsandfoes.network.MessageHandler; import com.faboslav.friendsandfoes.network.packet.MoobloomVariantsSyncPacket; import com.faboslav.friendsandfoes.platform.BiomeModifications; @@ -40,6 +41,8 @@ public static Logger getLogger() { } public static void init() { + ModChecker.setupModCompat(); + FriendsAndFoesActivities.init(); FriendsAndFoesBlockSetTypes.init(); FriendsAndFoesBlocks.init(); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/feature/PlayerIllusionDeadmau5FeatureRenderer.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/feature/PlayerIllusionDeadmau5FeatureRenderer.java index d48da9b95..57243ad50 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/feature/PlayerIllusionDeadmau5FeatureRenderer.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/feature/PlayerIllusionDeadmau5FeatureRenderer.java @@ -14,8 +14,8 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; -@Environment(EnvType.CLIENT) -public class PlayerIllusionDeadmau5FeatureRenderer extends FeatureRenderer> +@Environment(value = EnvType.CLIENT) +public final class PlayerIllusionDeadmau5FeatureRenderer extends FeatureRenderer> { public PlayerIllusionDeadmau5FeatureRenderer(FeatureRendererContext> arg) { super(arg); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/PlayerIllusionEntityRenderer.java b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/PlayerIllusionEntityRenderer.java index 0027c8579..7768fd9b3 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/PlayerIllusionEntityRenderer.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/client/render/entity/renderer/PlayerIllusionEntityRenderer.java @@ -6,6 +6,8 @@ import com.faboslav.friendsandfoes.client.render.entity.feature.PlayerIllusionHeldItemFeatureRenderer; import com.faboslav.friendsandfoes.client.render.entity.model.PlayerIllusionEntityModel; import com.faboslav.friendsandfoes.entity.PlayerIllusionEntity; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.client.model.ModelPart; import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.render.RenderLayer; @@ -30,6 +32,7 @@ import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.Vec3d; +@Environment(value = EnvType.CLIENT) public final class PlayerIllusionEntityRenderer extends MobEntityRenderer> { public PlayerIllusionEntityRenderer(EntityRendererFactory.Context ctx, boolean slim) { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/MoobloomEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/MoobloomEntity.java index f5c91c005..cf1e0322e 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/MoobloomEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/MoobloomEntity.java @@ -277,7 +277,13 @@ private void setVariant(MoobloomVariant variant) { } public MoobloomVariant getVariant() { - return MoobloomVariantManager.MOOBLOOM_VARIANT_MANAGER.getMoobloomVariantByName(this.dataTracker.get(VARIANT)); + MoobloomVariant moobloomVariant = MoobloomVariantManager.MOOBLOOM_VARIANT_MANAGER.getMoobloomVariantByName(this.dataTracker.get(VARIANT)); + + if (moobloomVariant == null) { + moobloomVariant = MoobloomVariantManager.MOOBLOOM_VARIANT_MANAGER.getDefaultMoobloomVariant(); + } + + return moobloomVariant; } static { diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/PlayerIllusionEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/PlayerIllusionEntity.java index 66d419a89..19b76400c 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/PlayerIllusionEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/PlayerIllusionEntity.java @@ -1,7 +1,9 @@ package com.faboslav.friendsandfoes.entity; import com.faboslav.friendsandfoes.init.FriendsAndFoesSoundEvents; -import com.faboslav.friendsandfoes.util.client.PlayerProvider; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.render.entity.PlayerModelPart; import net.minecraft.client.util.DefaultSkinHelper; @@ -113,10 +115,12 @@ public boolean damage( return true; } + @Environment(EnvType.CLIENT) public boolean isPartVisible(PlayerModelPart modelPart) { return (this.getDataTracker().get(PLAYER_MODEL_PARTS) & modelPart.getBitFlag()) == modelPart.getBitFlag(); } + @Environment(EnvType.CLIENT) public SkinTextures getSkinTextures() { PlayerListEntry playerListEntry = this.getPlayerListEntry(); @@ -133,10 +137,12 @@ public SkinTextures getSkinTextures() { return DefaultSkinHelper.getSkinTextures(uuid); } + @Environment(EnvType.CLIENT) public Vec3d lerpVelocity(float tickDelta) { return Vec3d.ZERO.lerp(this.getVelocity(), tickDelta); } + @Environment(EnvType.CLIENT) @Nullable private PlayerListEntry getPlayerListEntry() { if (this.playerListEntry == null) { @@ -146,7 +152,7 @@ private PlayerListEntry getPlayerListEntry() { uuid = this.getUuid(); } - this.playerListEntry = PlayerProvider.getClientPlayerListEntry(uuid); + this.playerListEntry = MinecraftClient.getInstance().getNetworkHandler().getPlayerListEntry(uuid); } return this.playerListEntry; diff --git a/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java b/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java index 8d584e662..8c66edd99 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/entity/RascalEntity.java @@ -29,20 +29,22 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.tag.StructureTags; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; import net.minecraft.util.math.random.Random; import net.minecraft.world.LocalDifficulty; import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.World; import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.structure.Structure; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.List; public final class RascalEntity extends PassiveEntity implements AnimatedEntity { @@ -86,27 +88,26 @@ public static boolean canSpawn( ) { if (spawnReason == SpawnReason.NATURAL) { ServerWorld serverWorld = serverWorldAccess.toServerWorld(); + Registry structureRegistry = serverWorldAccess.getRegistryManager().get(RegistryKeys.STRUCTURE); StructureAccessor structureAccessor = serverWorld.getStructureAccessor(); - if (structureAccessor.getStructureContaining( - blockPos, - StructureTags.MINESHAFT - ).hasChildren() == false) { + if ( + blockPos.getY() > 63 + || serverWorldAccess.isSkyVisible(blockPos) + ) { return false; } - List nearbyRascals = serverWorld.getEntitiesByClass(LivingEntity.class, new Box(blockPos).expand(32.0F), (livingEntity) -> { - return livingEntity instanceof RascalEntity || livingEntity instanceof PlayerEntity; - }); - - if (nearbyRascals.isEmpty() == false) { - return false; + for (RegistryEntry structure : structureRegistry.getOrCreateEntryList(StructureTags.MINESHAFT)) { + if (structureAccessor.getStructureAt(blockPos, structure.value()).hasChildren()) { + return true; + } } - return blockPos.getY() < 63 && serverWorldAccess.isSkyVisible(blockPos) == false; + return false; } - return false; + return true; } @Override @@ -305,6 +306,7 @@ public boolean damage( this.playHurtSound(source); this.playDisappearSound(); this.spawnCloudParticles(); + this.spawnAngerParticles(); this.discard(); return false; @@ -425,6 +427,10 @@ public void spawnCloudParticles() { ParticleSpawner.spawnParticles(this, ParticleTypes.CLOUD, 16, 0.1D); } + public void spawnAngerParticles() { + ParticleSpawner.spawnParticles(this, ParticleTypes.ANGRY_VILLAGER, 16, 0.1D); + } + static { POSE_TICKS = DataTracker.registerData(RascalEntity.class, TrackedDataHandlerRegistry.INTEGER); CAUGHT_COUNT = DataTracker.registerData(RascalEntity.class, TrackedDataHandlerRegistry.INTEGER); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/events/lifecycle/ClientSetupEvent.java b/common/src/main/java/com/faboslav/friendsandfoes/events/lifecycle/ClientSetupEvent.java new file mode 100644 index 000000000..1988fc43b --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/events/lifecycle/ClientSetupEvent.java @@ -0,0 +1,23 @@ +package com.faboslav.friendsandfoes.events.lifecycle; + +import com.faboslav.friendsandfoes.events.base.EventHandler; + +import java.util.function.Consumer; + +/** + * Event related is code based on The Bumblezone/Resourceful Lib mods with permissions from the authors + * + * @author TelepathicGrunt + * https://github.com/TelepathicGrunt/Bumblezone + * @author ThatGravyBoat + * https://github.com/Team-Resourceful/ResourcefulLib + */ +public record ClientSetupEvent(Consumer enqueue) +{ + + public static final EventHandler EVENT = new EventHandler<>(); + + public void enqueueWork(Runnable runnable) { + enqueue.accept(runnable); + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/mixin/PlayerEntityMixin.java b/common/src/main/java/com/faboslav/friendsandfoes/mixin/PlayerEntityMixin.java index 61d068b66..b72f5a026 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/mixin/PlayerEntityMixin.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/mixin/PlayerEntityMixin.java @@ -4,8 +4,9 @@ import com.faboslav.friendsandfoes.init.FriendsAndFoesEntityTypes; import com.faboslav.friendsandfoes.init.FriendsAndFoesItems; import com.faboslav.friendsandfoes.init.FriendsAndFoesSoundEvents; +import com.faboslav.friendsandfoes.modcompat.ModChecker; +import com.faboslav.friendsandfoes.modcompat.ModCompat; import com.faboslav.friendsandfoes.network.packet.TotemEffectPacket; -import com.faboslav.friendsandfoes.platform.TotemHelper; import com.faboslav.friendsandfoes.tag.FriendsAndFoesTags; import net.minecraft.advancement.criterion.Criteria; import net.minecraft.entity.Entity; @@ -14,10 +15,12 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.ai.TargetPredicate; import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.damage.DamageTypes; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.ParticleTypes; @@ -38,7 +41,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.function.Predicate; @Mixin(PlayerEntity.class) @@ -105,28 +110,27 @@ private void friendsandfoes_updateWildfireCrown() { } @Inject( - at = @At("HEAD"), + at = @At("TAIL"), method = "damage", cancellable = true ) public void friendsandfoes_tryUseTotems(DamageSource source, float amount, CallbackInfoReturnable cir) { - if (this.getHealth() <= this.getMaxHealth() / 2.0F) { - PlayerEntityMixin entity = this; - - ItemStack offhandItemStack = entity.getStackInHand(Hand.OFF_HAND); - ItemStack mainhandItemStack = entity.getStackInHand(Hand.MAIN_HAND); - ItemStack moddedSlotItemStack = TotemHelper.getTotemFromModdedSlots(((PlayerEntity) (Object) entity), PlayerEntityMixin::isTotem); - - @Nullable - ItemStack totemItemStack = null; - - if (isTotem(mainhandItemStack)) { - totemItemStack = mainhandItemStack; - } else if (isTotem(offhandItemStack)) { - totemItemStack = offhandItemStack; - } else if (moddedSlotItemStack != null) { - totemItemStack = moddedSlotItemStack; - } + PlayerEntityMixin entity = this; + PlayerEntity player = (PlayerEntity) (Object) this; + + if ( + player.isAlive() + && source.isOf(DamageTypes.IN_FIRE) == false + && source.isOf(DamageTypes.ON_FIRE) == false + && source.isOf(DamageTypes.FALL) == false + && source.isOf(DamageTypes.FALLING_BLOCK) == false + && source.getAttacker() != null + && this.getHealth() <= this.getMaxHealth() / 2.0F + ) { + ItemStack totemItemStack = friendsandfoes_getTotem( + friendsandfoes_getTotemFromHands(player), + friendsandfoes_getTotemFromCustomEquipmentSlots(player) + ); if (totemItemStack != null) { if ((Object) this instanceof ServerPlayerEntity) { @@ -141,24 +145,55 @@ public void friendsandfoes_tryUseTotems(DamageSource source, float amount, Callb Criteria.USED_TOTEM.trigger(serverPlayerEntity, totemItemStack); } + Item totemItem = totemItemStack.getItem(); this.clearStatusEffects(); + TotemEffectPacket.sendToClient(((PlayerEntity) (Object) entity), totemItemStack); + totemItemStack.decrement(1); - if (totemItemStack.getItem() == FriendsAndFoesItems.TOTEM_OF_FREEZING.get()) { + if (totemItem == FriendsAndFoesItems.TOTEM_OF_FREEZING.get()) { this.friendsandfoes_freezeEntities(); this.addStatusEffect(new StatusEffectInstance(StatusEffects.SPEED, POSITIVE_EFFECT_TICKS, 1)); - } else if (totemItemStack.getItem() == FriendsAndFoesItems.TOTEM_OF_ILLUSION.get()) { + } else if (totemItem == FriendsAndFoesItems.TOTEM_OF_ILLUSION.get()) { this.friendsandfoes_createIllusions(); } - TotemEffectPacket.sendToClient(((PlayerEntity) (Object) entity), totemItemStack); - totemItemStack.decrement(1); - cir.setReturnValue(true); } } } - private static boolean isTotem(ItemStack itemStack) { + @Nullable + private static ItemStack friendsandfoes_getTotem(ItemStack... itemStacks) { + return Arrays.stream(itemStacks).filter(Objects::nonNull).toList().stream().findFirst().orElse(null); + } + + @Nullable + private static ItemStack friendsandfoes_getTotemFromHands(PlayerEntity player) { + for (Hand hand : Hand.values()) { + ItemStack itemStack = player.getStackInHand(hand); + + if (friendsandfoes_isTotem(itemStack)) { + return itemStack; + } + } + + return null; + } + + @Nullable + private static ItemStack friendsandfoes_getTotemFromCustomEquipmentSlots(PlayerEntity player) { + for (ModCompat compat : ModChecker.CUSTOM_EQUIPMENT_SLOTS_COMPATS) { + ItemStack itemStack = compat.getEquippedItemFromCustomSlots(player, PlayerEntityMixin::friendsandfoes_isTotem); + + if (itemStack != null) { + return itemStack; + } + } + + return null; + } + + private static boolean friendsandfoes_isTotem(ItemStack itemStack) { return itemStack.isIn(FriendsAndFoesTags.TOTEMS); } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModChecker.java b/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModChecker.java new file mode 100644 index 000000000..535a8a77f --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModChecker.java @@ -0,0 +1,52 @@ +package com.faboslav.friendsandfoes.modcompat; + +import com.faboslav.friendsandfoes.FriendsAndFoes; +import com.faboslav.friendsandfoes.platform.Platform; +import dev.architectury.injectables.annotations.ExpectPlatform; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * Related code is based on The Bumblezone/Resourceful Lib mods with permissions from the authors + * + * @author TelepathicGrunt + * https://github.com/TelepathicGrunt/Bumblezone + * @author ThatGravyBoat + * https://github.com/Team-Resourceful/ResourcefulLib + */ +public final class ModChecker +{ + public static final List CUSTOM_EQUIPMENT_SLOTS_COMPATS = new ArrayList<>(); + + public static void setupModCompat() { + String modId = ""; + + try { + setupPlatformModCompat(); + } catch (Throwable e) { + FriendsAndFoes.getLogger().error("Failed to setup compat with " + modId); + e.printStackTrace(); + } + } + + @ExpectPlatform + public static void setupPlatformModCompat() { + throw new AssertionError(); + } + + public static void loadModCompat(String modId, Supplier loader) { + try { + if (Platform.isModLoaded(modId)) { + ModCompat compat = loader.get(); + if (compat.compatTypes().contains(ModCompat.Type.CUSTOM_EQUIPMENT_SLOTS)) { + CUSTOM_EQUIPMENT_SLOTS_COMPATS.add(compat); + } + } + } catch (Throwable e) { + FriendsAndFoes.getLogger().error("Failed to load compat with " + modId); + e.printStackTrace(); + } + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModCompat.java b/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModCompat.java new file mode 100644 index 000000000..2b9bf0aa2 --- /dev/null +++ b/common/src/main/java/com/faboslav/friendsandfoes/modcompat/ModCompat.java @@ -0,0 +1,34 @@ +package com.faboslav.friendsandfoes.modcompat; + + +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.function.Predicate; + +/** + * Related code is based on The Bumblezone/Resourceful Lib mods with permissions from the authors + * + * @author TelepathicGrunt + * https://github.com/TelepathicGrunt/Bumblezone + * @author ThatGravyBoat + * https://github.com/Team-Resourceful/ResourcefulLib + */ +public interface ModCompat +{ + default EnumSet compatTypes() { + return EnumSet.noneOf(Type.class); + } + + @Nullable + default ItemStack getEquippedItemFromCustomSlots(Entity entity, Predicate itemStackPredicate) { + return null; + } + + enum Type + { + CUSTOM_EQUIPMENT_SLOTS, + } +} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/network/packet/TotemEffectPacket.java b/common/src/main/java/com/faboslav/friendsandfoes/network/packet/TotemEffectPacket.java index e8d0b107b..4bb44e505 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/network/packet/TotemEffectPacket.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/network/packet/TotemEffectPacket.java @@ -69,7 +69,6 @@ public PacketContext handle(final TotemEffectPacket packet) { } public TotemEffectPacket decode(final PacketByteBuf buf) { - FriendsAndFoes.getLogger().info(String.valueOf(buf)); return new TotemEffectPacket(buf.readItemStack(), buf.readInt()); } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/platform/Platform.java b/common/src/main/java/com/faboslav/friendsandfoes/platform/Platform.java index d652e64fd..de5c96915 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/platform/Platform.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/platform/Platform.java @@ -8,5 +8,10 @@ public final class Platform public static String getProjectSlug() { throw new AssertionError(); } + + @ExpectPlatform + public static boolean isModLoaded(String modId) { + throw new AssertionError(); + } } diff --git a/common/src/main/java/com/faboslav/friendsandfoes/platform/TotemHelper.java b/common/src/main/java/com/faboslav/friendsandfoes/platform/TotemHelper.java deleted file mode 100644 index 72164c063..000000000 --- a/common/src/main/java/com/faboslav/friendsandfoes/platform/TotemHelper.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.faboslav.friendsandfoes.platform; - -import com.faboslav.friendsandfoes.FriendsAndFoes; -import dev.architectury.injectables.annotations.ExpectPlatform; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Predicate; - -public final class TotemHelper -{ - public static final Identifier TOTEM_EFFECT_PACKET = FriendsAndFoes.makeID("totem_effect_packet"); - public static final String TRINKETS_MOD_ID = "trinkets"; - public static final String CURIOS_MOD_ID = "curios"; - - @ExpectPlatform - @Nullable - public static ItemStack getTotemFromModdedSlots(PlayerEntity player, Predicate totemFilter) { - throw new AssertionError(); - } - - private TotemHelper() { - } -} diff --git a/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java b/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java index 59452ecbd..8ad526821 100644 --- a/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java +++ b/common/src/main/java/com/faboslav/friendsandfoes/tag/FriendsAndFoesTags.java @@ -16,7 +16,6 @@ public final class FriendsAndFoesTags { public static final TagKey COPPER_BUTTONS = blockTag("copper_buttons"); - public static final TagKey GLOW_BERRIES = blockTag("glow_berries"); public static final TagKey LIGHTNING_RODS = blockTag("lightning_rods"); public static final TagKey LIGHTNING_ROD_POI = pointOfInterestTypeTag("lightning_rods"); public static final TagKey GLARES_SPAWNABLE_ON = blockTag("glares_spawnable_on"); diff --git a/common/src/main/java/com/faboslav/friendsandfoes/util/client/PlayerProvider.java b/common/src/main/java/com/faboslav/friendsandfoes/util/client/PlayerProvider.java deleted file mode 100644 index c0c55aa7c..000000000 --- a/common/src/main/java/com/faboslav/friendsandfoes/util/client/PlayerProvider.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.faboslav.friendsandfoes.util.client; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.entity.player.PlayerEntity; - -import java.util.UUID; - -public final class PlayerProvider -{ - public static PlayerEntity getClientPlayer() { - return MinecraftClient.getInstance().player; - } - - public static PlayerListEntry getClientPlayerListEntry(UUID uuid) { - return MinecraftClient.getInstance().getNetworkHandler().getPlayerListEntry(uuid); - } - - private PlayerProvider() { - } -} diff --git a/common/src/main/resources/assets/friendsandfoes/lang/en_us.json b/common/src/main/resources/assets/friendsandfoes/lang/en_us.json index 698229bf7..f5996076a 100644 --- a/common/src/main/resources/assets/friendsandfoes/lang/en_us.json +++ b/common/src/main/resources/assets/friendsandfoes/lang/en_us.json @@ -129,5 +129,7 @@ "subtitle.entity.friendsandfoes.wildfire.shoot": "Wildfire shoots", "subtitle.entity.friendsandfoes.wildfire.step": "Footsteps", "subtitle.entity.friendsandfoes.wildfire.summon_blaze": "Wildfire summons blazes", - "trinkets.slot.charm.charm": "Charm" -} + "trinkets.slot.charm.charm": "Charm", + "text.betterf3.line.glares": "Glares", + "text.betterf3.line.rascals": "Rascals" +} \ No newline at end of file diff --git a/common/src/main/resources/assets/friendsandfoes/lang/es_mx.json b/common/src/main/resources/assets/friendsandfoes/lang/es_mx.json new file mode 100644 index 000000000..074437554 --- /dev/null +++ b/common/src/main/resources/assets/friendsandfoes/lang/es_mx.json @@ -0,0 +1,133 @@ +{ + "advancements.husbandry.beehive.title": "Conciencia Ecologica", + "advancements.husbandry.beehive.description": "Obtener todos los tipos de colmenas", + "advancements.adventure.kill_iceologer.title": "Estuve aqui, vivi, yo..", + "advancements.adventure.kill_iceologer.description": "Mata al Hielomante", + "advancements.adventure.kill_illusioner.title": "Za Warudo", + "advancements.adventure.kill_illusioner.description": "Mata al ilusionista... si es que realmente existe", + "advancements.husbandry.shear_a_moobloom.title": "MooBoom!", + "advancements.husbandry.shear_a_moobloom.description": "Trasquila un moobloom", + "advancements.adventure.summon_copper_golem.title": "¡Allá vas!", + "advancements.adventure.summon_copper_golem.description": "Invoca a un golem de cobre", + "advancements.husbandry.tame_a_glare.title": "Quejumbroso y lindo", + "advancements.husbandry.tame_a_glare.description": "Doma un glare", + "advancements.adventure.the_magicians.title": "Los magos", + "advancements.adventure.the_magicians.description": "Mata a los tres magos maldeanos", + "advancements.adventure.it_bites.title": "Muerde", + "advancements.adventure.it_bites.description": "Mata al mauler", + "advancements.survival.activate_zombie_horse_trap.title": "Jinetes en la tormenta", + "advancements.survival.activate_zombie_horse_trap.description": "Activa una trampa para caballos zombis", + "advancements.nether.find_citadel.title": "¿Una fortaleza? ¡No, una ciudadela!", + "advancements.nether.find_citadel.description": "Entra en una ciudadela del Nether", + "advancements.nether.kill_wildfire.title": "Déjalo caer como si estuviera caliente", + "advancements.nether.kill_wildfire.description": "Mata al Wildfire", + "advancements.nether.obtain_wildfire_crown.title": "El usurpador del infierno", + "advancements.nether.obtain_wildfire_crown.description": "Ten una corona de Wildfire en tu inventario", + "advancements.adventure.complete_hide_and_seek_game.title": "Escondite", + "advancements.adventure.complete_hide_and_seek_game.description": "Encuentra a un bribón tres veces en su pequeño juego", + "block.friendsandfoes.buttercup": "Buttercup", + "block.minecraft.beehive": "Colmena de roble", + "block.friendsandfoes.acacia_beehive": "Colmena de acacia", + "block.friendsandfoes.bamboo_beehive": "Colmena de bambú", + "block.friendsandfoes.birch_beehive": "Colmena de abedul", + "block.friendsandfoes.cherry_beehive": "Colmena de cerezo", + "block.friendsandfoes.crimson_beehive": "Colmena carmesí", + "block.friendsandfoes.dark_oak_beehive": "Colmena de roble oscuro", + "block.friendsandfoes.jungle_beehive": "Colmena de jungla", + "block.friendsandfoes.mangrove_beehive": "Colmena de manglar", + "block.friendsandfoes.spruce_beehive": "Colmena de abeto", + "block.friendsandfoes.warped_beehive": "Colmena deformada", + "block.friendsandfoes.copper_button": "Botón de cobre", + "block.friendsandfoes.exposed_copper_button": "Botón de cobre expuesto", + "block.friendsandfoes.weathered_copper_button": "Botón de cobre envejecido", + "block.friendsandfoes.oxidized_copper_button": "Botón de cobre oxidado", + "block.friendsandfoes.waxed_copper_button": "Botón de cobre encerado", + "block.friendsandfoes.waxed_exposed_copper_button": "Botón de cobre expuesto encerado", + "block.friendsandfoes.waxed_weathered_copper_button": "Botón de cobre envejecido encerado", + "block.friendsandfoes.waxed_oxidized_copper_button": "Botón de cobre oxidado encerado", + "block.friendsandfoes.exposed_lightning_rod": "Pararrayos expuesto", + "block.friendsandfoes.weathered_lightning_rod": "Pararrayos envejecido", + "block.friendsandfoes.oxidized_lightning_rod": "Pararrayos oxidado", + "block.friendsandfoes.waxed_lightning_rod": "Pararrayos encerado", + "block.friendsandfoes.waxed_exposed_lightning_rod": "Pararrayos expuesto encerado", + "block.friendsandfoes.waxed_weathered_lightning_rod": "Pararrayos envejecido encerado", + "block.friendsandfoes.waxed_oxidized_lightning_rod": "Pararrayos oxidado encerado", + "block.friendsandfoes.potted_buttercup": "Buttercup en maceta", + "entity.minecraft.villager.beekeeper": "Apicultor", + "entity.minecraft.villager.friendsandfoes.beekeeper": "Apicultor", + "entity.friendsandfoes.copper_golem": "Golem de cobre", + "entity.friendsandfoes.glare": "Resplandor", + "entity.friendsandfoes.iceologer": "Hielomante", + "entity.friendsandfoes.moobloom": "Moobloom", + "entity.friendsandfoes.rascal": "Bribón", + "entity.friendsandfoes.mauler": "Mauler", + "entity.friendsandfoes.tuff_golem": "Gólem Resistente", + "entity.friendsandfoes.wildfire": "Wildfire", + "item.friendsandfoes.buttercup": "Buttercup", + "item.friendsandfoes.glare_spawn_egg": "Generar Glare", + "item.friendsandfoes.copper_golem_spawn_egg": "Generar Gólem de Cobre", + "item.friendsandfoes.iceologer_spawn_egg": "Generar Hielomante", + "item.friendsandfoes.illusioner_spawn_egg": "Generar Ilusionista", + "item.friendsandfoes.mauler_spawn_egg": "Generar Mauler", + "item.friendsandfoes.moobloom_spawn_egg": "Generar Moobloom", + "item.friendsandfoes.rascal_spawn_egg": "Generar Bribón", + "item.friendsandfoes.tuff_golem_spawn_egg": "Generar Gólem Resistente", + "item.friendsandfoes.wildfire_spawn_egg": "Generar Wildfire", + "item.friendsandfoes.totem_of_freezing": "Tótem de Congelación", + "item.friendsandfoes.totem_of_illusion": "Tótem de Ilusión", + "item.friendsandfoes.wildfire_crown": "Corona de Wildfire", + "item.friendsandfoes.wildfire_crown_fragment": "Fragmento de Corona de Wildfire", + "subtitle.entity.friendsandfoes.glare.ambient": "Glare vuela", + "subtitle.entity.friendsandfoes.glare.death": "Glare muere", + "subtitle.entity.friendsandfoes.glare.eat": "Glare come", + "subtitle.entity.friendsandfoes.glare.grumpiness": "Glare se enfurruña", + "subtitle.entity.friendsandfoes.glare.grumpiness_short": "Glare se enfurruña", + "subtitle.entity.friendsandfoes.glare.hurt": "Glare se lastima", + "subtitle.entity.friendsandfoes.glare.rustle": "Glare se enfurruña", + "subtitle.entity.friendsandfoes.glare.shake": "Glare sacude las bayas luminosas", + "subtitle.entity.friendsandfoes.copper_golem.death": "Gólem de Cobre muere", + "subtitle.entity.friendsandfoes.copper_golem.head_spin": "Gólem de Cobre gira la cabeza", + "subtitle.entity.friendsandfoes.copper_golem.hurt": "Gólem de Cobre se lastima", + "subtitle.entity.friendsandfoes.copper_golem.repair": "Gólem de Cobre reparado", + "subtitle.entity.friendsandfoes.copper_golem.step": "Pasos", + "subtitle.entity.friendsandfoes.iceologer.ambient": "Hielomante murmura", + "subtitle.entity.friendsandfoes.iceologer.cast_spell": "Hielomante lanza hechizo", + "subtitle.entity.friendsandfoes.iceologer.death": "Hielomante muere", + "subtitle.entity.friendsandfoes.iceologer.hurt": "Hielomante se lastima", + "subtitle.entity.friendsandfoes.iceologer.prepare_slowness": "Hielomante prepara lentitud", + "subtitle.entity.friendsandfoes.iceologer.prepare_summon": "Hielomante prepara invocación", + "subtitle.entity.friendsandfoes.ice_chunk.ambient": "Trozo de hielo se agrieta", + "subtitle.entity.friendsandfoes.ice_chunk.hit": "Trozo de hielo cae", + "subtitle.entity.friendsandfoes.ice_chunk.summon": "Trozo de hielo se agrieta", + "subtitle.entity.friendsandfoes.mauler.bite": "Mauler muerde", + "subtitle.entity.friendsandfoes.mauler.death": "Mauler muere", + "subtitle.entity.friendsandfoes.mauler.growl": "Mauler gruñe", + "subtitle.entity.friendsandfoes.mauler.hurt": "Mauler se lastima", + "subtitle.entity.friendsandfoes.moobloom.convert": "Moobloom se transforma", + "subtitle.entity.friendsandfoes.player.mirror_move": "Jugador se desplaza", + "subtitle.entity.friendsandfoes.rascal.ambient": "Bribón se burla", + "subtitle.entity.friendsandfoes.rascal.disappear": "Bribón desaparece", + "subtitle.entity.friendsandfoes.rascal.nod": "Bribón asiente", + "subtitle.entity.friendsandfoes.rascal.hurt": "Bribón se lastima", + "subtitle.entity.friendsandfoes.rascal.reappear": "Bribón aparece", + "subtitle.entity.friendsandfoes.rascal.reward": "Bribón da recompensa", + "subtitle.entity.friendsandfoes.rascal.reward_bad": "Bribón da mala recompensa", + "subtitle.entity.friendsandfoes.shield_debris.impact": "Debris de escudo impactado", + "subtitle.entity.friendsandfoes.tuff_golem.glue_on": "Gólem Resistente se pega", + "subtitle.entity.friendsandfoes.tuff_golem.glue_off": "Gólem Resistente se despega", + "subtitle.entity.friendsandfoes.tuff_golem.hurt": "Gólem Resistente se lastima", + "subtitle.entity.friendsandfoes.tuff_golem.move": "Gólem Resistente se mueve", + "subtitle.entity.friendsandfoes.tuff_golem.repair": "Gólem Resistente reparado", + "subtitle.entity.friendsandfoes.tuff_golem.wake": "Gólem Resistente se despierta", + "subtitle.entity.friendsandfoes.tuff_golem.sleep": "Gólem Resistente se duerme", + "subtitle.entity.friendsandfoes.tuff_golem.step": "Pasos", + "subtitle.entity.friendsandfoes.wildfire.ambient": "Wildfire respira", + "subtitle.entity.friendsandfoes.wildfire.death": "Wildfire muere", + "subtitle.entity.friendsandfoes.wildfire.hurt": "Wildfire se lastima", + "subtitle.entity.friendsandfoes.wildfire.shield_break": "Escudo de Wildfire se rompe", + "subtitle.entity.friendsandfoes.wildfire.shockwave": "Wildfire genera ondas de choque", + "subtitle.entity.friendsandfoes.wildfire.shoot": "Wildfire dispara", + "subtitle.entity.friendsandfoes.wildfire.step": "Pasos", + "subtitle.entity.friendsandfoes.wildfire.summon_blaze": "Wildfire invoca blazes", + "trinkets.slot.charm.charm": "Amuleto" +} diff --git a/common/src/main/resources/assets/friendsandfoes/lang/ko_kr.json b/common/src/main/resources/assets/friendsandfoes/lang/ko_kr.json index 94de8db86..ea6996d47 100644 --- a/common/src/main/resources/assets/friendsandfoes/lang/ko_kr.json +++ b/common/src/main/resources/assets/friendsandfoes/lang/ko_kr.json @@ -130,4 +130,4 @@ "subtitle.entity.friendsandfoes.glare.ambient": "글레어가 앵앵댐", "subtitle.entity.friendsandfoes.glare.shake": "글레어가 발광 열매를 털어냄", "trinkets.slot.charm.charm": "장식" -} +} \ No newline at end of file diff --git a/common/src/main/resources/catalogue_background.png b/common/src/main/resources/catalogue_background.png index 19c746c95..bd103780e 100644 Binary files a/common/src/main/resources/catalogue_background.png and b/common/src/main/resources/catalogue_background.png differ diff --git a/common/src/main/resources/data/curios/tags/items/charm.json b/common/src/main/resources/data/curios/tags/items/charm.json deleted file mode 100644 index b174d4418..000000000 --- a/common/src/main/resources/data/curios/tags/items/charm.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "#friendsandfoes:totems" - ] -} \ No newline at end of file diff --git a/common/src/main/resources/data/trinkets/tags/items/charm/charm.json b/common/src/main/resources/data/trinkets/tags/items/charm/charm.json deleted file mode 100644 index b174d4418..000000000 --- a/common/src/main/resources/data/trinkets/tags/items/charm/charm.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "values": [ - "#friendsandfoes:totems" - ] -} \ No newline at end of file diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/fabric/FriendsAndFoesFabricClient.java b/fabric/src/main/java/com/faboslav/friendsandfoes/fabric/FriendsAndFoesFabricClient.java index f9ab0147b..ae3ca3233 100644 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/fabric/FriendsAndFoesFabricClient.java +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/fabric/FriendsAndFoesFabricClient.java @@ -3,17 +3,12 @@ import com.faboslav.friendsandfoes.FriendsAndFoesClient; import com.faboslav.friendsandfoes.client.particle.FreezingTotemParticle; import com.faboslav.friendsandfoes.client.particle.IllusionTotemParticle; -import com.faboslav.friendsandfoes.init.FriendsAndFoesItems; +import com.faboslav.friendsandfoes.events.lifecycle.ClientSetupEvent; import com.faboslav.friendsandfoes.init.FriendsAndFoesParticleTypes; -import com.faboslav.friendsandfoes.platform.TotemHelper; -import com.faboslav.friendsandfoes.util.TotemUtil; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; -import net.minecraft.entity.Entity; -import net.minecraft.item.ItemStack; public final class FriendsAndFoesFabricClient implements ClientModInitializer { @@ -24,26 +19,16 @@ public void onInitializeClient() { FriendsAndFoesClient.postInit(); this.registerParticleFactories(); - this.registerTotemPacket(); + this.initEvents(); + } + + private void initEvents() { + ClientSetupEvent.EVENT.invoke(new ClientSetupEvent(Runnable::run)); } private void registerParticleFactories() { ParticleFactoryRegistry.getInstance().register(FriendsAndFoesParticleTypes.TOTEM_OF_FREEZING, FreezingTotemParticle.Factory::new); ParticleFactoryRegistry.getInstance().register(FriendsAndFoesParticleTypes.TOTEM_OF_ILLUSION, IllusionTotemParticle.Factory::new); } - - private void registerTotemPacket() { - ClientPlayNetworking.registerGlobalReceiver(TotemHelper.TOTEM_EFFECT_PACKET, (client, handler, buf, responseSender) -> { - ItemStack itemStack = buf.readItemStack(); - assert client.world != null; - Entity entity = client.world.getEntityById(buf.readInt()); - - if (itemStack.getItem() == FriendsAndFoesItems.TOTEM_OF_ILLUSION.get()) { - client.execute(() -> TotemUtil.playActivateAnimation(itemStack, entity, FriendsAndFoesParticleTypes.TOTEM_OF_ILLUSION)); - } else if (itemStack.getItem() == FriendsAndFoesItems.TOTEM_OF_FREEZING.get()) { - client.execute(() -> TotemUtil.playActivateAnimation(itemStack, entity, FriendsAndFoesParticleTypes.TOTEM_OF_FREEZING)); - } - }); - } } diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/CatalogueIntegration.java b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/CatalogueCompat.java similarity index 85% rename from fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/CatalogueIntegration.java rename to fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/CatalogueCompat.java index 1db0c301e..64c1764ca 100644 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/CatalogueIntegration.java +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/CatalogueCompat.java @@ -1,4 +1,4 @@ -package com.faboslav.friendsandfoes.integrations.fabric; +package com.faboslav.friendsandfoes.modcompat.fabric; import com.faboslav.friendsandfoes.FriendsAndFoes; import com.faboslav.friendsandfoes.config.ConfigScreenBuilder; @@ -6,7 +6,7 @@ import net.fabricmc.loader.api.ModContainer; import net.minecraft.client.gui.screen.Screen; -public class CatalogueIntegration +public final class CatalogueCompat { public static Screen createConfigScreen(Screen currentScreen, ModContainer container) { if (FabricLoader.getInstance().isModLoaded("catalogue") == false) { diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModCheckerImpl.java b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModCheckerImpl.java new file mode 100644 index 000000000..20edc6da3 --- /dev/null +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModCheckerImpl.java @@ -0,0 +1,20 @@ +package com.faboslav.friendsandfoes.modcompat.fabric; + +import com.faboslav.friendsandfoes.FriendsAndFoes; + +import static com.faboslav.friendsandfoes.modcompat.ModChecker.loadModCompat; + +public final class ModCheckerImpl +{ + public static void setupPlatformModCompat() { + String modId = ""; + + try { + modId = "trinkets"; + loadModCompat(modId, () -> new TrinketsCompat()); + } catch (Throwable e) { + FriendsAndFoes.getLogger().error("Failed to setup compat with " + modId); + e.printStackTrace(); + } + } +} diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/ModMenuIntegration.java b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModMenuCompat.java similarity index 71% rename from fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/ModMenuIntegration.java rename to fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModMenuCompat.java index be5a27ec4..3d4d59f78 100644 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/integrations/fabric/ModMenuIntegration.java +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/ModMenuCompat.java @@ -1,16 +1,12 @@ -package com.faboslav.friendsandfoes.integrations.fabric; +package com.faboslav.friendsandfoes.modcompat.fabric; import com.faboslav.friendsandfoes.FriendsAndFoes; import com.faboslav.friendsandfoes.config.ConfigScreenBuilder; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.fabricmc.loader.api.FabricLoader; -@Environment(EnvType.CLIENT) - -public final class ModMenuIntegration implements ModMenuApi +public final class ModMenuCompat implements ModMenuApi { @Override public ConfigScreenFactory getModConfigScreenFactory() { diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/TrinketsCompat.java b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/TrinketsCompat.java new file mode 100644 index 000000000..32734467c --- /dev/null +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/modcompat/fabric/TrinketsCompat.java @@ -0,0 +1,35 @@ +package com.faboslav.friendsandfoes.modcompat.fabric; + +import com.faboslav.friendsandfoes.modcompat.ModCompat; +import dev.emi.trinkets.api.SlotReference; +import dev.emi.trinkets.api.TrinketsApi; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Pair; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.List; +import java.util.function.Predicate; + +public final class TrinketsCompat implements ModCompat +{ + @Override + public EnumSet compatTypes() { + return EnumSet.of(Type.CUSTOM_EQUIPMENT_SLOTS); + } + + @Override + @Nullable + public ItemStack getEquippedItemFromCustomSlots(Entity entity, Predicate itemStackPredicate) { + if (entity instanceof PlayerEntity player) { + return TrinketsApi.getTrinketComponent(player).map(component -> { + List> res = component.getEquipped(itemStackPredicate); + return !res.isEmpty() ? res.get(0).getRight():null; + }).orElse(null); + } + + return null; + } +} diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/PlatformImpl.java b/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/PlatformImpl.java index e304b5fdf..e1474b928 100644 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/PlatformImpl.java +++ b/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/PlatformImpl.java @@ -1,11 +1,17 @@ package com.faboslav.friendsandfoes.platform.fabric; +import net.fabricmc.loader.api.FabricLoader; + public final class PlatformImpl { public static String getProjectSlug() { return "friends-and-foes"; } + public static boolean isModLoaded(String modId) { + return FabricLoader.getInstance().isModLoaded(modId); + } + private PlatformImpl() { } } diff --git a/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/TotemHelperImpl.java b/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/TotemHelperImpl.java deleted file mode 100644 index cda57f409..000000000 --- a/fabric/src/main/java/com/faboslav/friendsandfoes/platform/fabric/TotemHelperImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.faboslav.friendsandfoes.platform.fabric; - -import com.faboslav.friendsandfoes.platform.TotemHelper; -import dev.emi.trinkets.api.SlotReference; -import dev.emi.trinkets.api.TrinketsApi; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Pair; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.function.Predicate; - -/** - * @see TotemHelper - */ -public final class TotemHelperImpl -{ - @Nullable - public static ItemStack getTotemFromModdedSlots(PlayerEntity player, Predicate totemFilter) { - if (FabricLoader.getInstance().isModLoaded(TotemHelper.TRINKETS_MOD_ID)) { - return TrinketsApi.getTrinketComponent(player).map(component -> { - List> res = component.getEquipped(totemFilter); - return res.size() > 0 ? res.get(0).getRight():null; - }).orElse(null); - } - - return null; - } -} \ No newline at end of file diff --git a/common/src/main/resources/data/trinkets/entities/friendsandfoestotem.json b/fabric/src/main/resources/data/trinkets/entities/friendsandfoestotem.json similarity index 100% rename from common/src/main/resources/data/trinkets/entities/friendsandfoestotem.json rename to fabric/src/main/resources/data/trinkets/entities/friendsandfoestotem.json diff --git a/common/src/main/resources/data/trinkets/slots/charm/charm.json b/fabric/src/main/resources/data/trinkets/slots/charm/charm.json similarity index 100% rename from common/src/main/resources/data/trinkets/slots/charm/charm.json rename to fabric/src/main/resources/data/trinkets/slots/charm/charm.json diff --git a/fabric/src/main/resources/data/trinkets/tags/items/charm/charm.json b/fabric/src/main/resources/data/trinkets/tags/items/charm/charm.json new file mode 100644 index 000000000..79c6affe2 --- /dev/null +++ b/fabric/src/main/resources/data/trinkets/tags/items/charm/charm.json @@ -0,0 +1,27 @@ +{ + "replace": false, + "values": [ + "#friendsandfoes:totems", + "minecraft:totem_of_undying", + { + "id": "biomemakeover:enchanted_totem", + "required": false + }, + { + "id": "voidtotem:totem_of_void_undying", + "required": false + }, + { + "id": "#voidtotem:additional_totems", + "required": false + }, + { + "id": "fwaystones:void_totem", + "required": false + }, + { + "id": "netheriteextras:totem_of_neverdying", + "required": false + } + ] +} \ No newline at end of file diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 6a180df8d..d3950f4c6 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -28,7 +28,7 @@ "com.llamalad7.mixinextras.MixinExtrasBootstrap::init" ], "modmenu": [ - "com.faboslav.friendsandfoes.integrations.fabric.ModMenuIntegration" + "com.faboslav.friendsandfoes.modcompat.fabric.ModMenuCompat" ] }, "mixins": [ @@ -44,7 +44,6 @@ "custom": { "modmenu": { "links": { - "modmenu.discord": "https://discord.com/invite/QGwFvvMQCn", "Discord": "https://discord.com/invite/QGwFvvMQCn", "Wiki": "https://github.com/Faboslav/friends-and-foes/wiki", "CurseForge": "https://www.curseforge.com/minecraft/mc-mods/friends-and-foes", @@ -52,7 +51,7 @@ } }, "catalogue": { - "configFactory": "com.faboslav.friendsandfoes.integrations.fabric.CatalogueIntegration", + "configFactory": "com.faboslav.friendsandfoes.modcompat.fabric.CatalogueCompat", "icon": { "image": "catalogue_icon.png" }, diff --git a/gradle.properties b/gradle.properties index 41651cdf5..93a82a095 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.configureondemand=false # Mod mod_name=Friends&Foes mod_id=friendsandfoes -mod_version=2.0.9 +mod_version=2.0.10 mod_author=Faboslav mod_description=Adds outvoted and forgotten mobs from the mob votes in a believable vanilla plus style. maven_group=com.faboslav.friendsandfoes diff --git a/neoforge/build.gradle b/neoforge/build.gradle index c020a8e92..77af6528a 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -34,6 +34,10 @@ dependencies { implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixin_extras_version}")) implementation(include("io.github.llamalad7:mixinextras-neoforge:${rootProject.mixin_extras_version}")) + // Curios (https://www.curseforge.com/minecraft/mc-mods/curios) + modImplementation("top.theillusivec4.curios:curios-neoforge:${project.curios_version}+${rootProject.minecraft_version}:api") + modRuntimeOnly("top.theillusivec4.curios:curios-neoforge:${project.curios_version}+${rootProject.minecraft_version}"); + // Cloth config (https://www.curseforge.com/minecraft/mc-mods/cloth-config) modImplementation("me.shedaniel.cloth:cloth-config-neoforge:${rootProject.cloth_config_version}") } diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties index 2914393db..7d21ada88 100644 --- a/neoforge/gradle.properties +++ b/neoforge/gradle.properties @@ -1 +1,2 @@ -loom.platform=neoforge \ No newline at end of file +loom.platform=neoforge +curios_version=7.3.4 \ No newline at end of file diff --git a/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/CuriosCompat.java b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/CuriosCompat.java new file mode 100644 index 000000000..c8097c14a --- /dev/null +++ b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/CuriosCompat.java @@ -0,0 +1,48 @@ +package com.faboslav.friendsandfoes.modcompat.neoforge; + +import com.faboslav.friendsandfoes.events.lifecycle.ClientSetupEvent; +import com.faboslav.friendsandfoes.init.FriendsAndFoesItems; +import com.faboslav.friendsandfoes.modcompat.ModCompat; +import com.faboslav.friendsandfoes.modcompat.neoforge.curios.CuriosTotemRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.neoforged.fml.InterModComms; +import org.jetbrains.annotations.Nullable; +import top.theillusivec4.curios.api.CuriosApi; +import top.theillusivec4.curios.api.SlotResult; +import top.theillusivec4.curios.api.client.CuriosRendererRegistry; + +import java.util.EnumSet; +import java.util.function.Predicate; + +@SuppressWarnings({"all"}) +public final class CuriosCompat implements ModCompat +{ + public CuriosCompat() { + InterModComms.sendTo("curios", top.theillusivec4.curios.api.SlotTypeMessage.REGISTER_TYPE, () -> top.theillusivec4.curios.api.SlotTypePreset.CHARM.getMessageBuilder().build()); + ClientSetupEvent.EVENT.addListener(CuriosCompat::registerRenderers); + } + + private static void registerRenderers(final ClientSetupEvent clientSetupEvent) { + CuriosRendererRegistry.register(Items.TOTEM_OF_UNDYING, CuriosTotemRenderer::new); + CuriosRendererRegistry.register(FriendsAndFoesItems.TOTEM_OF_FREEZING.get(), CuriosTotemRenderer::new); + CuriosRendererRegistry.register(FriendsAndFoesItems.TOTEM_OF_ILLUSION.get(), CuriosTotemRenderer::new); + } + + @Override + public EnumSet compatTypes() { + return EnumSet.of(Type.CUSTOM_EQUIPMENT_SLOTS); + } + + @Override + @Nullable + public ItemStack getEquippedItemFromCustomSlots(Entity entity, Predicate itemStackPredicate) { + if (entity instanceof PlayerEntity player) { + return CuriosApi.getCuriosHelper().findFirstCurio(player, itemStackPredicate).map(SlotResult::stack).orElse(null); + } + + return null; + } +} diff --git a/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/ModCheckerImpl.java b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/ModCheckerImpl.java new file mode 100644 index 000000000..9cac44a99 --- /dev/null +++ b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/ModCheckerImpl.java @@ -0,0 +1,20 @@ +package com.faboslav.friendsandfoes.modcompat.neoforge; + +import com.faboslav.friendsandfoes.FriendsAndFoes; + +import static com.faboslav.friendsandfoes.modcompat.ModChecker.loadModCompat; + +public class ModCheckerImpl +{ + public static void setupPlatformModCompat() { + String modId = ""; + + try { + modId = "curios"; + loadModCompat(modId, () -> new CuriosCompat()); + } catch (Throwable e) { + FriendsAndFoes.getLogger().error("Failed to setup compat with " + modId); + e.printStackTrace(); + } + } +} diff --git a/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/curios/CuriosTotemRenderer.java b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/curios/CuriosTotemRenderer.java new file mode 100644 index 000000000..7695b7160 --- /dev/null +++ b/neoforge/src/main/java/com/faboslav/friendsandfoes/modcompat/neoforge/curios/CuriosTotemRenderer.java @@ -0,0 +1,52 @@ +package com.faboslav.friendsandfoes.modcompat.neoforge.curios; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.feature.FeatureRendererContext; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.Direction; +import top.theillusivec4.curios.api.SlotContext; +import top.theillusivec4.curios.api.client.ICurioRenderer; + +public class CuriosTotemRenderer implements ICurioRenderer +{ + @Override + public > void render( + ItemStack itemStack, + SlotContext slotContext, + MatrixStack matrices, + FeatureRendererContext featureRendererContext, + VertexConsumerProvider vertexConsumers, + int light, + float limbSwing, + float limbSwingAmount, + float partialTicks, + float ticks, + float headYaw, + float headPitch + ) { + var livingEntity = slotContext.entity(); + ICurioRenderer.translateIfSneaking(matrices, livingEntity); + ICurioRenderer.rotateIfSneaking(matrices, livingEntity); + + matrices.scale(0.35F, 0.35F, 0.35F); + matrices.translate(0.0F, 1.1F, -0.4F); + matrices.multiply(Direction.DOWN.getRotationQuaternion()); + + MinecraftClient.getInstance().getItemRenderer().renderItem( + itemStack, + ModelTransformationMode.FIXED, + light, + OverlayTexture.DEFAULT_UV, + matrices, + vertexConsumers, + null, + 0 + ); + } +} \ No newline at end of file diff --git a/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/PlatformImpl.java b/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/PlatformImpl.java index 7fde42325..69263199a 100644 --- a/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/PlatformImpl.java +++ b/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/PlatformImpl.java @@ -1,11 +1,17 @@ package com.faboslav.friendsandfoes.platform.neoforge; +import net.neoforged.fml.ModList; + public final class PlatformImpl { public static String getProjectSlug() { return "friends-and-foes-forge"; } + public static boolean isModLoaded(String modId) { + return ModList.get().isLoaded(modId); + } + private PlatformImpl() { } } diff --git a/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/TotemHelperImpl.java b/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/TotemHelperImpl.java deleted file mode 100644 index e918009c3..000000000 --- a/neoforge/src/main/java/com/faboslav/friendsandfoes/platform/neoforge/TotemHelperImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.faboslav.friendsandfoes.platform.neoforge; - -import com.faboslav.friendsandfoes.platform.TotemHelper; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; - -import java.util.function.Predicate; - -/** - * @see TotemHelper - */ -public final class TotemHelperImpl -{ - public static ItemStack getTotemFromModdedSlots(PlayerEntity player, Predicate totemFilter) { - return null; - } -} - diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml index 781063f41..e9cb22966 100644 --- a/neoforge/src/main/resources/META-INF/mods.toml +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -1,7 +1,6 @@ modLoader = "javafml" loaderVersion = "*" license = "CC-BY-NC-ND-4.0" -displayURL = "https://github.com/Faboslav/friends-and-foes" issueTrackerURL = "https://github.com/Faboslav/friends-and-foes/issues" [[mods]] @@ -12,6 +11,7 @@ authors = "${modAuthor}" description = "${modDescription}" logoFile = "icon.png" logoBlur = false +displayURL = "https://github.com/Faboslav/friends-and-foes" [[mixins]] config = "friendsandfoes-neoforge.mixins.json" @@ -26,5 +26,5 @@ versionRange = "[${minecraftVersion},)" [modproperties.${ modId }] catalogueImageIcon = "catalogue_icon.png" -catalogueBackground = "catalogue_logo.png" +catalogueBackground = "catalogue_background.png" configuredBackground = "catalogue_background.png" \ No newline at end of file diff --git a/neoforge/src/main/resources/data/curios/tags/items/charm.json b/neoforge/src/main/resources/data/curios/tags/items/charm.json new file mode 100644 index 000000000..79c6affe2 --- /dev/null +++ b/neoforge/src/main/resources/data/curios/tags/items/charm.json @@ -0,0 +1,27 @@ +{ + "replace": false, + "values": [ + "#friendsandfoes:totems", + "minecraft:totem_of_undying", + { + "id": "biomemakeover:enchanted_totem", + "required": false + }, + { + "id": "voidtotem:totem_of_void_undying", + "required": false + }, + { + "id": "#voidtotem:additional_totems", + "required": false + }, + { + "id": "fwaystones:void_totem", + "required": false + }, + { + "id": "netheriteextras:totem_of_neverdying", + "required": false + } + ] +} \ No newline at end of file diff --git a/neoforge/src/main/resources/data/friendsandfoes/curios/entities/totems.json b/neoforge/src/main/resources/data/friendsandfoes/curios/entities/totems.json new file mode 100644 index 000000000..9bc682614 --- /dev/null +++ b/neoforge/src/main/resources/data/friendsandfoes/curios/entities/totems.json @@ -0,0 +1,8 @@ +{ + "entities": [ + "player" + ], + "slots": [ + "charm" + ] +} \ No newline at end of file