Spaces:
Build error
Build error
package net.minecraft.client; | |
import com.google.common.collect.Lists; | |
import java.util.List; | |
import java.util.ListIterator; | |
import java.util.Optional; | |
import java.util.function.BiConsumer; | |
import java.util.stream.Collectors; | |
import javax.annotation.Nullable; | |
import net.minecraft.network.chat.FormattedText; | |
import net.minecraft.network.chat.Style; | |
import net.minecraft.util.FormattedCharSequence; | |
import net.minecraft.util.FormattedCharSink; | |
import net.minecraft.util.StringDecomposer; | |
import net.minecraftforge.api.distmarker.Dist; | |
import net.minecraftforge.api.distmarker.OnlyIn; | |
import org.apache.commons.lang3.mutable.MutableFloat; | |
import org.apache.commons.lang3.mutable.MutableInt; | |
import org.apache.commons.lang3.mutable.MutableObject; | |
public class StringSplitter { | |
final StringSplitter.WidthProvider widthProvider; | |
public StringSplitter(StringSplitter.WidthProvider p_92335_) { | |
this.widthProvider = p_92335_; | |
} | |
public float stringWidth( { String p_92354_) | |
if (p_92354_ == null) { | |
return 0.0F; | |
} else { | |
MutableFloat mutablefloat = new MutableFloat(); | |
StringDecomposer.iterateFormatted(p_92354_, Style.EMPTY, (p_92429_, p_92430_, p_92431_) -> { | |
mutablefloat.add(this.widthProvider.getWidth(p_92431_, p_92430_)); | |
return true; | |
}); | |
return mutablefloat.floatValue(); | |
} | |
} | |
public float stringWidth(FormattedText p_92385_) { | |
MutableFloat mutablefloat = new MutableFloat(); | |
StringDecomposer.iterateFormatted(p_92385_, Style.EMPTY, (p_92420_, p_92421_, p_92422_) -> { | |
mutablefloat.add(this.widthProvider.getWidth(p_92422_, p_92421_)); | |
return true; | |
}); | |
return mutablefloat.floatValue(); | |
} | |
public float stringWidth(FormattedCharSequence p_92337_) { | |
MutableFloat mutablefloat = new MutableFloat(); | |
p_92337_.accept((p_92400_, p_92401_, p_92402_) -> { | |
mutablefloat.add(this.widthProvider.getWidth(p_92402_, p_92401_)); | |
return true; | |
}); | |
return mutablefloat.floatValue(); | |
} | |
public int plainIndexAtWidth(String p_92361_, int p_92362_, Style p_92363_) { | |
StringSplitter.WidthLimitedCharSink stringsplitter$widthlimitedcharsink = new StringSplitter.WidthLimitedCharSink((float)p_92362_); | |
StringDecomposer.iterate(p_92361_, p_92363_, stringsplitter$widthlimitedcharsink); | |
return stringsplitter$widthlimitedcharsink.getPosition(); | |
} | |
public String plainHeadByWidth(String p_92411_, int p_92412_, Style p_92413_) { | |
return p_92411_.substring(0, this.plainIndexAtWidth(p_92411_, p_92412_, p_92413_)); | |
} | |
public String plainTailByWidth(String p_92424_, int p_92425_, Style p_92426_) { | |
MutableFloat mutablefloat = new MutableFloat(); | |
MutableInt mutableint = new MutableInt(p_92424_.length()); | |
StringDecomposer.iterateBackwards(p_92424_, p_92426_, (p_92407_, p_92408_, p_92409_) -> { | |
float f = mutablefloat.addAndGet(this.widthProvider.getWidth(p_92409_, p_92408_)); | |
if (f > (float)p_92425_) { | |
return false; | |
} else { | |
mutableint.setValue(p_92407_); | |
return true; | |
} | |
}); | |
return p_92424_.substring(mutableint.intValue()); | |
} | |
public int formattedIndexByWidth(String p_168627_, int p_168628_, Style p_168629_) { | |
StringSplitter.WidthLimitedCharSink stringsplitter$widthlimitedcharsink = new StringSplitter.WidthLimitedCharSink((float)p_168628_); | |
StringDecomposer.iterateFormatted(p_168627_, p_168629_, stringsplitter$widthlimitedcharsink); | |
return stringsplitter$widthlimitedcharsink.getPosition(); | |
} | |
public Style componentStyleAtWidth(FormattedText p_92387_, int p_92388_) { | |
StringSplitter.WidthLimitedCharSink stringsplitter$widthlimitedcharsink = new StringSplitter.WidthLimitedCharSink((float)p_92388_); | |
return p_92387_.<Style>visit( | |
(p_92343_, p_92344_) -> StringDecomposer.iterateFormatted(p_92344_, p_92343_, stringsplitter$widthlimitedcharsink) | |
? Optional.empty() | |
: Optional.of(p_92343_), | |
Style.EMPTY | |
) | |
.orElse(null); | |
} | |
public Style componentStyleAtWidth(FormattedCharSequence p_92339_, int p_92340_) { | |
StringSplitter.WidthLimitedCharSink stringsplitter$widthlimitedcharsink = new StringSplitter.WidthLimitedCharSink((float)p_92340_); | |
MutableObject<Style> mutableobject = new MutableObject<>(); | |
p_92339_.accept((p_92348_, p_92349_, p_92350_) -> { | |
if (!stringsplitter$widthlimitedcharsink.accept(p_92348_, p_92349_, p_92350_)) { | |
mutableobject.setValue(p_92349_); | |
return false; | |
} else { | |
return true; | |
} | |
}); | |
return mutableobject.getValue(); | |
} | |
public String formattedHeadByWidth(String p_168631_, int p_168632_, Style p_168633_) { | |
return p_168631_.substring(0, this.formattedIndexByWidth(p_168631_, p_168632_, p_168633_)); | |
} | |
public FormattedText headByWidth(FormattedText p_92390_, int p_92391_, Style p_92392_) { | |
final StringSplitter.WidthLimitedCharSink stringsplitter$widthlimitedcharsink = new StringSplitter.WidthLimitedCharSink((float)p_92391_); | |
return p_92390_.visit(new FormattedText.StyledContentConsumer<FormattedText>() { | |
private final ComponentCollector collector = new ComponentCollector(); | |
public Optional<FormattedText> accept(Style p_92443_, String p_92444_) { | |
stringsplitter$widthlimitedcharsink.resetPosition(); | |
if (!StringDecomposer.iterateFormatted(p_92444_, p_92443_, stringsplitter$widthlimitedcharsink)) { | |
String s = p_92444_.substring(0, stringsplitter$widthlimitedcharsink.getPosition()); | |
if (!s.isEmpty()) { | |
this.collector.append(FormattedText.of(s, p_92443_)); | |
} | |
return Optional.of(this.collector.getResultOrEmpty()); | |
} else { | |
if (!p_92444_.isEmpty()) { | |
this.collector.append(FormattedText.of(p_92444_, p_92443_)); | |
} | |
return Optional.empty(); | |
} | |
} | |
}, p_92392_).orElse(p_92390_); | |
} | |
public int findLineBreak(String p_168635_, int p_168636_, Style p_168637_) { | |
StringSplitter.LineBreakFinder stringsplitter$linebreakfinder = new StringSplitter.LineBreakFinder((float)p_168636_); | |
StringDecomposer.iterateFormatted(p_168635_, p_168637_, stringsplitter$linebreakfinder); | |
return stringsplitter$linebreakfinder.getSplitPosition(); | |
} | |
public static int getWordPosition(String p_92356_, int p_92357_, int p_92358_, boolean p_92359_) { | |
int i = p_92358_; | |
boolean flag = p_92357_ < 0; | |
int j = Math.abs(p_92357_); | |
for (int k = 0; k < j; k++) { | |
if (flag) { | |
while (p_92359_ && i > 0 && (p_92356_.charAt(i - 1) == ' ' || p_92356_.charAt(i - 1) == '\n')) { | |
i--; | |
} | |
while (i > 0 && p_92356_.charAt(i - 1) != ' ' && p_92356_.charAt(i - 1) != '\n') { | |
i--; | |
} | |
} else { | |
int l = p_92356_.length(); | |
int i1 = p_92356_.indexOf(32, i); | |
int j1 = p_92356_.indexOf(10, i); | |
if (i1 == -1 && j1 == -1) { | |
i = -1; | |
} else if (i1 != -1 && j1 != -1) { | |
i = Math.min(i1, j1); | |
} else if (i1 != -1) { | |
i = i1; | |
} else { | |
i = j1; | |
} | |
if (i == -1) { | |
i = l; | |
} else { | |
while (p_92359_ && i < l && (p_92356_.charAt(i) == ' ' || p_92356_.charAt(i) == '\n')) { | |
i++; | |
} | |
} | |
} | |
} | |
return i; | |
} | |
public void splitLines(String p_92365_, int p_92366_, Style p_92367_, boolean p_92368_, StringSplitter.LinePosConsumer p_92369_) { | |
int i = 0; | |
int j = p_92365_.length(); | |
Style style = p_92367_; | |
while (i < j) { | |
StringSplitter.LineBreakFinder stringsplitter$linebreakfinder = new StringSplitter.LineBreakFinder((float)p_92366_); | |
boolean flag = StringDecomposer.iterateFormatted(p_92365_, i, style, p_92367_, stringsplitter$linebreakfinder); | |
if (flag) { | |
p_92369_.accept(style, i, j); | |
break; | |
} | |
int k = stringsplitter$linebreakfinder.getSplitPosition(); | |
char c0 = p_92365_.charAt(k); | |
int l = c0 != '\n' && c0 != ' ' ? k : k + 1; | |
p_92369_.accept(style, i, p_92368_ ? l : k); | |
i = l; | |
style = stringsplitter$linebreakfinder.getSplitStyle(); | |
} | |
} | |
public List<FormattedText> splitLines(String p_92433_, int p_92434_, Style p_92435_) { | |
List<FormattedText> list = Lists.newArrayList(); | |
this.splitLines( | |
p_92433_, | |
p_92434_, | |
p_92435_, | |
false, | |
(p_92373_, p_92374_, p_92375_) -> list.add(FormattedText.of(p_92433_.substring(p_92374_, p_92375_), p_92373_)) | |
); | |
return list; | |
} | |
public List<FormattedText> splitLines(FormattedText p_92415_, int p_92416_, Style p_92417_) { | |
List<FormattedText> list = Lists.newArrayList(); | |
this.splitLines(p_92415_, p_92416_, p_92417_, (p_92378_, p_92379_) -> list.add(p_92378_)); | |
return list; | |
} | |
public List<FormattedText> splitLines(FormattedText p_168622_, int p_168623_, Style p_168624_, FormattedText p_168625_) { | |
List<FormattedText> list = Lists.newArrayList(); | |
this.splitLines( | |
p_168622_, p_168623_, p_168624_, (p_168619_, p_168620_) -> list.add(p_168620_ ? FormattedText.composite(p_168625_, p_168619_) : p_168619_) | |
); | |
return list; | |
} | |
public void splitLines(FormattedText p_92394_, int p_92395_, Style p_92396_, BiConsumer<FormattedText, Boolean> p_92397_) { | |
List<StringSplitter.LineComponent> list = Lists.newArrayList(); | |
p_92394_.visit((p_92382_, p_92383_) -> { | |
if (!p_92383_.isEmpty()) { | |
list.add(new StringSplitter.LineComponent(p_92383_, p_92382_)); | |
} | |
return Optional.empty(); | |
}, p_92396_); | |
StringSplitter.FlatComponents stringsplitter$flatcomponents = new StringSplitter.FlatComponents(list); | |
boolean flag = true; | |
boolean flag1 = false; | |
boolean flag2 = false; | |
while (flag) { | |
flag = false; | |
StringSplitter.LineBreakFinder stringsplitter$linebreakfinder = new StringSplitter.LineBreakFinder((float)p_92395_); | |
for (StringSplitter.LineComponent stringsplitter$linecomponent : stringsplitter$flatcomponents.parts) { | |
boolean flag3 = StringDecomposer.iterateFormatted( | |
stringsplitter$linecomponent.contents, 0, stringsplitter$linecomponent.style, p_92396_, stringsplitter$linebreakfinder | |
); | |
if (!flag3) { | |
int i = stringsplitter$linebreakfinder.getSplitPosition(); | |
Style style = stringsplitter$linebreakfinder.getSplitStyle(); | |
char c0 = stringsplitter$flatcomponents.charAt(i); | |
boolean flag4 = c0 == '\n'; | |
boolean flag5 = flag4 || c0 == ' '; | |
flag1 = flag4; | |
FormattedText formattedtext = stringsplitter$flatcomponents.splitAt(i, flag5 ? 1 : 0, style); | |
p_92397_.accept(formattedtext, flag2); | |
flag2 = !flag4; | |
flag = true; | |
break; | |
} | |
stringsplitter$linebreakfinder.addToOffset(stringsplitter$linecomponent.contents.length()); | |
} | |
} | |
FormattedText formattedtext1 = stringsplitter$flatcomponents.getRemainder(); | |
if (formattedtext1 != null) { | |
p_92397_.accept(formattedtext1, flag2); | |
} else if (flag1) { | |
p_92397_.accept(FormattedText.EMPTY, false); | |
} | |
} | |
static class FlatComponents { | |
final List<StringSplitter.LineComponent> parts; | |
private String flatParts; | |
public FlatComponents(List<StringSplitter.LineComponent> p_92448_) { | |
this.parts = p_92448_; | |
this.flatParts = p_92448_.stream().map(p_92459_ -> p_92459_.contents).collect(Collectors.joining()); | |
} | |
public char charAt(int p_92451_) { | |
return this.flatParts.charAt(p_92451_); | |
} | |
public FormattedText splitAt(int p_92453_, int p_92454_, Style p_92455_) { | |
ComponentCollector componentcollector = new ComponentCollector(); | |
ListIterator<StringSplitter.LineComponent> listiterator = this.parts.listIterator(); | |
int i = p_92453_; | |
boolean flag = false; | |
while (listiterator.hasNext()) { | |
StringSplitter.LineComponent stringsplitter$linecomponent = listiterator.next(); | |
String s = stringsplitter$linecomponent.contents; | |
int j = s.length(); | |
if (!flag) { | |
if (i > j) { | |
componentcollector.append(stringsplitter$linecomponent); | |
listiterator.remove(); | |
i -= j; | |
} else { | |
String s1 = s.substring(0, i); | |
if (!s1.isEmpty()) { | |
componentcollector.append(FormattedText.of(s1, stringsplitter$linecomponent.style)); | |
} | |
i += p_92454_; | |
flag = true; | |
} | |
} | |
if (flag) { | |
if (i <= j) { | |
String s2 = s.substring(i); | |
if (s2.isEmpty()) { | |
listiterator.remove(); | |
} else { | |
listiterator.set(new StringSplitter.LineComponent(s2, p_92455_)); | |
} | |
break; | |
} | |
listiterator.remove(); | |
i -= j; | |
} | |
} | |
this.flatParts = this.flatParts.substring(p_92453_ + p_92454_); | |
return componentcollector.getResultOrEmpty(); | |
} | |
public FormattedText getRemainder() { | |
ComponentCollector componentcollector = new ComponentCollector(); | |
this.parts.forEach(componentcollector::append); | |
this.parts.clear(); | |
return componentcollector.getResult(); | |
} | |
} | |
class LineBreakFinder implements FormattedCharSink { | |
private final float maxWidth; | |
private int lineBreak = -1; | |
private Style lineBreakStyle = Style.EMPTY; | |
private boolean hadNonZeroWidthChar; | |
private float width; | |
private int lastSpace = -1; | |
private Style lastSpaceStyle = Style.EMPTY; | |
private int nextChar; | |
private int offset; | |
public LineBreakFinder(final float p_92472_) { | |
this.maxWidth = Math.max(p_92472_, 1.0F); | |
} | |
public boolean accept(int p_92480_, Style p_92481_, int p_92482_) { | |
int i = p_92480_ + this.offset; | |
switch (p_92482_) { | |
case 10: | |
return this.finishIteration(i, p_92481_); | |
case 32: | |
this.lastSpace = i; | |
this.lastSpaceStyle = p_92481_; | |
default: | |
float f = StringSplitter.this.widthProvider.getWidth(p_92482_, p_92481_); | |
this.width += f; | |
if (!this.hadNonZeroWidthChar || !(this.width > this.maxWidth)) { | |
this.hadNonZeroWidthChar |= f != 0.0F; | |
this.nextChar = i + Character.charCount(p_92482_); | |
return true; | |
} else { | |
return this.lastSpace != -1 ? this.finishIteration(this.lastSpace, this.lastSpaceStyle) : this.finishIteration(i, p_92481_); | |
} | |
} | |
} | |
private boolean finishIteration(int p_92477_, Style p_92478_) { | |
this.lineBreak = p_92477_; | |
this.lineBreakStyle = p_92478_; | |
return false; | |
} | |
private boolean lineBreakFound() { | |
return this.lineBreak != -1; | |
} | |
public int getSplitPosition() { | |
return this.lineBreakFound() ? this.lineBreak : this.nextChar; | |
} | |
public Style getSplitStyle() { | |
return this.lineBreakStyle; | |
} | |
public void addToOffset(int p_92475_) { | |
this.offset += p_92475_; | |
} | |
} | |
static class LineComponent implements FormattedText { | |
final String contents; | |
final Style style; | |
public LineComponent(String p_92488_, Style p_92489_) { | |
this.contents = p_92488_; | |
this.style = p_92489_; | |
} | |
public <T> Optional<T> visit(FormattedText.ContentConsumer<T> p_92493_) { | |
return p_92493_.accept(this.contents); | |
} | |
public <T> Optional<T> visit(FormattedText.StyledContentConsumer<T> p_92495_, Style p_92496_) { | |
return p_92495_.accept(this.style.applyTo(p_92496_), this.contents); | |
} | |
} | |
public interface LinePosConsumer { | |
void accept(Style p_92500_, int p_92501_, int p_92502_); | |
} | |
class WidthLimitedCharSink implements FormattedCharSink { | |
private float maxWidth; | |
private int position; | |
public WidthLimitedCharSink(final float p_92508_) { | |
this.maxWidth = p_92508_; | |
} | |
public boolean accept(int p_92511_, Style p_92512_, int p_92513_) { | |
this.maxWidth = this.maxWidth - StringSplitter.this.widthProvider.getWidth(p_92513_, p_92512_); | |
if (this.maxWidth >= 0.0F) { | |
this.position = p_92511_ + Character.charCount(p_92513_); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
public int getPosition() { | |
return this.position; | |
} | |
public void resetPosition() { | |
this.position = 0; | |
} | |
} | |
public interface WidthProvider { | |
float getWidth(int p_92516_, Style p_92517_); | |
} | |
} |