164 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.util;
 | ||
| 
 | ||
| import java.util.Optional;
 | ||
| import net.minecraft.ChatFormatting;
 | ||
| import net.minecraft.network.chat.FormattedText;
 | ||
| import net.minecraft.network.chat.Style;
 | ||
| 
 | ||
| public class StringDecomposer {
 | ||
| 	private static final char REPLACEMENT_CHAR = '<27>';
 | ||
| 	private static final Optional<Object> STOP_ITERATION = Optional.of(Unit.INSTANCE);
 | ||
| 
 | ||
| 	private static boolean feedChar(Style style, FormattedCharSink sink, int position, char character) {
 | ||
| 		return Character.isSurrogate(character) ? sink.accept(position, style, 65533) : sink.accept(position, style, character);
 | ||
| 	}
 | ||
| 
 | ||
| 	public static boolean iterate(String text, Style style, FormattedCharSink sink) {
 | ||
| 		int i = text.length();
 | ||
| 
 | ||
| 		for (int j = 0; j < i; j++) {
 | ||
| 			char c = text.charAt(j);
 | ||
| 			if (Character.isHighSurrogate(c)) {
 | ||
| 				if (j + 1 >= i) {
 | ||
| 					if (!sink.accept(j, style, 65533)) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 					break;
 | ||
| 				}
 | ||
| 
 | ||
| 				char d = text.charAt(j + 1);
 | ||
| 				if (Character.isLowSurrogate(d)) {
 | ||
| 					if (!sink.accept(j, style, Character.toCodePoint(c, d))) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 
 | ||
| 					j++;
 | ||
| 				} else if (!sink.accept(j, style, 65533)) {
 | ||
| 					return false;
 | ||
| 				}
 | ||
| 			} else if (!feedChar(style, sink, j, c)) {
 | ||
| 				return false;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		return true;
 | ||
| 	}
 | ||
| 
 | ||
| 	public static boolean iterateBackwards(String text, Style style, FormattedCharSink sink) {
 | ||
| 		int i = text.length();
 | ||
| 
 | ||
| 		for (int j = i - 1; j >= 0; j--) {
 | ||
| 			char c = text.charAt(j);
 | ||
| 			if (Character.isLowSurrogate(c)) {
 | ||
| 				if (j - 1 < 0) {
 | ||
| 					if (!sink.accept(0, style, 65533)) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 					break;
 | ||
| 				}
 | ||
| 
 | ||
| 				char d = text.charAt(j - 1);
 | ||
| 				if (Character.isHighSurrogate(d)) {
 | ||
| 					if (!sink.accept(--j, style, Character.toCodePoint(d, c))) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 				} else if (!sink.accept(j, style, 65533)) {
 | ||
| 					return false;
 | ||
| 				}
 | ||
| 			} else if (!feedChar(style, sink, j, c)) {
 | ||
| 				return false;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		return true;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Iterate a String while applying legacy formatting codes starting with a {@code §} sign.
 | ||
| 	 */
 | ||
| 	public static boolean iterateFormatted(String text, Style style, FormattedCharSink sink) {
 | ||
| 		return iterateFormatted(text, 0, style, sink);
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Iterate a String while applying legacy formatting codes starting with a {@code §} sign.
 | ||
| 	 * 
 | ||
| 	 * @param skip The amount of characters to skip from the beginning.
 | ||
| 	 */
 | ||
| 	public static boolean iterateFormatted(String text, int skip, Style style, FormattedCharSink sink) {
 | ||
| 		return iterateFormatted(text, skip, style, style, sink);
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Iterate a String while applying legacy formatting codes starting with a {@code §} sign.
 | ||
| 	 * 
 | ||
| 	 * @param skip The amount of character to skip from the beginning.
 | ||
| 	 * @param currentStyle The current style at the starting position after the skip.
 | ||
| 	 * @param defaultStyle The default style for the sequence that should be applied after a reset format code ({@code §r})
 | ||
| 	 */
 | ||
| 	public static boolean iterateFormatted(String text, int skip, Style currentStyle, Style defaultStyle, FormattedCharSink sink) {
 | ||
| 		int i = text.length();
 | ||
| 		Style style = currentStyle;
 | ||
| 
 | ||
| 		for (int j = skip; j < i; j++) {
 | ||
| 			char c = text.charAt(j);
 | ||
| 			if (c == 167) {
 | ||
| 				if (j + 1 >= i) {
 | ||
| 					break;
 | ||
| 				}
 | ||
| 
 | ||
| 				char d = text.charAt(j + 1);
 | ||
| 				ChatFormatting chatFormatting = ChatFormatting.getByCode(d);
 | ||
| 				if (chatFormatting != null) {
 | ||
| 					style = chatFormatting == ChatFormatting.RESET ? defaultStyle : style.applyLegacyFormat(chatFormatting);
 | ||
| 				}
 | ||
| 
 | ||
| 				j++;
 | ||
| 			} else if (Character.isHighSurrogate(c)) {
 | ||
| 				if (j + 1 >= i) {
 | ||
| 					if (!sink.accept(j, style, 65533)) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 					break;
 | ||
| 				}
 | ||
| 
 | ||
| 				char d = text.charAt(j + 1);
 | ||
| 				if (Character.isLowSurrogate(d)) {
 | ||
| 					if (!sink.accept(j, style, Character.toCodePoint(c, d))) {
 | ||
| 						return false;
 | ||
| 					}
 | ||
| 
 | ||
| 					j++;
 | ||
| 				} else if (!sink.accept(j, style, 65533)) {
 | ||
| 					return false;
 | ||
| 				}
 | ||
| 			} else if (!feedChar(style, sink, j, c)) {
 | ||
| 				return false;
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		return true;
 | ||
| 	}
 | ||
| 
 | ||
| 	public static boolean iterateFormatted(FormattedText text, Style style, FormattedCharSink sink) {
 | ||
| 		return text.visit((stylex, string) -> iterateFormatted(string, 0, stylex, sink) ? Optional.empty() : STOP_ITERATION, style).isEmpty();
 | ||
| 	}
 | ||
| 
 | ||
| 	public static String filterBrokenSurrogates(String text) {
 | ||
| 		StringBuilder stringBuilder = new StringBuilder();
 | ||
| 		iterate(text, Style.EMPTY, (i, style, j) -> {
 | ||
| 			stringBuilder.appendCodePoint(j);
 | ||
| 			return true;
 | ||
| 		});
 | ||
| 		return stringBuilder.toString();
 | ||
| 	}
 | ||
| 
 | ||
| 	public static String getPlainText(FormattedText text) {
 | ||
| 		StringBuilder stringBuilder = new StringBuilder();
 | ||
| 		iterateFormatted(text, Style.EMPTY, (i, style, j) -> {
 | ||
| 			stringBuilder.appendCodePoint(j);
 | ||
| 			return true;
 | ||
| 		});
 | ||
| 		return stringBuilder.toString();
 | ||
| 	}
 | ||
| }
 |