Util.java

net.minecraft.util.Util

信息

  • 全限定名:net.minecraft.util.Util
  • 类型:public class
  • 包:net.minecraft.util
  • 源码路径:src/main/java/net/minecraft/util/Util.java
  • 起始行号:L94
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L95
    • 说明:

      TODO

  • DEFAULT_MAX_THREADS

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L96
    • 说明:

      TODO

  • DEFAULT_SAFE_FILE_OPERATION_RETRIES

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L97
    • 说明:

      TODO

  • MAX_THREADS_SYSTEM_PROPERTY

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L98
    • 说明:

      TODO

  • BACKGROUND_EXECUTOR

    • 类型: TracingExecutor
    • 修饰符: private static final
    • 源码定位: L99
    • 说明:

      TODO

  • IO_POOL

    • 类型: TracingExecutor
    • 修饰符: private static final
    • 源码定位: L100
    • 说明:

      TODO

  • DOWNLOAD_POOL

    • 类型: TracingExecutor
    • 修饰符: private static final
    • 源码定位: L101
    • 说明:

      TODO

  • FILENAME_DATE_TIME_FORMATTER

    • 类型: DateTimeFormatter
    • 修饰符: private static final
    • 源码定位: L102
    • 说明:

      TODO

  • LINEAR_LOOKUP_THRESHOLD

    • 类型: int
    • 修饰符: public static final
    • 源码定位: L103
    • 说明:

      TODO

  • ALLOWED_UNTRUSTED_LINK_PROTOCOLS

    • 类型: Set<String>
    • 修饰符: private static final
    • 源码定位: L104
    • 说明:

      TODO

  • NANOS_PER_MILLI

    • 类型: long
    • 修饰符: public static final
    • 源码定位: L105
    • 说明:

      TODO

  • timeSource

    • 类型: TimeSource.NanoTimeSource
    • 修饰符: public static
    • 源码定位: L106
    • 说明:

      TODO

  • TICKER

    • 类型: Ticker
    • 修饰符: public static final public
    • 源码定位: L107
    • 说明:

      TODO

  • NIL_UUID

    • 类型: UUID
    • 修饰符: public static final
    • 源码定位: L113
    • 说明:

      TODO

  • ZIP_FILE_SYSTEM_PROVIDER

    • 类型: FileSystemProvider
    • 修饰符: public static final
    • 源码定位: L114
    • 说明:

      TODO

  • thePauser

    • 类型: Consumer<String>
    • 修饰符: private static
    • 源码定位: L119
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.util.Util.OS
    • 类型: enum
    • 修饰符: public static
    • 源码定位: L1125
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public static <K,V> Collector<Entry<?extends K,?extends V>,?,Map<K,V>> toMap() @ L121

  • 方法名:toMap
  • 源码定位:L121
  • 返回类型:<K,V> Collector<Entry<?extends K,?extends V>,?,Map<K,V>>
  • 修饰符:public static

参数:

说明:

TODO

public static <T> Collector<T,?,List<T>> toMutableList() @ L125

  • 方法名:toMutableList
  • 源码定位:L125
  • 返回类型: Collector<T,?,List>
  • 修饰符:public static

参数:

说明:

TODO

public static <T extends Comparable<T>> String getPropertyName(Property<T> key, Object value) @ L129

  • 方法名:getPropertyName
  • 源码定位:L129
  • 返回类型:<T extends Comparable> String
  • 修饰符:public static

参数:

  • key: Property
  • value: Object

说明:

TODO

public static String makeDescriptionId(String prefix, Identifier location) @ L133

  • 方法名:makeDescriptionId
  • 源码定位:L133
  • 返回类型:String
  • 修饰符:public static

参数:

  • prefix: String
  • location: Identifier

说明:

TODO

public static long getMillis() @ L137

  • 方法名:getMillis
  • 源码定位:L137
  • 返回类型:long
  • 修饰符:public static

参数:

说明:

TODO

public static long getNanos() @ L141

  • 方法名:getNanos
  • 源码定位:L141
  • 返回类型:long
  • 修饰符:public static

参数:

说明:

TODO

public static long getEpochMillis() @ L145

  • 方法名:getEpochMillis
  • 源码定位:L145
  • 返回类型:long
  • 修饰符:public static

参数:

说明:

TODO

public static String getFilenameFormattedDateTime() @ L149

  • 方法名:getFilenameFormattedDateTime
  • 源码定位:L149
  • 返回类型:String
  • 修饰符:public static

参数:

说明:

TODO

private static TracingExecutor makeExecutor(String name) @ L153

  • 方法名:makeExecutor
  • 源码定位:L153
  • 返回类型:TracingExecutor
  • 修饰符:private static

参数:

  • name: String

说明:

TODO

public static int maxAllowedExecutorThreads() @ L188

  • 方法名:maxAllowedExecutorThreads
  • 源码定位:L188
  • 返回类型:int
  • 修饰符:public static

参数:

说明:

TODO

private static int getMaxThreads() @ L192

  • 方法名:getMaxThreads
  • 源码定位:L192
  • 返回类型:int
  • 修饰符:private static

参数:

说明:

TODO

public static TracingExecutor backgroundExecutor() @ L210

  • 方法名:backgroundExecutor
  • 源码定位:L210
  • 返回类型:TracingExecutor
  • 修饰符:public static

参数:

说明:

TODO

public static TracingExecutor ioPool() @ L214

  • 方法名:ioPool
  • 源码定位:L214
  • 返回类型:TracingExecutor
  • 修饰符:public static

参数:

说明:

TODO

public static TracingExecutor nonCriticalIoPool() @ L218

  • 方法名:nonCriticalIoPool
  • 源码定位:L218
  • 返回类型:TracingExecutor
  • 修饰符:public static

参数:

说明:

TODO

public static void shutdownExecutors() @ L222

  • 方法名:shutdownExecutors
  • 源码定位:L222
  • 返回类型:void
  • 修饰符:public static

参数:

说明:

TODO

private static TracingExecutor makeIoExecutor(String prefix, boolean daemon) @ L227

  • 方法名:makeIoExecutor
  • 源码定位:L227
  • 返回类型:TracingExecutor
  • 修饰符:private static

参数:

  • prefix: String
  • daemon: boolean

说明:

TODO

public static void throwAsRuntime(Throwable throwable) @ L240

  • 方法名:throwAsRuntime
  • 源码定位:L240
  • 返回类型:void
  • 修饰符:public static

参数:

  • throwable: Throwable

说明:

TODO

private static void onThreadException(Thread thread, Throwable throwable) @ L244

  • 方法名:onThreadException
  • 源码定位:L244
  • 返回类型:void
  • 修饰符:private static

参数:

  • thread: Thread
  • throwable: Throwable

说明:

TODO

public static Type<?> fetchChoiceType(TypeReference reference, String name) @ L263

  • 方法名:fetchChoiceType
  • 源码定位:L263
  • 返回类型:Type<?>
  • 修饰符:public static

参数:

  • reference: TypeReference
  • name: String

说明:

TODO

private static Type<?> doFetchChoiceType(TypeReference reference, String name) @ L267

  • 方法名:doFetchChoiceType
  • 源码定位:L267
  • 返回类型:Type<?>
  • 修饰符:private static

参数:

  • reference: TypeReference
  • name: String

说明:

TODO

public static void runNamed(Runnable runnable, String name) @ L284

  • 方法名:runNamed
  • 源码定位:L284
  • 返回类型:void
  • 修饰符:public static

参数:

  • runnable: Runnable
  • name: String

说明:

TODO

public static <T> String getRegisteredName(Registry<T> registry, T entry) @ L302

  • 方法名:getRegisteredName
  • 源码定位:L302
  • 返回类型: String
  • 修饰符:public static

参数:

  • registry: Registry
  • entry: T

说明:

TODO

public static <T> Predicate<T> allOf() @ L307

  • 方法名:allOf
  • 源码定位:L307
  • 返回类型: Predicate
  • 修饰符:public static

参数:

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T> condition) @ L311

  • 方法名:allOf
  • 源码定位:L311
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T> condition1, Predicate<?super T> condition2) @ L315

  • 方法名:allOf
  • 源码定位:L315
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3) @ L319

  • 方法名:allOf
  • 源码定位:L319
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3, Predicate<?super T> condition4) @ L323

  • 方法名:allOf
  • 源码定位:L323
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>
  • condition4: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3, Predicate<?super T> condition4, Predicate<?super T> condition5) @ L329

  • 方法名:allOf
  • 源码定位:L329
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>
  • condition4: Predicate<?super T>
  • condition5: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> allOf(Predicate<?super T>... conditions) @ L343

  • 方法名:allOf
  • 源码定位:L343
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • conditions: Predicate<?super T>…

说明:

TODO

public static <T> Predicate<T> allOf(List<?extends Predicate<?super T>> conditions) @ L356

  • 方法名:allOf
  • 源码定位:L356
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • conditions: List<?extends Predicate<?super T>>

说明:

TODO

public static <T> Predicate<T> anyOf() @ L382

  • 方法名:anyOf
  • 源码定位:L382
  • 返回类型: Predicate
  • 修饰符:public static

参数:

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T> condition1) @ L386

  • 方法名:anyOf
  • 源码定位:L386
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T> condition1, Predicate<?super T> condition2) @ L390

  • 方法名:anyOf
  • 源码定位:L390
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3) @ L394

  • 方法名:anyOf
  • 源码定位:L394
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3, Predicate<?super T> condition4) @ L398

  • 方法名:anyOf
  • 源码定位:L398
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>
  • condition4: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T> condition1, Predicate<?super T> condition2, Predicate<?super T> condition3, Predicate<?super T> condition4, Predicate<?super T> condition5) @ L404

  • 方法名:anyOf
  • 源码定位:L404
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • condition1: Predicate<?super T>
  • condition2: Predicate<?super T>
  • condition3: Predicate<?super T>
  • condition4: Predicate<?super T>
  • condition5: Predicate<?super T>

说明:

TODO

public static <T> Predicate<T> anyOf(Predicate<?super T>... conditions) @ L418

  • 方法名:anyOf
  • 源码定位:L418
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • conditions: Predicate<?super T>…

说明:

TODO

public static <T> Predicate<T> anyOf(List<?extends Predicate<?super T>> conditions) @ L431

  • 方法名:anyOf
  • 源码定位:L431
  • 返回类型: Predicate
  • 修饰符:public static

参数:

  • conditions: List<?extends Predicate<?super T>>

说明:

TODO

public static <T> boolean isSymmetrical(int width, int height, List<T> ingredients) @ L457

  • 方法名:isSymmetrical
  • 源码定位:L457
  • 返回类型: boolean
  • 修饰符:public static

参数:

  • width: int
  • height: int
  • ingredients: List

说明:

TODO

public static int growByHalf(int currentSize, int minimalNewSize) @ L478

  • 方法名:growByHalf
  • 源码定位:L478
  • 返回类型:int
  • 修饰符:public static

参数:

  • currentSize: int
  • minimalNewSize: int

说明:

TODO

public static DateTimeFormatter localizedDateFormatter(FormatStyle formatStyle) @ L482

  • 方法名:localizedDateFormatter
  • 源码定位:L482
  • 返回类型:DateTimeFormatter
  • 修饰符:public static

参数:

  • formatStyle: FormatStyle

说明:

TODO

public static Util.OS getPlatform() @ L487

  • 方法名:getPlatform
  • 源码定位:L487
  • 返回类型:Util.OS
  • 修饰符:public static

参数:

说明:

TODO

public static boolean isAarch64() @ L504

  • 方法名:isAarch64
  • 源码定位:L504
  • 返回类型:boolean
  • 修饰符:public static

参数:

说明:

TODO

public static URI parseAndValidateUntrustedUri(String uri) @ L509

  • 方法名:parseAndValidateUntrustedUri
  • 源码定位:L509
  • 返回类型:URI
  • 修饰符:public static

参数:

  • uri: String

说明:

TODO

public static <T> T findNextInIterable(Iterable<T> collection, T current) @ L524

  • 方法名:findNextInIterable
  • 源码定位:L524
  • 返回类型: T
  • 修饰符:public static

参数:

  • collection: Iterable
  • current: T

说明:

TODO

public static <T> T findPreviousInIterable(Iterable<T> collection, T current) @ L544

  • 方法名:findPreviousInIterable
  • 源码定位:L544
  • 返回类型: T
  • 修饰符:public static

参数:

  • collection: Iterable
  • current: T

说明:

TODO

public static <T> T make(Supplier<T> factory) @ L563

  • 方法名:make
  • 源码定位:L563
  • 返回类型: T
  • 修饰符:public static

参数:

  • factory: Supplier

说明:

TODO

public static <T> T make(T t, Consumer<?super T> consumer) @ L567

  • 方法名:make
  • 源码定位:L567
  • 返回类型: T
  • 修饰符:public static

参数:

  • t: T
  • consumer: Consumer<?super T>

说明:

TODO

public static <K extends Enum<K>,V> Map<K,V> makeEnumMap(Class<K> keyType, Function<K,V> function) @ L572

  • 方法名:makeEnumMap
  • 源码定位:L572
  • 返回类型:<K extends Enum,V> Map<K,V>
  • 修饰符:public static

参数:

  • keyType: Class
  • function: Function<K,V>

说明:

TODO

public static <K,V1,V2> Map<K,V2> mapValues(Map<K,V1> map, Function<?super V1,V2> valueMapper) @ L582

  • 方法名:mapValues
  • 源码定位:L582
  • 返回类型:<K,V1,V2> Map<K,V2>
  • 修饰符:public static

参数:

  • map: Map<K,V1>
  • valueMapper: Function<?super V1,V2>

说明:

TODO

public static <K,V1,V2> Map<K,V2> mapValuesLazy(Map<K,V1> map, com.google.common.base.Function<V1,V2> valueMapper) @ L586

  • 方法名:mapValuesLazy
  • 源码定位:L586
  • 返回类型:<K,V1,V2> Map<K,V2>
  • 修饰符:public static

参数:

  • map: Map<K,V1>
  • valueMapper: com.google.common.base.Function<V1,V2>

说明:

TODO

public static <T extends Enum<T>> Set<T> allOfEnumExcept(T value) @ L590

  • 方法名:allOfEnumExcept
  • 源码定位:L590
  • 返回类型:<T extends Enum> Set
  • 修饰符:public static

参数:

  • value: T

说明:

TODO

public static <V> CompletableFuture<List<V>> sequence(List<?extends CompletableFuture<V>> futures) @ L594

  • 方法名:sequence
  • 源码定位:L594
  • 返回类型: CompletableFuture<List>
  • 修饰符:public static

参数:

  • futures: List<?extends CompletableFuture>

说明:

TODO

public static <V> CompletableFuture<List<V>> sequenceFailFast(List<?extends CompletableFuture<?extends V>> futures) @ L605

  • 方法名:sequenceFailFast
  • 源码定位:L605
  • 返回类型: CompletableFuture<List>
  • 修饰符:public static

参数:

  • futures: List<?extends CompletableFuture<?extends V>>

说明:

TODO

public static <V> CompletableFuture<List<V>> sequenceFailFastAndCancel(List<?extends CompletableFuture<?extends V>> futures) @ L610

  • 方法名:sequenceFailFastAndCancel
  • 源码定位:L610
  • 返回类型: CompletableFuture<List>
  • 修饰符:public static

参数:

  • futures: List<?extends CompletableFuture<?extends V>>

说明:

TODO

private static <V> CompletableFuture<List<V>> fallibleSequence(List<?extends CompletableFuture<?extends V>> futures, Consumer<Throwable> failureHandler) @ L621

  • 方法名:fallibleSequence
  • 源码定位:L621
  • 返回类型: CompletableFuture<List>
  • 修饰符:private static

参数:

  • futures: List<?extends CompletableFuture<?extends V>>
  • failureHandler: Consumer

说明:

TODO

public static <T> Optional<T> ifElse(Optional<T> input, Consumer<T> onTrue, Runnable onFalse) @ L640

  • 方法名:ifElse
  • 源码定位:L640
  • 返回类型: Optional
  • 修饰符:public static

参数:

  • input: Optional
  • onTrue: Consumer
  • onFalse: Runnable

说明:

TODO

public static <T> Supplier<T> name(Supplier<T> task, Supplier<String> nameGetter) @ L650

  • 方法名:name
  • 源码定位:L650
  • 返回类型: Supplier
  • 修饰符:public static

参数:

  • task: Supplier
  • nameGetter: Supplier

说明:

TODO

public static Runnable name(Runnable task, Supplier<String> nameGetter) @ L669

  • 方法名:name
  • 源码定位:L669
  • 返回类型:Runnable
  • 修饰符:public static

参数:

  • task: Runnable
  • nameGetter: Supplier

说明:

TODO

public static void logAndPauseIfInIde(String message) @ L688

  • 方法名:logAndPauseIfInIde
  • 源码定位:L688
  • 返回类型:void
  • 修饰符:public static

参数:

  • message: String

说明:

TODO

public static void logAndPauseIfInIde(String message, Throwable throwable) @ L695

  • 方法名:logAndPauseIfInIde
  • 源码定位:L695
  • 返回类型:void
  • 修饰符:public static

参数:

  • message: String
  • throwable: Throwable

说明:

TODO

public static <T extends Throwable> T pauseInIde(T t) @ L702

  • 方法名:pauseInIde
  • 源码定位:L702
  • 返回类型: T
  • 修饰符:public static

参数:

  • t: T

说明:

TODO

public static void setPause(Consumer<String> pauseFunction) @ L711

  • 方法名:setPause
  • 源码定位:L711
  • 返回类型:void
  • 修饰符:public static

参数:

  • pauseFunction: Consumer

说明:

TODO

private static void doPause(String message) @ L715

  • 方法名:doPause
  • 源码定位:L715
  • 返回类型:void
  • 修饰符:private static

参数:

  • message: String

说明:

TODO

public static String describeError(Throwable err) @ L724

  • 方法名:describeError
  • 源码定位:L724
  • 返回类型:String
  • 修饰符:public static

参数:

  • err: Throwable

说明:

TODO

public static <T> T getRandom(T[] array, RandomSource random) @ L732

  • 方法名:getRandom
  • 源码定位:L732
  • 返回类型: T
  • 修饰符:public static

参数:

  • array: T[]
  • random: RandomSource

说明:

TODO

public static int getRandom(int[] array, RandomSource random) @ L736

  • 方法名:getRandom
  • 源码定位:L736
  • 返回类型:int
  • 修饰符:public static

参数:

  • array: int[]
  • random: RandomSource

说明:

TODO

public static <T> T getRandom(List<T> list, RandomSource random) @ L740

  • 方法名:getRandom
  • 源码定位:L740
  • 返回类型: T
  • 修饰符:public static

参数:

  • list: List
  • random: RandomSource

说明:

TODO

public static <T> Optional<T> getRandomSafe(List<T> list, RandomSource random) @ L744

  • 方法名:getRandomSafe
  • 源码定位:L744
  • 返回类型: Optional
  • 修饰符:public static

参数:

  • list: List
  • random: RandomSource

说明:

TODO

private static BooleanSupplier createRenamer(Path from, Path to, CopyOption... options) @ L748

  • 方法名:createRenamer
  • 源码定位:L748
  • 返回类型:BooleanSupplier
  • 修饰符:private static

参数:

  • from: Path
  • to: Path
  • options: CopyOption…

说明:

TODO

private static BooleanSupplier createDeleter(Path target) @ L768

  • 方法名:createDeleter
  • 源码定位:L768
  • 返回类型:BooleanSupplier
  • 修饰符:private static

参数:

  • target: Path

说明:

TODO

private static BooleanSupplier createFileDeletedCheck(Path target) @ L788

  • 方法名:createFileDeletedCheck
  • 源码定位:L788
  • 返回类型:BooleanSupplier
  • 修饰符:private static

参数:

  • target: Path

说明:

TODO

private static BooleanSupplier createFileCreatedCheck(Path target) @ L802

  • 方法名:createFileCreatedCheck
  • 源码定位:L802
  • 返回类型:BooleanSupplier
  • 修饰符:private static

参数:

  • target: Path

说明:

TODO

private static boolean executeInSequence(BooleanSupplier... operations) @ L816

  • 方法名:executeInSequence
  • 源码定位:L816
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • operations: BooleanSupplier…

说明:

TODO

private static boolean runWithRetries(int numberOfRetries, String description, BooleanSupplier... operations) @ L827

  • 方法名:runWithRetries
  • 源码定位:L827
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • numberOfRetries: int
  • description: String
  • operations: BooleanSupplier…

说明:

TODO

public static boolean safeMoveFile(Path fromPath, Path toPath, CopyOption... options) @ L840

  • 方法名:safeMoveFile
  • 源码定位:L840
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • fromPath: Path
  • toPath: Path
  • options: CopyOption…

说明:

TODO

public static void safeReplaceFile(Path targetPath, Path newPath, Path backupPath) @ L844

  • 方法名:safeReplaceFile
  • 源码定位:L844
  • 返回类型:void
  • 修饰符:public static

参数:

  • targetPath: Path
  • newPath: Path
  • backupPath: Path

说明:

TODO

public static boolean safeReplaceOrMoveFile(Path targetPath, Path newPath, Path backupPath, boolean noRollback) @ L848

  • 方法名:safeReplaceOrMoveFile
  • 源码定位:L848
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • targetPath: Path
  • newPath: Path
  • backupPath: Path
  • noRollback: boolean

说明:

TODO

public static int offsetByCodepoints(String input, int pos, int offset) @ L865

  • 方法名:offsetByCodepoints
  • 源码定位:L865
  • 返回类型:int
  • 修饰符:public static

参数:

  • input: String
  • pos: int
  • offset: int

说明:

TODO

public static Consumer<String> prefix(String prefix, Consumer<String> consumer) @ L885

  • 方法名:prefix
  • 源码定位:L885
  • 返回类型:Consumer
  • 修饰符:public static

参数:

  • prefix: String
  • consumer: Consumer

说明:

TODO

public static DataResult<int[]> fixedSize(IntStream stream, int size) @ L889

  • 方法名:fixedSize
  • 源码定位:L889
  • 返回类型:DataResult<int[]>
  • 修饰符:public static

参数:

  • stream: IntStream
  • size: int

说明:

TODO

public static DataResult<long[]> fixedSize(LongStream stream, int size) @ L899

  • 方法名:fixedSize
  • 源码定位:L899
  • 返回类型:DataResult<long[]>
  • 修饰符:public static

参数:

  • stream: LongStream
  • size: int

说明:

TODO

public static <T> DataResult<List<T>> fixedSize(List<T> list, int size) @ L909

  • 方法名:fixedSize
  • 源码定位:L909
  • 返回类型: DataResult<List>
  • 修饰符:public static

参数:

  • list: List
  • size: int

说明:

TODO

public static void startTimerHackThread() @ L918

  • 方法名:startTimerHackThread
  • 源码定位:L918
  • 返回类型:void
  • 修饰符:public static

参数:

说明:

TODO

public static void copyBetweenDirs(Path sourceDir, Path targetDir, Path sourcePath) @ L937

  • 方法名:copyBetweenDirs
  • 源码定位:L937
  • 返回类型:void
  • 修饰符:public static

参数:

  • sourceDir: Path
  • targetDir: Path
  • sourcePath: Path

说明:

TODO

public static String sanitizeName(String value, CharPredicate isAllowedChar) @ L943

  • 方法名:sanitizeName
  • 源码定位:L943
  • 返回类型:String
  • 修饰符:public static

参数:

  • value: String
  • isAllowedChar: CharPredicate

说明:

TODO

public static <K,V> SingleKeyCache<K,V> singleKeyCache(Function<K,V> computeValueFunction) @ L950

  • 方法名:singleKeyCache
  • 源码定位:L950
  • 返回类型:<K,V> SingleKeyCache<K,V>
  • 修饰符:public static

参数:

  • computeValueFunction: Function<K,V>

说明:

TODO

public static <T,R> Function<T,R> memoize(Function<T,R> function) @ L954

  • 方法名:memoize
  • 源码定位:L954
  • 返回类型:<T,R> Function<T,R>
  • 修饰符:public static

参数:

  • function: Function<T,R>

说明:

TODO

public static <T,U,R> BiFunction<T,U,R> memoize(BiFunction<T,U,R> function) @ L970

  • 方法名:memoize
  • 源码定位:L970
  • 返回类型:<T,U,R> BiFunction<T,U,R>
  • 修饰符:public static

参数:

  • function: BiFunction<T,U,R>

说明:

TODO

public static <T> List<T> toShuffledList(Stream<T> stream, RandomSource random) @ L986

  • 方法名:toShuffledList
  • 源码定位:L986
  • 返回类型: List
  • 修饰符:public static

参数:

  • stream: Stream
  • random: RandomSource

说明:

TODO

public static IntArrayList toShuffledList(IntStream stream, RandomSource random) @ L992

  • 方法名:toShuffledList
  • 源码定位:L992
  • 返回类型:IntArrayList
  • 修饰符:public static

参数:

  • stream: IntStream
  • random: RandomSource

说明:

TODO

public static <T> List<T> shuffledCopy(T[] array, RandomSource random) @ L1004

  • 方法名:shuffledCopy
  • 源码定位:L1004
  • 返回类型: List
  • 修饰符:public static

参数:

  • array: T[]
  • random: RandomSource

说明:

TODO

public static <T> List<T> shuffledCopy(ObjectArrayList<T> list, RandomSource random) @ L1010

  • 方法名:shuffledCopy
  • 源码定位:L1010
  • 返回类型: List
  • 修饰符:public static

参数:

  • list: ObjectArrayList
  • random: RandomSource

说明:

TODO

public static <T> void shuffle(List<T> list, RandomSource random) @ L1016

  • 方法名:shuffle
  • 源码定位:L1016
  • 返回类型: void
  • 修饰符:public static

参数:

  • list: List
  • random: RandomSource

说明:

TODO

public static <T> CompletableFuture<T> blockUntilDone(Function<Executor,CompletableFuture<T>> task) @ L1025

  • 方法名:blockUntilDone
  • 源码定位:L1025
  • 返回类型: CompletableFuture
  • 修饰符:public static

参数:

  • task: Function<Executor,CompletableFuture>

说明:

TODO

public static <T> T blockUntilDone(Function<Executor,T> task, Predicate<T> completionCheck) @ L1029

  • 方法名:blockUntilDone
  • 源码定位:L1029
  • 返回类型: T
  • 修饰符:public static

参数:

  • task: Function<Executor,T>
  • completionCheck: Predicate

说明:

TODO

public static <T> ToIntFunction<T> createIndexLookup(List<T> values) @ L1053

  • 方法名:createIndexLookup
  • 源码定位:L1053
  • 返回类型: ToIntFunction
  • 修饰符:public static

参数:

  • values: List

说明:

TODO

public static <T> ToIntFunction<T> createIndexIdentityLookup(List<T> values) @ L1069

  • 方法名:createIndexIdentityLookup
  • 源码定位:L1069
  • 返回类型: ToIntFunction
  • 修饰符:public static

参数:

  • values: List

说明:

TODO

public static <A,B> Typed<B> writeAndReadTypedOrThrow(Typed<A> typed, Type<B> newType, UnaryOperator<Dynamic<?>> function) @ L1086

  • 方法名:writeAndReadTypedOrThrow
  • 源码定位:L1086
  • 返回类型:<A,B> Typed
  • 修饰符:public static

参数:

说明:

TODO

public static <T> Typed<T> readTypedOrThrow(Type<T> type, Dynamic<?> dynamic) @ L1091

  • 方法名:readTypedOrThrow
  • 源码定位:L1091
  • 返回类型: Typed
  • 修饰符:public static

参数:

  • type: Type
  • dynamic: Dynamic<?>

说明:

TODO

public static <T> Typed<T> readTypedOrThrow(Type<T> type, Dynamic<?> dynamic, boolean acceptPartial) @ L1095

  • 方法名:readTypedOrThrow
  • 源码定位:L1095
  • 返回类型: Typed
  • 修饰符:public static

参数:

  • type: Type
  • dynamic: Dynamic<?>
  • acceptPartial: boolean

说明:

TODO

public static <T> List<T> copyAndAdd(List<T> list, T element) @ L1109

  • 方法名:copyAndAdd
  • 源码定位:L1109
  • 返回类型: List
  • 修饰符:public static

参数:

  • list: List
  • element: T

说明:

TODO

public static <T> List<T> copyAndAdd(List<T> list, T... elements) @ L1113

  • 方法名:copyAndAdd
  • 源码定位:L1113
  • 返回类型: List
  • 修饰符:public static

参数:

  • list: List
  • elements: T…

说明:

TODO

public static <T> List<T> copyAndAdd(T element, List<T> list) @ L1117

  • 方法名:copyAndAdd
  • 源码定位:L1117
  • 返回类型: List
  • 修饰符:public static

参数:

  • element: T
  • list: List

说明:

TODO

public static <K,V> Map<K,V> copyAndPut(Map<K,V> map, K key, V value) @ L1121

  • 方法名:copyAndPut
  • 源码定位:L1121
  • 返回类型:<K,V> Map<K,V>
  • 修饰符:public static

参数:

  • map: Map<K,V>
  • key: K
  • value: V

说明:

TODO

代码

public class Util {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final int DEFAULT_MAX_THREADS = 255;
    private static final int DEFAULT_SAFE_FILE_OPERATION_RETRIES = 10;
    private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
    private static final TracingExecutor BACKGROUND_EXECUTOR = makeExecutor("Main");
    private static final TracingExecutor IO_POOL = makeIoExecutor("IO-Worker-", false);
    private static final TracingExecutor DOWNLOAD_POOL = makeIoExecutor("Download-", true);
    private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT);
    public static final int LINEAR_LOOKUP_THRESHOLD = 8;
    private static final Set<String> ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https");
    public static final long NANOS_PER_MILLI = 1000000L;
    public static TimeSource.NanoTimeSource timeSource = System::nanoTime;
    public static final Ticker TICKER = new Ticker() {
        @Override
        public long read() {
            return Util.timeSource.getAsLong();
        }
    };
    public static final UUID NIL_UUID = new UUID(0L, 0L);
    public static final FileSystemProvider ZIP_FILE_SYSTEM_PROVIDER = FileSystemProvider.installedProviders()
        .stream()
        .filter(p -> p.getScheme().equalsIgnoreCase("jar"))
        .findFirst()
        .orElseThrow(() -> new IllegalStateException("No jar file system provider found"));
    private static Consumer<String> thePauser = msg -> {};
 
    public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> toMap() {
        return Collectors.toMap(Entry::getKey, Entry::getValue);
    }
 
    public static <T> Collector<T, ?, List<T>> toMutableList() {
        return Collectors.toCollection(Lists::newArrayList);
    }
 
    public static <T extends Comparable<T>> String getPropertyName(Property<T> key, Object value) {
        return key.getName((T)value);
    }
 
    public static String makeDescriptionId(String prefix, @Nullable Identifier location) {
        return location == null ? prefix + ".unregistered_sadface" : prefix + "." + location.getNamespace() + "." + location.getPath().replace('/', '.');
    }
 
    public static long getMillis() {
        return getNanos() / 1000000L;
    }
 
    public static long getNanos() {
        return timeSource.getAsLong();
    }
 
    public static long getEpochMillis() {
        return Instant.now().toEpochMilli();
    }
 
    public static String getFilenameFormattedDateTime() {
        return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
    }
 
    private static TracingExecutor makeExecutor(String name) {
        int threads = maxAllowedExecutorThreads();
        ExecutorService executor;
        if (threads <= 0) {
            executor = MoreExecutors.newDirectExecutorService();
        } else {
            AtomicInteger workerCount = new AtomicInteger(1);
            executor = new ForkJoinPool(threads, pool -> {
                final String threadName = "Worker-" + name + "-" + workerCount.getAndIncrement();
                ForkJoinWorkerThread thread = new ForkJoinWorkerThread(pool) {
                    @Override
                    protected void onStart() {
                        TracyClient.setThreadName(threadName, name.hashCode());
                        super.onStart();
                    }
 
                    @Override
                    protected void onTermination(@Nullable Throwable exception) {
                        if (exception != null) {
                            Util.LOGGER.warn("{} died", this.getName(), exception);
                        } else {
                            Util.LOGGER.debug("{} shutdown", this.getName());
                        }
 
                        super.onTermination(exception);
                    }
                };
                thread.setName(threadName);
                return thread;
            }, Util::onThreadException, true);
        }
 
        return new TracingExecutor(executor);
    }
 
    public static int maxAllowedExecutorThreads() {
        return Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads());
    }
 
    private static int getMaxThreads() {
        String maxThreadsString = System.getProperty("max.bg.threads");
        if (maxThreadsString != null) {
            try {
                int maxThreads = Integer.parseInt(maxThreadsString);
                if (maxThreads >= 1 && maxThreads <= 255) {
                    return maxThreads;
                }
 
                LOGGER.error("Wrong {} property value '{}'. Should be an integer value between 1 and {}.", "max.bg.threads", maxThreadsString, 255);
            } catch (NumberFormatException var2) {
                LOGGER.error("Could not parse {} property value '{}'. Should be an integer value between 1 and {}.", "max.bg.threads", maxThreadsString, 255);
            }
        }
 
        return 255;
    }
 
    public static TracingExecutor backgroundExecutor() {
        return BACKGROUND_EXECUTOR;
    }
 
    public static TracingExecutor ioPool() {
        return IO_POOL;
    }
 
    public static TracingExecutor nonCriticalIoPool() {
        return DOWNLOAD_POOL;
    }
 
    public static void shutdownExecutors() {
        BACKGROUND_EXECUTOR.shutdownAndAwait(3L, TimeUnit.SECONDS);
        IO_POOL.shutdownAndAwait(3L, TimeUnit.SECONDS);
    }
 
    private static TracingExecutor makeIoExecutor(String prefix, boolean daemon) {
        AtomicInteger workerCount = new AtomicInteger(1);
        return new TracingExecutor(Executors.newCachedThreadPool(runnable -> {
            Thread thread = new Thread(runnable);
            String name = prefix + workerCount.getAndIncrement();
            TracyClient.setThreadName(name, prefix.hashCode());
            thread.setName(name);
            thread.setDaemon(daemon);
            thread.setUncaughtExceptionHandler(Util::onThreadException);
            return thread;
        }));
    }
 
    public static void throwAsRuntime(Throwable throwable) {
        throw throwable instanceof RuntimeException ? (RuntimeException)throwable : new RuntimeException(throwable);
    }
 
    private static void onThreadException(Thread thread, Throwable throwable) {
        pauseInIde(throwable);
        if (throwable instanceof CompletionException) {
            throwable = throwable.getCause();
        }
 
        LOGGER.error("Caught exception in thread {}", thread, throwable);
        CrashReport report;
        if (throwable instanceof ReportedException reportedException) {
            report = reportedException.getReport();
        } else {
            report = CrashReport.forThrowable(throwable, "Exception on worker thread");
        }
 
        CrashReportCategory threadInfo = report.addCategory("ThreadInfo");
        threadInfo.setDetail("Name", thread.getName());
        BlockableEventLoop.relayDelayCrash(report);
    }
 
    public static @Nullable Type<?> fetchChoiceType(TypeReference reference, String name) {
        return !SharedConstants.CHECK_DATA_FIXER_SCHEMA ? null : doFetchChoiceType(reference, name);
    }
 
    private static @Nullable Type<?> doFetchChoiceType(TypeReference reference, String name) {
        Type<?> dataType = null;
 
        try {
            dataType = DataFixers.getDataFixer()
                .getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().dataVersion().version()))
                .getChoiceType(reference, name);
        } catch (IllegalArgumentException var4) {
            LOGGER.error("No data fixer registered for {}", name);
            if (SharedConstants.IS_RUNNING_IN_IDE) {
                throw var4;
            }
        }
 
        return dataType;
    }
 
    public static void runNamed(Runnable runnable, String name) {
        if (SharedConstants.IS_RUNNING_IN_IDE) {
            Thread thread = Thread.currentThread();
            String oldName = thread.getName();
            thread.setName(name);
 
            try (Zone ignored = TracyClient.beginZone(name, SharedConstants.IS_RUNNING_IN_IDE)) {
                runnable.run();
            } finally {
                thread.setName(oldName);
            }
        } else {
            try (Zone ignored = TracyClient.beginZone(name, SharedConstants.IS_RUNNING_IN_IDE)) {
                runnable.run();
            }
        }
    }
 
    public static <T> String getRegisteredName(Registry<T> registry, T entry) {
        Identifier key = registry.getKey(entry);
        return key == null ? "[unregistered]" : key.toString();
    }
 
    public static <T> Predicate<T> allOf() {
        return context -> true;
    }
 
    public static <T> Predicate<T> allOf(Predicate<? super T> condition) {
        return (Predicate<T>)condition;
    }
 
    public static <T> Predicate<T> allOf(Predicate<? super T> condition1, Predicate<? super T> condition2) {
        return context -> condition1.test(context) && condition2.test(context);
    }
 
    public static <T> Predicate<T> allOf(Predicate<? super T> condition1, Predicate<? super T> condition2, Predicate<? super T> condition3) {
        return context -> condition1.test(context) && condition2.test(context) && condition3.test(context);
    }
 
    public static <T> Predicate<T> allOf(
        Predicate<? super T> condition1, Predicate<? super T> condition2, Predicate<? super T> condition3, Predicate<? super T> condition4
    ) {
        return context -> condition1.test(context) && condition2.test(context) && condition3.test(context) && condition4.test(context);
    }
 
    public static <T> Predicate<T> allOf(
        Predicate<? super T> condition1,
        Predicate<? super T> condition2,
        Predicate<? super T> condition3,
        Predicate<? super T> condition4,
        Predicate<? super T> condition5
    ) {
        return context -> condition1.test(context)
            && condition2.test(context)
            && condition3.test(context)
            && condition4.test(context)
            && condition5.test(context);
    }
 
    @SafeVarargs
    public static <T> Predicate<T> allOf(Predicate<? super T>... conditions) {
        return context -> {
            for (Predicate<? super T> entry : conditions) {
                if (!entry.test(context)) {
                    return false;
                }
            }
 
            return true;
        };
    }
 
    public static <T> Predicate<T> allOf(List<? extends Predicate<? super T>> conditions) {
        return switch (conditions.size()) {
            case 0 -> allOf();
            case 1 -> allOf((Predicate<? super T>)conditions.get(0));
            case 2 -> allOf((Predicate<? super T>)conditions.get(0), (Predicate<? super T>)conditions.get(1));
            case 3 -> allOf((Predicate<? super T>)conditions.get(0), (Predicate<? super T>)conditions.get(1), (Predicate<? super T>)conditions.get(2));
            case 4 -> allOf(
                (Predicate<? super T>)conditions.get(0),
                (Predicate<? super T>)conditions.get(1),
                (Predicate<? super T>)conditions.get(2),
                (Predicate<? super T>)conditions.get(3)
            );
            case 5 -> allOf(
                (Predicate<? super T>)conditions.get(0),
                (Predicate<? super T>)conditions.get(1),
                (Predicate<? super T>)conditions.get(2),
                (Predicate<? super T>)conditions.get(3),
                (Predicate<? super T>)conditions.get(4)
            );
            default -> {
                Predicate<? super T>[] conditionsCopy = conditions.toArray(Predicate[]::new);
                yield allOf(conditionsCopy);
            }
        };
    }
 
    public static <T> Predicate<T> anyOf() {
        return context -> false;
    }
 
    public static <T> Predicate<T> anyOf(Predicate<? super T> condition1) {
        return (Predicate<T>)condition1;
    }
 
    public static <T> Predicate<T> anyOf(Predicate<? super T> condition1, Predicate<? super T> condition2) {
        return context -> condition1.test(context) || condition2.test(context);
    }
 
    public static <T> Predicate<T> anyOf(Predicate<? super T> condition1, Predicate<? super T> condition2, Predicate<? super T> condition3) {
        return context -> condition1.test(context) || condition2.test(context) || condition3.test(context);
    }
 
    public static <T> Predicate<T> anyOf(
        Predicate<? super T> condition1, Predicate<? super T> condition2, Predicate<? super T> condition3, Predicate<? super T> condition4
    ) {
        return context -> condition1.test(context) || condition2.test(context) || condition3.test(context) || condition4.test(context);
    }
 
    public static <T> Predicate<T> anyOf(
        Predicate<? super T> condition1,
        Predicate<? super T> condition2,
        Predicate<? super T> condition3,
        Predicate<? super T> condition4,
        Predicate<? super T> condition5
    ) {
        return context -> condition1.test(context)
            || condition2.test(context)
            || condition3.test(context)
            || condition4.test(context)
            || condition5.test(context);
    }
 
    @SafeVarargs
    public static <T> Predicate<T> anyOf(Predicate<? super T>... conditions) {
        return context -> {
            for (Predicate<? super T> entry : conditions) {
                if (entry.test(context)) {
                    return true;
                }
            }
 
            return false;
        };
    }
 
    public static <T> Predicate<T> anyOf(List<? extends Predicate<? super T>> conditions) {
        return switch (conditions.size()) {
            case 0 -> anyOf();
            case 1 -> anyOf((Predicate<? super T>)conditions.get(0));
            case 2 -> anyOf((Predicate<? super T>)conditions.get(0), (Predicate<? super T>)conditions.get(1));
            case 3 -> anyOf((Predicate<? super T>)conditions.get(0), (Predicate<? super T>)conditions.get(1), (Predicate<? super T>)conditions.get(2));
            case 4 -> anyOf(
                (Predicate<? super T>)conditions.get(0),
                (Predicate<? super T>)conditions.get(1),
                (Predicate<? super T>)conditions.get(2),
                (Predicate<? super T>)conditions.get(3)
            );
            case 5 -> anyOf(
                (Predicate<? super T>)conditions.get(0),
                (Predicate<? super T>)conditions.get(1),
                (Predicate<? super T>)conditions.get(2),
                (Predicate<? super T>)conditions.get(3),
                (Predicate<? super T>)conditions.get(4)
            );
            default -> {
                Predicate<? super T>[] conditionsCopy = conditions.toArray(Predicate[]::new);
                yield anyOf(conditionsCopy);
            }
        };
    }
 
    public static <T> boolean isSymmetrical(int width, int height, List<T> ingredients) {
        if (width == 1) {
            return true;
        } else {
            int centerX = width / 2;
 
            for (int y = 0; y < height; y++) {
                for (int leftX = 0; leftX < centerX; leftX++) {
                    int rightX = width - 1 - leftX;
                    T left = ingredients.get(leftX + y * width);
                    T right = ingredients.get(rightX + y * width);
                    if (!left.equals(right)) {
                        return false;
                    }
                }
            }
 
            return true;
        }
    }
 
    public static int growByHalf(int currentSize, int minimalNewSize) {
        return (int)Math.max(Math.min((long)currentSize + (currentSize >> 1), 2147483639L), (long)minimalNewSize);
    }
 
    @SuppressForbidden(reason = "Intentional use of default locale for user-visible date")
    public static DateTimeFormatter localizedDateFormatter(FormatStyle formatStyle) {
        return DateTimeFormatter.ofLocalizedDateTime(formatStyle);
    }
 
    public static Util.OS getPlatform() {
        String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
        if (osName.contains("win")) {
            return Util.OS.WINDOWS;
        } else if (osName.contains("mac")) {
            return Util.OS.OSX;
        } else if (osName.contains("solaris")) {
            return Util.OS.SOLARIS;
        } else if (osName.contains("sunos")) {
            return Util.OS.SOLARIS;
        } else if (osName.contains("linux")) {
            return Util.OS.LINUX;
        } else {
            return osName.contains("unix") ? Util.OS.LINUX : Util.OS.UNKNOWN;
        }
    }
 
    public static boolean isAarch64() {
        String arch = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
        return arch.equals("aarch64");
    }
 
    public static URI parseAndValidateUntrustedUri(String uri) throws URISyntaxException {
        URI parsedUri = new URI(uri);
        String scheme = parsedUri.getScheme();
        if (scheme == null) {
            throw new URISyntaxException(uri, "Missing protocol in URI: " + uri);
        } else {
            String protocol = scheme.toLowerCase(Locale.ROOT);
            if (!ALLOWED_UNTRUSTED_LINK_PROTOCOLS.contains(protocol)) {
                throw new URISyntaxException(uri, "Unsupported protocol in URI: " + uri);
            } else {
                return parsedUri;
            }
        }
    }
 
    public static <T> T findNextInIterable(Iterable<T> collection, @Nullable T current) {
        Iterator<T> iterator = collection.iterator();
        T first = iterator.next();
        if (current != null) {
            T property = first;
 
            while (property != current) {
                if (iterator.hasNext()) {
                    property = iterator.next();
                }
            }
 
            if (iterator.hasNext()) {
                return iterator.next();
            }
        }
 
        return first;
    }
 
    public static <T> T findPreviousInIterable(Iterable<T> collection, @Nullable T current) {
        Iterator<T> iterator = collection.iterator();
        T last = null;
 
        while (iterator.hasNext()) {
            T next = iterator.next();
            if (next == current) {
                if (last == null) {
                    last = iterator.hasNext() ? Iterators.getLast(iterator) : current;
                }
                break;
            }
 
            last = next;
        }
 
        return last;
    }
 
    public static <T> T make(Supplier<T> factory) {
        return factory.get();
    }
 
    public static <T> T make(T t, Consumer<? super T> consumer) {
        consumer.accept(t);
        return t;
    }
 
    public static <K extends Enum<K>, V> Map<K, V> makeEnumMap(Class<K> keyType, Function<K, V> function) {
        EnumMap<K, V> map = new EnumMap<>(keyType);
 
        for (K key : keyType.getEnumConstants()) {
            map.put(key, function.apply(key));
        }
 
        return map;
    }
 
    public static <K, V1, V2> Map<K, V2> mapValues(Map<K, V1> map, Function<? super V1, V2> valueMapper) {
        return map.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> valueMapper.apply(e.getValue())));
    }
 
    public static <K, V1, V2> Map<K, V2> mapValuesLazy(Map<K, V1> map, com.google.common.base.Function<V1, V2> valueMapper) {
        return Maps.transformValues(map, valueMapper);
    }
 
    public static <T extends Enum<T>> Set<T> allOfEnumExcept(T value) {
        return EnumSet.complementOf(EnumSet.of(value));
    }
 
    public static <V> CompletableFuture<List<V>> sequence(List<? extends CompletableFuture<V>> futures) {
        if (futures.isEmpty()) {
            return CompletableFuture.completedFuture(List.of());
        } else if (futures.size() == 1) {
            return futures.getFirst().thenApply(ObjectLists::singleton);
        } else {
            CompletableFuture<Void> all = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            return all.thenApply(ignored -> futures.stream().map(CompletableFuture::join).toList());
        }
    }
 
    public static <V> CompletableFuture<List<V>> sequenceFailFast(List<? extends CompletableFuture<? extends V>> futures) {
        CompletableFuture<List<V>> failureFuture = new CompletableFuture<>();
        return fallibleSequence(futures, failureFuture::completeExceptionally).applyToEither(failureFuture, Function.identity());
    }
 
    public static <V> CompletableFuture<List<V>> sequenceFailFastAndCancel(List<? extends CompletableFuture<? extends V>> futures) {
        CompletableFuture<List<V>> failureFuture = new CompletableFuture<>();
        return fallibleSequence(futures, exception -> {
            if (failureFuture.completeExceptionally(exception)) {
                for (CompletableFuture<? extends V> future : futures) {
                    future.cancel(true);
                }
            }
        }).applyToEither(failureFuture, Function.identity());
    }
 
    private static <V> CompletableFuture<List<V>> fallibleSequence(List<? extends CompletableFuture<? extends V>> futures, Consumer<Throwable> failureHandler) {
        ObjectArrayList<V> results = new ObjectArrayList<>();
        results.size(futures.size());
        CompletableFuture<?>[] decoratedFutures = new CompletableFuture[futures.size()];
 
        for (int i = 0; i < futures.size(); i++) {
            int index = i;
            decoratedFutures[i] = futures.get(i).whenComplete((result, exception) -> {
                if (exception != null) {
                    failureHandler.accept(exception);
                } else {
                    results.set(index, (V)result);
                }
            });
        }
 
        return CompletableFuture.allOf(decoratedFutures).thenApply(nothing -> results);
    }
 
    public static <T> Optional<T> ifElse(Optional<T> input, Consumer<T> onTrue, Runnable onFalse) {
        if (input.isPresent()) {
            onTrue.accept(input.get());
        } else {
            onFalse.run();
        }
 
        return input;
    }
 
    public static <T> Supplier<T> name(Supplier<T> task, Supplier<String> nameGetter) {
        if (SharedConstants.DEBUG_NAMED_RUNNABLES) {
            final String name = nameGetter.get();
            return new Supplier<T>() {
                @Override
                public T get() {
                    return task.get();
                }
 
                @Override
                public String toString() {
                    return name;
                }
            };
        } else {
            return task;
        }
    }
 
    public static Runnable name(Runnable task, Supplier<String> nameGetter) {
        if (SharedConstants.DEBUG_NAMED_RUNNABLES) {
            final String name = nameGetter.get();
            return new Runnable() {
                @Override
                public void run() {
                    task.run();
                }
 
                @Override
                public String toString() {
                    return name;
                }
            };
        } else {
            return task;
        }
    }
 
    public static void logAndPauseIfInIde(String message) {
        LOGGER.error(message);
        if (SharedConstants.IS_RUNNING_IN_IDE) {
            doPause(message);
        }
    }
 
    public static void logAndPauseIfInIde(String message, Throwable throwable) {
        LOGGER.error(message, throwable);
        if (SharedConstants.IS_RUNNING_IN_IDE) {
            doPause(message);
        }
    }
 
    public static <T extends Throwable> T pauseInIde(T t) {
        if (SharedConstants.IS_RUNNING_IN_IDE) {
            LOGGER.error("Trying to throw a fatal exception, pausing in IDE", t);
            doPause(t.getMessage());
        }
 
        return t;
    }
 
    public static void setPause(Consumer<String> pauseFunction) {
        thePauser = pauseFunction;
    }
 
    private static void doPause(String message) {
        Instant preLog = Instant.now();
        LOGGER.warn("Did you remember to set a breakpoint here?");
        boolean dontBotherWithPause = Duration.between(preLog, Instant.now()).toMillis() > 500L;
        if (!dontBotherWithPause) {
            thePauser.accept(message);
        }
    }
 
    public static String describeError(Throwable err) {
        if (err.getCause() != null) {
            return describeError(err.getCause());
        } else {
            return err.getMessage() != null ? err.getMessage() : err.toString();
        }
    }
 
    public static <T> T getRandom(T[] array, RandomSource random) {
        return array[random.nextInt(array.length)];
    }
 
    public static int getRandom(int[] array, RandomSource random) {
        return array[random.nextInt(array.length)];
    }
 
    public static <T> T getRandom(List<T> list, RandomSource random) {
        return list.get(random.nextInt(list.size()));
    }
 
    public static <T> Optional<T> getRandomSafe(List<T> list, RandomSource random) {
        return list.isEmpty() ? Optional.empty() : Optional.of(getRandom(list, random));
    }
 
    private static BooleanSupplier createRenamer(Path from, Path to, CopyOption... options) {
        return new BooleanSupplier() {
            @Override
            public boolean getAsBoolean() {
                try {
                    Files.move(from, to, options);
                    return true;
                } catch (IOException var2) {
                    Util.LOGGER.error("Failed to rename", (Throwable)var2);
                    return false;
                }
            }
 
            @Override
            public String toString() {
                return "rename " + from + " to " + to;
            }
        };
    }
 
    private static BooleanSupplier createDeleter(Path target) {
        return new BooleanSupplier() {
            @Override
            public boolean getAsBoolean() {
                try {
                    Files.deleteIfExists(target);
                    return true;
                } catch (IOException var2) {
                    Util.LOGGER.warn("Failed to delete", (Throwable)var2);
                    return false;
                }
            }
 
            @Override
            public String toString() {
                return "delete old " + target;
            }
        };
    }
 
    private static BooleanSupplier createFileDeletedCheck(Path target) {
        return new BooleanSupplier() {
            @Override
            public boolean getAsBoolean() {
                return !Files.exists(target);
            }
 
            @Override
            public String toString() {
                return "verify that " + target + " is deleted";
            }
        };
    }
 
    private static BooleanSupplier createFileCreatedCheck(Path target) {
        return new BooleanSupplier() {
            @Override
            public boolean getAsBoolean() {
                return Files.isRegularFile(target);
            }
 
            @Override
            public String toString() {
                return "verify that " + target + " is present";
            }
        };
    }
 
    private static boolean executeInSequence(BooleanSupplier... operations) {
        for (BooleanSupplier operation : operations) {
            if (!operation.getAsBoolean()) {
                LOGGER.warn("Failed to execute {}", operation);
                return false;
            }
        }
 
        return true;
    }
 
    private static boolean runWithRetries(int numberOfRetries, String description, BooleanSupplier... operations) {
        for (int retry = 0; retry < numberOfRetries; retry++) {
            if (executeInSequence(operations)) {
                return true;
            }
 
            LOGGER.error("Failed to {}, retrying {}/{}", description, retry, numberOfRetries);
        }
 
        LOGGER.error("Failed to {}, aborting, progress might be lost", description);
        return false;
    }
 
    public static boolean safeMoveFile(Path fromPath, Path toPath, CopyOption... options) {
        return runWithRetries(10, "move from  " + fromPath + " to " + toPath, createRenamer(fromPath, toPath, options), createFileCreatedCheck(toPath));
    }
 
    public static void safeReplaceFile(Path targetPath, Path newPath, Path backupPath) {
        safeReplaceOrMoveFile(targetPath, newPath, backupPath, false);
    }
 
    public static boolean safeReplaceOrMoveFile(Path targetPath, Path newPath, Path backupPath, boolean noRollback) {
        if (Files.exists(targetPath)
            && !runWithRetries(
                10, "create backup " + backupPath, createDeleter(backupPath), createRenamer(targetPath, backupPath), createFileCreatedCheck(backupPath)
            )) {
            return false;
        } else if (!runWithRetries(10, "remove old " + targetPath, createDeleter(targetPath), createFileDeletedCheck(targetPath))) {
            return false;
        } else if (!runWithRetries(10, "replace " + targetPath + " with " + newPath, createRenamer(newPath, targetPath), createFileCreatedCheck(targetPath))
            && !noRollback) {
            runWithRetries(10, "restore " + targetPath + " from " + backupPath, createRenamer(backupPath, targetPath), createFileCreatedCheck(targetPath));
            return false;
        } else {
            return true;
        }
    }
 
    public static int offsetByCodepoints(String input, int pos, int offset) {
        int length = input.length();
        if (offset >= 0) {
            for (int i = 0; pos < length && i < offset; i++) {
                if (Character.isHighSurrogate(input.charAt(pos++)) && pos < length && Character.isLowSurrogate(input.charAt(pos))) {
                    pos++;
                }
            }
        } else {
            for (int ix = offset; pos > 0 && ix < 0; ix++) {
                pos--;
                if (Character.isLowSurrogate(input.charAt(pos)) && pos > 0 && Character.isHighSurrogate(input.charAt(pos - 1))) {
                    pos--;
                }
            }
        }
 
        return pos;
    }
 
    public static Consumer<String> prefix(String prefix, Consumer<String> consumer) {
        return s -> consumer.accept(prefix + s);
    }
 
    public static DataResult<int[]> fixedSize(IntStream stream, int size) {
        int[] ints = stream.limit(size + 1).toArray();
        if (ints.length != size) {
            Supplier<String> message = () -> "Input is not a list of " + size + " ints";
            return ints.length >= size ? DataResult.error(message, Arrays.copyOf(ints, size)) : DataResult.error(message);
        } else {
            return DataResult.success(ints);
        }
    }
 
    public static DataResult<long[]> fixedSize(LongStream stream, int size) {
        long[] longs = stream.limit(size + 1).toArray();
        if (longs.length != size) {
            Supplier<String> message = () -> "Input is not a list of " + size + " longs";
            return longs.length >= size ? DataResult.error(message, Arrays.copyOf(longs, size)) : DataResult.error(message);
        } else {
            return DataResult.success(longs);
        }
    }
 
    public static <T> DataResult<List<T>> fixedSize(List<T> list, int size) {
        if (list.size() != size) {
            Supplier<String> message = () -> "Input is not a list of " + size + " elements";
            return list.size() >= size ? DataResult.error(message, list.subList(0, size)) : DataResult.error(message);
        } else {
            return DataResult.success(list);
        }
    }
 
    public static void startTimerHackThread() {
        Thread timerThread = new Thread("Timer hack thread") {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(2147483647L);
                    } catch (InterruptedException var2) {
                        Util.LOGGER.warn("Timer hack thread interrupted, that really should not happen");
                        return;
                    }
                }
            }
        };
        timerThread.setDaemon(true);
        timerThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
        timerThread.start();
    }
 
    public static void copyBetweenDirs(Path sourceDir, Path targetDir, Path sourcePath) throws IOException {
        Path relative = sourceDir.relativize(sourcePath);
        Path target = targetDir.resolve(relative);
        Files.copy(sourcePath, target);
    }
 
    public static String sanitizeName(String value, CharPredicate isAllowedChar) {
        return value.toLowerCase(Locale.ROOT)
            .chars()
            .mapToObj(c -> isAllowedChar.test((char)c) ? Character.toString((char)c) : "_")
            .collect(Collectors.joining());
    }
 
    public static <K, V> SingleKeyCache<K, V> singleKeyCache(Function<K, V> computeValueFunction) {
        return new SingleKeyCache<>(computeValueFunction);
    }
 
    public static <T, R> Function<T, R> memoize(Function<T, R> function) {
        return new Function<T, R>() {
            private final Map<T, R> cache = new ConcurrentHashMap<>();
 
            @Override
            public R apply(T arg) {
                return this.cache.computeIfAbsent(arg, function);
            }
 
            @Override
            public String toString() {
                return "memoize/1[function=" + function + ", size=" + this.cache.size() + "]";
            }
        };
    }
 
    public static <T, U, R> BiFunction<T, U, R> memoize(BiFunction<T, U, R> function) {
        return new BiFunction<T, U, R>() {
            private final Map<Pair<T, U>, R> cache = new ConcurrentHashMap<>();
 
            @Override
            public R apply(T a, U b) {
                return this.cache.computeIfAbsent(Pair.of(a, b), args -> function.apply(args.getFirst(), args.getSecond()));
            }
 
            @Override
            public String toString() {
                return "memoize/2[function=" + function + ", size=" + this.cache.size() + "]";
            }
        };
    }
 
    public static <T> List<T> toShuffledList(Stream<T> stream, RandomSource random) {
        ObjectArrayList<T> result = stream.collect(ObjectArrayList.toList());
        shuffle(result, random);
        return result;
    }
 
    public static IntArrayList toShuffledList(IntStream stream, RandomSource random) {
        IntArrayList result = IntArrayList.wrap(stream.toArray());
        int size = result.size();
 
        for (int i = size; i > 1; i--) {
            int swapTo = random.nextInt(i);
            result.set(i - 1, result.set(swapTo, result.getInt(i - 1)));
        }
 
        return result;
    }
 
    public static <T> List<T> shuffledCopy(T[] array, RandomSource random) {
        ObjectArrayList<T> copy = new ObjectArrayList<>(array);
        shuffle(copy, random);
        return copy;
    }
 
    public static <T> List<T> shuffledCopy(ObjectArrayList<T> list, RandomSource random) {
        ObjectArrayList<T> copy = new ObjectArrayList<>(list);
        shuffle(copy, random);
        return copy;
    }
 
    public static <T> void shuffle(List<T> list, RandomSource random) {
        int size = list.size();
 
        for (int i = size; i > 1; i--) {
            int swapTo = random.nextInt(i);
            list.set(i - 1, list.set(swapTo, list.get(i - 1)));
        }
    }
 
    public static <T> CompletableFuture<T> blockUntilDone(Function<Executor, CompletableFuture<T>> task) {
        return blockUntilDone(task, CompletableFuture::isDone);
    }
 
    public static <T> T blockUntilDone(Function<Executor, T> task, Predicate<T> completionCheck) {
        BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
        T result = task.apply(tasks::add);
 
        while (!completionCheck.test(result)) {
            try {
                Runnable runnable = tasks.poll(100L, TimeUnit.MILLISECONDS);
                if (runnable != null) {
                    runnable.run();
                }
            } catch (InterruptedException var5) {
                LOGGER.warn("Interrupted wait");
                break;
            }
        }
 
        int remainingSize = tasks.size();
        if (remainingSize > 0) {
            LOGGER.warn("Tasks left in queue: {}", remainingSize);
        }
 
        return result;
    }
 
    public static <T> ToIntFunction<T> createIndexLookup(List<T> values) {
        int size = values.size();
        if (size < 8) {
            return values::indexOf;
        } else {
            Object2IntMap<T> lookup = new Object2IntOpenHashMap<>(size);
            lookup.defaultReturnValue(-1);
 
            for (int i = 0; i < size; i++) {
                lookup.put(values.get(i), i);
            }
 
            return lookup;
        }
    }
 
    public static <T> ToIntFunction<T> createIndexIdentityLookup(List<T> values) {
        int size = values.size();
        if (size < 8) {
            ReferenceList<T> referenceLookup = new ReferenceImmutableList<>(values);
            return referenceLookup::indexOf;
        } else {
            Reference2IntMap<T> lookup = new Reference2IntOpenHashMap<>(size);
            lookup.defaultReturnValue(-1);
 
            for (int i = 0; i < size; i++) {
                lookup.put(values.get(i), i);
            }
 
            return lookup;
        }
    }
 
    public static <A, B> Typed<B> writeAndReadTypedOrThrow(Typed<A> typed, Type<B> newType, UnaryOperator<Dynamic<?>> function) {
        Dynamic<?> dynamic = (Dynamic<?>)typed.write().getOrThrow();
        return readTypedOrThrow(newType, function.apply(dynamic), true);
    }
 
    public static <T> Typed<T> readTypedOrThrow(Type<T> type, Dynamic<?> dynamic) {
        return readTypedOrThrow(type, dynamic, false);
    }
 
    public static <T> Typed<T> readTypedOrThrow(Type<T> type, Dynamic<?> dynamic, boolean acceptPartial) {
        DataResult<Typed<T>> result = type.readTyped(dynamic).map(Pair::getFirst);
 
        try {
            return acceptPartial ? result.getPartialOrThrow(IllegalStateException::new) : result.getOrThrow(IllegalStateException::new);
        } catch (IllegalStateException var7) {
            CrashReport report = CrashReport.forThrowable(var7, "Reading type");
            CrashReportCategory category = report.addCategory("Info");
            category.setDetail("Data", dynamic);
            category.setDetail("Type", type);
            throw new ReportedException(report);
        }
    }
 
    public static <T> List<T> copyAndAdd(List<T> list, T element) {
        return ImmutableList.<T>builderWithExpectedSize(list.size() + 1).addAll(list).add(element).build();
    }
 
    public static <T> List<T> copyAndAdd(List<T> list, T... elements) {
        return ImmutableList.<T>builderWithExpectedSize(list.size() + elements.length).addAll(list).add(elements).build();
    }
 
    public static <T> List<T> copyAndAdd(T element, List<T> list) {
        return ImmutableList.<T>builderWithExpectedSize(list.size() + 1).add(element).addAll(list).build();
    }
 
    public static <K, V> Map<K, V> copyAndPut(Map<K, V> map, K key, V value) {
        return ImmutableMap.<K, V>builderWithExpectedSize(map.size() + 1).putAll(map).put(key, value).buildKeepingLast();
    }
 
    public static enum OS {
        LINUX("linux"),
        SOLARIS("solaris"),
        WINDOWS("windows") {
            @Override
            protected String[] getOpenUriArguments(URI uri) {
                return new String[]{"rundll32", "url.dll,FileProtocolHandler", uri.toString()};
            }
        },
        OSX("mac") {
            @Override
            protected String[] getOpenUriArguments(URI uri) {
                return new String[]{"open", uri.toString()};
            }
        },
        UNKNOWN("unknown");
 
        private final String telemetryName;
 
        private OS(String telemetryName) {
            this.telemetryName = telemetryName;
        }
 
        public void openUri(URI uri) {
            try {
                Process process = Runtime.getRuntime().exec(this.getOpenUriArguments(uri));
                process.getInputStream().close();
                process.getErrorStream().close();
                process.getOutputStream().close();
            } catch (IOException var3) {
                Util.LOGGER.error("Couldn't open location '{}'", uri, var3);
            }
        }
 
        public void openFile(File file) {
            this.openUri(file.toURI());
        }
 
        public void openPath(Path path) {
            this.openUri(path.toUri());
        }
 
        protected String[] getOpenUriArguments(URI uri) {
            String string = uri.toString();
            if ("file".equals(uri.getScheme())) {
                string = string.replace("file:", "file://");
            }
 
            return new String[]{"xdg-open", string};
        }
 
        public void openUri(String uri) {
            try {
                this.openUri(new URI(uri));
            } catch (IllegalArgumentException | URISyntaxException var3) {
                Util.LOGGER.error("Couldn't open uri '{}'", uri, var3);
            }
        }
 
        public String telemetryName() {
            return this.telemetryName;
        }
    }
}

引用的其他类