Skip to content

Commit

Permalink
fix: fix server crash related to the primordial infestation effect
Browse files Browse the repository at this point in the history
  • Loading branch information
Elenterius committed Sep 15, 2024
1 parent 89da508 commit 3dcdc0a
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -78,6 +79,8 @@ public static void onSetup(final FMLClientSetupEvent event) {

event.enqueueWork(ClientSetupHandler::onPostSetup);

TransliterationUtil.init();

ModsCompatHandler.onBiomancyClientSetup(event);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {

Expand All @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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> filteredText, SignText text, CallbackInfoReturnable<SignText> 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> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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));
}

}
Original file line number Diff line number Diff line change
@@ -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<AnvilMenu> {

@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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

/**
Expand All @@ -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);
Expand Down
12 changes: 6 additions & 6 deletions src/main/resources/mixins.biomancy.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [ ]
}

0 comments on commit 3dcdc0a

Please sign in to comment.