diff --git a/src/main/java/com/github/elenterius/biomancy/event/ChatMessageHandler.java b/src/main/java/com/github/elenterius/biomancy/event/ChatMessageHandler.java index 0a963bec..34b22aa1 100644 --- a/src/main/java/com/github/elenterius/biomancy/event/ChatMessageHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/event/ChatMessageHandler.java @@ -6,33 +6,36 @@ import com.github.elenterius.biomancy.util.ComponentUtil; import com.github.elenterius.biomancy.util.TransliterationUtil; import net.minecraft.SharedConstants; -import net.minecraft.network.chat.Component; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.HoverEvent; +import net.minecraftforge.client.event.ClientChatEvent; import net.minecraftforge.event.ServerChatEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import org.apache.commons.lang3.StringUtils; -import java.util.function.UnaryOperator; - @Mod.EventBusSubscriber(modid = BiomancyMod.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) public final class ChatMessageHandler { - private static final UnaryOperator ABBREVIATE_OPERATOR = s -> StringUtils.abbreviate(s, SharedConstants.MAX_CHAT_LENGTH); - private ChatMessageHandler() {} @SubscribeEvent public static void onServerReceiveChatMessageFromClient(final ServerChatEvent event) { if (event.getPlayer().hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) { - event.setMessage(transform(event.getMessage())); + HoverEvent hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, event.getMessage().copy()); + event.setMessage(ComponentUtil.setStyles(event.getMessage(), TextStyles.PRIMORDIAL_RUNES.withHoverEvent(hoverEvent))); } } - private static Component transform(Component component) { - Component transliterated = TransliterationUtil.transliterate(component, ABBREVIATE_OPERATOR); - HoverEvent hoverEvent = new HoverEvent(HoverEvent.Action.SHOW_TEXT, component.copy()); - return ComponentUtil.setStyles(transliterated, TextStyles.PRIMORDIAL_RUNES.withHoverEvent(hoverEvent)); + @SubscribeEvent + public static void onClientSendChatMessageToServer(final ClientChatEvent event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player != null && player.hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) { + String transliterated = TransliterationUtil.transliterate(event.getMessage()); + String abbreviated = StringUtils.abbreviate(transliterated, SharedConstants.MAX_CHAT_LENGTH); + event.setMessage(abbreviated); + } } } diff --git a/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java b/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java index 11b7d5ae..5afebb12 100644 --- a/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/init/client/ClientSetupHandler.java @@ -37,6 +37,7 @@ import com.github.elenterius.biomancy.tooltip.EmptyLineTooltipComponent; import com.github.elenterius.biomancy.tooltip.HrTooltipComponent; import com.github.elenterius.biomancy.tooltip.StorageSacTooltipComponent; +import com.github.elenterius.biomancy.util.TransliterationUtil; import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import net.minecraft.client.particle.AttackSweepParticle; @@ -78,6 +79,8 @@ public static void onSetup(final FMLClientSetupEvent event) { event.enqueueWork(ClientSetupHandler::onPostSetup); + TransliterationUtil.init(); + ModsCompatHandler.onBiomancyClientSetup(event); } diff --git a/src/main/java/com/github/elenterius/biomancy/mixin/ServerGamePacketListenerImplMixin.java b/src/main/java/com/github/elenterius/biomancy/mixin/ServerGamePacketListenerImplMixin.java index ef3e441f..8f6cb655 100644 --- a/src/main/java/com/github/elenterius/biomancy/mixin/ServerGamePacketListenerImplMixin.java +++ b/src/main/java/com/github/elenterius/biomancy/mixin/ServerGamePacketListenerImplMixin.java @@ -3,8 +3,6 @@ import com.github.elenterius.biomancy.init.ModMobEffects; import com.github.elenterius.biomancy.styles.TextStyles; import com.github.elenterius.biomancy.util.ComponentUtil; -import com.github.elenterius.biomancy.util.TransliterationUtil; -import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundRenameItemPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; @@ -13,13 +11,10 @@ import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.function.UnaryOperator; - @Mixin(ServerGamePacketListenerImpl.class) public abstract class ServerGamePacketListenerImplMixin { @@ -36,15 +31,9 @@ private void onHandleRenameItem(ServerboundRenameItemPacket packet, CallbackInfo ItemStack stack = slot.getItem(); if (!stack.hasCustomHoverName()) return; - stack.setHoverName(biomancy$transform(stack.getHoverName())); + stack.setHoverName(ComponentUtil.setStyles(stack.getHoverName(), TextStyles.PRIMORDIAL_RUNES)); } } } - @Unique - private static Component biomancy$transform(Component component) { - Component transliterated = TransliterationUtil.transliterate(component, UnaryOperator.identity()); - return ComponentUtil.setStyles(transliterated, TextStyles.PRIMORDIAL_RUNES); - } - } diff --git a/src/main/java/com/github/elenterius/biomancy/mixin/SignBlockEntityMixin.java b/src/main/java/com/github/elenterius/biomancy/mixin/SignBlockEntityMixin.java index 2d535ad4..ad8ee4d5 100644 --- a/src/main/java/com/github/elenterius/biomancy/mixin/SignBlockEntityMixin.java +++ b/src/main/java/com/github/elenterius/biomancy/mixin/SignBlockEntityMixin.java @@ -2,83 +2,34 @@ import com.github.elenterius.biomancy.init.ModMobEffects; import com.github.elenterius.biomancy.styles.Fonts; -import com.github.elenterius.biomancy.util.ComponentUtil; -import com.github.elenterius.biomancy.util.TransliterationUtil; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.server.network.FilteredText; -import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignText; -import org.apache.commons.lang3.StringUtils; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; @Mixin(SignBlockEntity.class) public abstract class SignBlockEntityMixin { - @Shadow - public abstract int getMaxTextLineWidth(); - - @Inject( - method = "setMessages(Lnet/minecraft/world/entity/player/Player;Ljava/util/List;Lnet/minecraft/world/level/block/entity/SignText;)Lnet/minecraft/world/level/block/entity/SignText;", - at = @At(value = "HEAD"), - cancellable = true - ) - private void onSetMessages(Player player, List filteredText, SignText text, CallbackInfoReturnable cir) { - if (player.hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) { - int maxWidth = biomancy$approximateMaxLineWidth(); - - for (int i = 0; i < filteredText.size(); i++) { - FilteredText filteredtext = filteredText.get(i); - Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle(); - - if (player.isTextFilteringEnabled()) { - text = text.setMessage(i, biomancy$transform(filteredtext.filteredOrEmpty(), maxWidth, style)); - } - else { - text = text.setMessage(i, biomancy$transform(filteredtext.raw(), maxWidth, style), biomancy$transform(filteredtext.filteredOrEmpty(), maxWidth, style)); - } - } - - cir.setReturnValue(text); - } - } - @ModifyExpressionValue( method = "setMessages", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/chat/Component;getStyle()Lnet/minecraft/network/chat/Style;") ) private Style onSetMessagesModifyStyle(Style originalStyle, Player player, List filteredText, SignText text) { - if (originalStyle.getFont().equals(Fonts.CARO_INVITICA)) { - return originalStyle.withFont(null); + if (player.hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) { + return originalStyle.withFont(Fonts.CARO_INVITICA); } - return originalStyle; - } - - @Unique - private static Component biomancy$transform(String text, int maxWidth, Style style) { - String transliterated = TransliterationUtil.transliterate(text); - String abbreviated = StringUtils.abbreviate(transliterated, maxWidth); - if (abbreviated.isBlank()) { - return ComponentUtil.empty(); + if (originalStyle.getFont().equals(Fonts.CARO_INVITICA)) { + return originalStyle.withFont(null); } - return ComponentUtil.literal(abbreviated).setStyle(style.withFont(Fonts.CARO_INVITICA)); - } - - @Unique - private int biomancy$approximateMaxLineWidth() { - return Mth.floor((float) getMaxTextLineWidth() / (Fonts.CARO_INVITICA_GLYPH_WIDTH - 1)); + return originalStyle; } } diff --git a/src/main/java/com/github/elenterius/biomancy/mixin/client/AbstractSignEditScreenMixin.java b/src/main/java/com/github/elenterius/biomancy/mixin/client/AbstractSignEditScreenMixin.java new file mode 100644 index 00000000..71b2ca10 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/mixin/client/AbstractSignEditScreenMixin.java @@ -0,0 +1,58 @@ +package com.github.elenterius.biomancy.mixin.client; + +import com.github.elenterius.biomancy.init.ModMobEffects; +import com.github.elenterius.biomancy.styles.Fonts; +import com.github.elenterius.biomancy.util.TransliterationUtil; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import org.apache.commons.lang3.StringUtils; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(AbstractSignEditScreen.class) +public abstract class AbstractSignEditScreenMixin extends Screen { + + @Shadow + @Final + private String[] messages; + + @Shadow + @Final + private SignBlockEntity sign; + + private AbstractSignEditScreenMixin(Component title) { + super(title); + } + + @Inject(method = "removed", at = @At(value = "HEAD")) + private void onRemoved(CallbackInfo ci) { + if (minecraft == null) return; + if (minecraft.player == null) return; + if (!minecraft.player.hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) return; + + int maxWidth = biomancy$approximateMaxLineWidth(); + for (int i = 0; i < messages.length; i++) { + messages[i] = biomancy$transform(messages[i], maxWidth); + } + } + + @Unique + private static String biomancy$transform(String text, int maxWidth) { + String transliterated = TransliterationUtil.transliterate(text); + return StringUtils.abbreviate(transliterated, maxWidth); + } + + @Unique + private int biomancy$approximateMaxLineWidth() { + return Mth.floor((float) sign.getMaxTextLineWidth() / (Fonts.CARO_INVITICA_GLYPH_WIDTH - 1)); + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/mixin/client/AnvilScreenMixin.java b/src/main/java/com/github/elenterius/biomancy/mixin/client/AnvilScreenMixin.java new file mode 100644 index 00000000..fec1ef53 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/mixin/client/AnvilScreenMixin.java @@ -0,0 +1,38 @@ +package com.github.elenterius.biomancy.mixin.client; + +import com.github.elenterius.biomancy.init.ModMobEffects; +import com.github.elenterius.biomancy.util.TransliterationUtil; +import net.minecraft.client.gui.screens.inventory.AnvilScreen; +import net.minecraft.client.gui.screens.inventory.ItemCombinerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AnvilMenu; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(AnvilScreen.class) +public abstract class AnvilScreenMixin extends ItemCombinerScreen { + + @Shadow + @Final + private Player player; + + private AnvilScreenMixin(AnvilMenu menu, Inventory playerInventory, Component title, ResourceLocation texture) { + super(menu, playerInventory, title, texture); + } + + @ModifyVariable(method = "onNameChanged", at = @At(value = "HEAD"), argsOnly = true) + private String onNameChanged(String text) { + if (menu.getSlot(0).hasItem() && player.hasEffect(ModMobEffects.PRIMORDIAL_INFESTATION.get())) { + return TransliterationUtil.transliterate(text); + } + + return text; + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/util/TransliterationUtil.java b/src/main/java/com/github/elenterius/biomancy/util/TransliterationUtil.java index 7ebba36c..87a83737 100644 --- a/src/main/java/com/github/elenterius/biomancy/util/TransliterationUtil.java +++ b/src/main/java/com/github/elenterius/biomancy/util/TransliterationUtil.java @@ -2,9 +2,15 @@ import com.ibm.icu.text.Transliterator; import net.minecraft.network.chat.Component; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import java.util.function.UnaryOperator; +/** + * The ICU library is only available on the client side + */ +@OnlyIn(Dist.CLIENT) public final class TransliterationUtil { /** @@ -18,10 +24,15 @@ public final class TransliterationUtil { */ private static final String ANY_TO_LATIN_WITHOUT_ACCENTS_TO_ASCII = "Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC; Latin-ASCII;"; - private static final Transliterator ASCII_TRANSLITERATOR = Transliterator.getInstance(ANY_TO_LATIN_WITHOUT_ACCENTS_TO_ASCII); + private static Transliterator ASCII_TRANSLITERATOR; private TransliterationUtil() {} + public static void init() { + //we initialize the Transliterator during the client setup to prevent lag during gameplay + ASCII_TRANSLITERATOR = Transliterator.getInstance(ANY_TO_LATIN_WITHOUT_ACCENTS_TO_ASCII); + } + public static String transliterate(String text) { if (text.isBlank()) return text; return ASCII_TRANSLITERATOR.transliterate(text); diff --git a/src/main/resources/mixins.biomancy.json b/src/main/resources/mixins.biomancy.json index b75a101c..31044d51 100644 --- a/src/main/resources/mixins.biomancy.json +++ b/src/main/resources/mixins.biomancy.json @@ -8,17 +8,17 @@ "defaultRequire": 1 }, "mixins": [ + "AnimalMixin", "AreaEffectCloudMixin", "ArrowMixin", "BlockMixin", "ChickenMixin", "CowMixin", "FlowingFluidMixin", "LivingEntityMixin", + "MobEffectInstanceMixin", "NodeEvaluatorMixin", "PhantomMixin", "PigMixin", "PlayerMixin", "ServerGamePacketListenerImplMixin", "ServerLevelMixin", + "SheepMixin", "SignBlockEntityMixin", "ThrownPotionMixin", "UnbreakingEnchantmentMixin", "VillagerMakeLoveMixin", "VillagerMixin", "WallBlockMixin", "accessor.AgeableMobAccessor", "accessor.ArmorStandAccessor", "accessor.BiomeAccessor", "accessor.CreeperAccessor", "accessor.DamageSourceAccessor", "accessor.EntityAccessor", "accessor.IntegerPropertyAccessor", "accessor.LivingEntityAccessor", "accessor.MobEffectInstanceAccessor", "accessor.MobEntityAccessor", "accessor.ServerLevelAccessor", "accessor.SheepAccessor", "accessor.SlimeAccessor", "accessor.SuspiciousStewItemAccessor", - "accessor.SwordItemMixinAccessor", "accessor.TadpoleAccessor", "accessor.TextureSlotAccessor", "accessor.ZombieVillagerMixinAccessor", - "AnimalMixin", "AreaEffectCloudMixin", "ArrowMixin", "ChickenMixin", "CowMixin", "FlowingFluidMixin", "LivingEntityMixin", "MobEffectInstanceMixin", - "PhantomMixin", "PigMixin", "PlayerMixin", "ServerLevelMixin", "SheepMixin", "ThrownPotionMixin", "UnbreakingEnchantmentMixin", "WallBlockMixin", - "BlockMixin", "NodeEvaluatorMixin", "SignBlockEntityMixin", "ServerGamePacketListenerImplMixin", "VillagerMixin", "VillagerMakeLoveMixin" + "accessor.SwordItemMixinAccessor", "accessor.TadpoleAccessor", "accessor.TextureSlotAccessor", "accessor.ZombieVillagerMixinAccessor" ], "client": [ - "accessor.RecipeCollectionAccessor", "client.ClientPackListenerMixin", "client.ClientRecipeBookMixin", "client.GuiGraphicsMixin", - "client.PlayerRendererMixin" + "accessor.RecipeCollectionAccessor", "client.AbstractSignEditScreenMixin", "client.AnvilScreenMixin", "client.ClientPackListenerMixin", + "client.ClientRecipeBookMixin", "client.GuiGraphicsMixin", "client.PlayerRendererMixin" ], "server": [ ] } \ No newline at end of file