package wtf.hak.survivalfabric.mixin; import com.mojang.authlib.minecraft.client.MinecraftClient; import net.minecraft.network.ClientConnection; import net.minecraft.network.message.MessageType; import net.minecraft.network.message.SignedMessage; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.network.ConnectedClientData; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.world.GameMode; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.config.ConfigManager; import java.awt.*; import java.beans.Expression; import java.util.Objects; import java.util.Set; @Mixin(PlayerManager.class) public abstract class PlayerManagerMixin { @Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")}) public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) { if(ConfigManager.getConfig().joinMessageEnabled && !player.getServer().isSingleplayer()) { Text text = Text.literal(String.format(ConfigManager.getConfig().joinMessage, player.getName().getString())); player.sendMessage(text, false); } } @ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) private Text onPlayerConnect(Text text) { if(ConfigManager.getConfig().joinMessageEnabled) { String name = text.getString().split(" ")[0]; return Text.literal(String.format(ConfigManager.getConfig().joinMessage, name)); } else return text; } @Inject(method = {"remove"}, at = {@At("HEAD")}) public void onPlayerLeave(ServerPlayerEntity player, CallbackInfo ci) { if(SpectatorCommand.spectating.containsKey(player)) { SpectatorCommand.LocationData loc = SpectatorCommand.spectating.remove(player); player.teleport(loc.world, loc.x,loc.y,loc.z, Set.of(), loc.yaw, loc.pitch, false); player.changeGameMode(GameMode.SURVIVAL); } } @Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true) private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) { if(sender != null && ConfigManager.getConfig().chatMessageEnabled) { String rawMessage = message.getContent().getString().trim(); if(sender != null && ConfigManager.getConfig().chatCalcEnabled && rawMessage.endsWith("=")) { String expression = rawMessage.substring(0, rawMessage.length() - 1).trim(); try { String result = String.valueOf(evaluateExpression(expression)); if(rawMessage.contains(" ")) rawMessage += " "; rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result; } catch (Exception e) {} } Text text = Text.literal(String.format(ConfigManager.getConfig().chatMessage, sender.getName().getString(), rawMessage)); sender.getServer().getPlayerManager().broadcast(text, false); ci.cancel(); } else if (sender != null && ConfigManager.getConfig().chatCalcEnabled) { String rawMessage = message.getContent().getString().trim(); if (rawMessage.endsWith("=")) { String expression = rawMessage.substring(0, rawMessage.length() - 1).trim(); try { String result = String.valueOf(evaluateExpression(expression)); if(rawMessage.contains(" ")) rawMessage += " "; rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result; Text formattedMessage = Text.literal("<" + sender.getName().getString() + "> " + rawMessage); sender.getServer().getPlayerManager().broadcast(formattedMessage, false); ci.cancel(); } catch (Exception e) {} } } } private double evaluateExpression(String expression) { return evaluate(expression.replaceAll("\\s", ""), new int[]{0}); } private double evaluate(String expr, int[] index) { double value = parseTerm(expr, index); while (index[0] < expr.length()) { char op = expr.charAt(index[0]); if (op != '+' && op != '-') break; index[0]++; double nextTerm = parseTerm(expr, index); value = (op == '+') ? value + nextTerm : value - nextTerm; } return value; } private double parseTerm(String expr, int[] index) { double value = parseFactor(expr, index); while (index[0] < expr.length()) { char op = expr.charAt(index[0]); if (op != '*' && op != '/') break; index[0]++; double nextFactor = parseFactor(expr, index); value = (op == '*') ? value * nextFactor : value / nextFactor; } return value; } private double parseFactor(String expr, int[] index) { if (expr.charAt(index[0]) == '(') { index[0]++; double value = evaluate(expr, index); index[0]++; // Skip closing ')' return value; } int start = index[0]; while (index[0] < expr.length() && (Character.isDigit(expr.charAt(index[0])) || expr.charAt(index[0]) == '.')) { index[0]++; } return Double.parseDouble(expr.substring(start, index[0])); } }