PackFormat.java
net.minecraft.server.packs.metadata.pack.PackFormat
信息
- 全限定名:net.minecraft.server.packs.metadata.pack.PackFormat
- 类型:public record
- 包:net.minecraft.server.packs.metadata.pack
- 源码路径:src/main/java/net/minecraft/server/packs/metadata/pack/PackFormat.java
- 起始行号:L20
- 实现:Comparable
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L21 - 说明:
TODO
- 类型:
-
BOTTOM_CODEC- 类型:
Codec<PackFormat> - 修饰符:
public static final - 源码定位:
L22 - 说明:
TODO
- 类型:
-
TOP_CODEC- 类型:
Codec<PackFormat> - 修饰符:
public static final - 源码定位:
L23 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.server.packs.metadata.pack.PackFormat.IntermediaryFormat- 类型:
record - 修饰符:
public - 源码定位:
L103 - 说明:
TODO
- 类型:
-
net.minecraft.server.packs.metadata.pack.PackFormat.IntermediaryFormatHolder- 类型:
interface - 修饰符:
public - 源码定位:
L329 - 说明:
TODO
- 类型:
构造器
- 无
方法
下面的方法块按源码顺序生成。
private static Codec<PackFormat> fullCodec(int defaultMinor) @ L25
- 方法名:fullCodec
- 源码定位:L25
- 返回类型:Codec
- 修饰符:private static
参数:
- defaultMinor: int
说明:
TODO
public static <ResultType,HolderType extends PackFormat.IntermediaryFormatHolder> DataResult<List<ResultType>> validateHolderList(List<HolderType> list, int lastPreMinorVersion, BiFunction<HolderType,InclusiveRange<PackFormat>,ResultType> constructor) @ L33
- 方法名:validateHolderList
- 源码定位:L33
- 返回类型:<ResultType,HolderType extends PackFormat.IntermediaryFormatHolder> DataResult<List
> - 修饰符:public static
参数:
- list: List
- lastPreMinorVersion: int
- constructor: BiFunction<HolderType,InclusiveRange
,ResultType>
说明:
TODO
public static int lastPreMinorVersion(PackType type) @ L62
- 方法名:lastPreMinorVersion
- 源码定位:L62
- 返回类型:int
- 修饰符:public static
参数:
- type: PackType
说明:
TODO
public static MapCodec<InclusiveRange<PackFormat>> packCodec(PackType type) @ L70
- 方法名:packCodec
- 源码定位:L70
- 返回类型:MapCodec<InclusiveRange
> - 修饰符:public static
参数:
- type: PackType
说明:
TODO
public static PackFormat of(int major, int minor) @ L79
- 方法名:of
- 源码定位:L79
- 返回类型:PackFormat
- 修饰符:public static
参数:
- major: int
- minor: int
说明:
TODO
public static PackFormat of(int major) @ L83
- 方法名:of
- 源码定位:L83
- 返回类型:PackFormat
- 修饰符:public static
参数:
- major: int
说明:
TODO
public InclusiveRange<PackFormat> minorRange() @ L87
- 方法名:minorRange
- 源码定位:L87
- 返回类型:InclusiveRange
- 修饰符:public
参数:
- 无
说明:
TODO
public int compareTo(PackFormat other) @ L91
- 方法名:compareTo
- 源码定位:L91
- 返回类型:int
- 修饰符:public
参数:
- other: PackFormat
说明:
TODO
public String toString() @ L96
- 方法名:toString
- 源码定位:L96
- 返回类型:String
- 修饰符:public
参数:
- 无
说明:
TODO
代码
public record PackFormat(int major, int minor) implements Comparable<PackFormat> {
private static final Logger LOGGER = LogUtils.getLogger();
public static final Codec<PackFormat> BOTTOM_CODEC = fullCodec(0);
public static final Codec<PackFormat> TOP_CODEC = fullCodec(Integer.MAX_VALUE);
private static Codec<PackFormat> fullCodec(int defaultMinor) {
return ExtraCodecs.compactListCodec(ExtraCodecs.NON_NEGATIVE_INT, ExtraCodecs.NON_NEGATIVE_INT.listOf(1, 256))
.xmap(
list -> list.size() > 1 ? of(list.getFirst(), list.get(1)) : of(list.getFirst(), defaultMinor),
pf -> pf.minor != defaultMinor ? List.of(pf.major(), pf.minor()) : List.of(pf.major())
);
}
public static <ResultType, HolderType extends PackFormat.IntermediaryFormatHolder> DataResult<List<ResultType>> validateHolderList(
List<HolderType> list, int lastPreMinorVersion, BiFunction<HolderType, InclusiveRange<PackFormat>, ResultType> constructor
) {
int minVersion = list.stream()
.map(PackFormat.IntermediaryFormatHolder::format)
.mapToInt(PackFormat.IntermediaryFormat::effectiveMinMajorVersion)
.min()
.orElse(Integer.MAX_VALUE);
List<ResultType> result = new ArrayList<>(list.size());
for (HolderType entry : list) {
PackFormat.IntermediaryFormat format = entry.format();
if (format.min().isEmpty() && format.max().isEmpty() && format.supported().isEmpty()) {
LOGGER.warn("Unknown or broken overlay entry {}", entry);
} else {
DataResult<InclusiveRange<PackFormat>> entryResult = format.validate(
lastPreMinorVersion, false, minVersion <= lastPreMinorVersion, "Overlay \"" + entry + "\"", "formats"
);
if (!entryResult.isSuccess()) {
return DataResult.error(entryResult.error().get()::message);
}
result.add(constructor.apply(entry, entryResult.getOrThrow()));
}
}
return DataResult.success(List.copyOf(result));
}
@VisibleForTesting
public static int lastPreMinorVersion(PackType type) {
return switch (type) {
case CLIENT_RESOURCES -> 64;
case SERVER_DATA -> 81;
};
}
public static MapCodec<InclusiveRange<PackFormat>> packCodec(PackType type) {
int lastPreMinorVersion = lastPreMinorVersion(type);
return PackFormat.IntermediaryFormat.PACK_CODEC
.flatXmap(
intermediaryFormat -> intermediaryFormat.validate(lastPreMinorVersion, true, false, "Pack", "supported_formats"),
range -> DataResult.success(PackFormat.IntermediaryFormat.fromRange((InclusiveRange<PackFormat>)range, lastPreMinorVersion))
);
}
public static PackFormat of(int major, int minor) {
return new PackFormat(major, minor);
}
public static PackFormat of(int major) {
return new PackFormat(major, 0);
}
public InclusiveRange<PackFormat> minorRange() {
return new InclusiveRange<>(this, of(this.major, Integer.MAX_VALUE));
}
public int compareTo(PackFormat other) {
int majorDiff = Integer.compare(this.major(), other.major());
return majorDiff != 0 ? majorDiff : Integer.compare(this.minor(), other.minor());
}
@Override
public String toString() {
return this.minor == Integer.MAX_VALUE
? String.format(Locale.ROOT, "%d.*", this.major())
: String.format(Locale.ROOT, "%d.%d", this.major(), this.minor());
}
public record IntermediaryFormat(Optional<PackFormat> min, Optional<PackFormat> max, Optional<Integer> format, Optional<InclusiveRange<Integer>> supported) {
private static final MapCodec<PackFormat.IntermediaryFormat> PACK_CODEC = RecordCodecBuilder.mapCodec(
i -> i.group(
PackFormat.BOTTOM_CODEC.optionalFieldOf("min_format").forGetter(PackFormat.IntermediaryFormat::min),
PackFormat.TOP_CODEC.optionalFieldOf("max_format").forGetter(PackFormat.IntermediaryFormat::max),
Codec.INT.optionalFieldOf("pack_format").forGetter(PackFormat.IntermediaryFormat::format),
InclusiveRange.codec(Codec.INT).optionalFieldOf("supported_formats").forGetter(PackFormat.IntermediaryFormat::supported)
)
.apply(i, PackFormat.IntermediaryFormat::new)
);
public static final MapCodec<PackFormat.IntermediaryFormat> OVERLAY_CODEC = RecordCodecBuilder.mapCodec(
i -> i.group(
PackFormat.BOTTOM_CODEC.optionalFieldOf("min_format").forGetter(PackFormat.IntermediaryFormat::min),
PackFormat.TOP_CODEC.optionalFieldOf("max_format").forGetter(PackFormat.IntermediaryFormat::max),
InclusiveRange.codec(Codec.INT).optionalFieldOf("formats").forGetter(PackFormat.IntermediaryFormat::supported)
)
.apply(i, (min, max, formats) -> new PackFormat.IntermediaryFormat(min, max, min.map(PackFormat::major), formats))
);
public static PackFormat.IntermediaryFormat fromRange(InclusiveRange<PackFormat> range, int lastPreMinorVersion) {
InclusiveRange<Integer> majorRange = range.map(PackFormat::major);
return new PackFormat.IntermediaryFormat(
Optional.of(range.minInclusive()),
Optional.of(range.maxInclusive()),
majorRange.isValueInRange(lastPreMinorVersion) ? Optional.of(majorRange.minInclusive()) : Optional.empty(),
majorRange.isValueInRange(lastPreMinorVersion)
? Optional.of(new InclusiveRange<>(majorRange.minInclusive(), majorRange.maxInclusive()))
: Optional.empty()
);
}
public int effectiveMinMajorVersion() {
if (this.min.isPresent()) {
return this.supported.isPresent() ? Math.min(this.min.get().major(), this.supported.get().minInclusive()) : this.min.get().major();
} else {
return this.supported.isPresent() ? this.supported.get().minInclusive() : Integer.MAX_VALUE;
}
}
public DataResult<InclusiveRange<PackFormat>> validate(
int lastPreMinorVersion, boolean hasPackFormatField, boolean requireOldField, String context, String oldFieldName
) {
if (this.min.isPresent() != this.max.isPresent()) {
return DataResult.error(() -> context + " missing field, must declare both min_format and max_format");
} else if (requireOldField && this.supported.isEmpty()) {
return DataResult.error(
() -> context
+ " missing required field "
+ oldFieldName
+ ", must be present in all overlays for any overlays to work across game versions"
);
} else if (this.min.isPresent()) {
return this.validateNewFormat(lastPreMinorVersion, hasPackFormatField, requireOldField, context, oldFieldName);
} else if (this.supported.isPresent()) {
return this.validateOldFormat(lastPreMinorVersion, hasPackFormatField, context, oldFieldName);
} else if (hasPackFormatField && this.format.isPresent()) {
int mainFormat = this.format.get();
return mainFormat > lastPreMinorVersion
? DataResult.error(
() -> context
+ " declares support for version newer than "
+ lastPreMinorVersion
+ ", but is missing mandatory fields min_format and max_format"
)
: DataResult.success(new InclusiveRange<>(PackFormat.of(mainFormat)));
} else {
return DataResult.error(() -> context + " could not be parsed, missing format version information");
}
}
private DataResult<InclusiveRange<PackFormat>> validateNewFormat(
int lastPreMinorVersion, boolean hasPackFormatField, boolean requireOldField, String context, String oldFieldName
) {
int majorMin = this.min.get().major();
int majorMax = this.max.get().major();
if (this.min.get().compareTo(this.max.get()) > 0) {
return DataResult.error(() -> context + " min_format (" + this.min.get() + ") is greater than max_format (" + this.max.get() + ")");
} else {
if (majorMin > lastPreMinorVersion && !requireOldField) {
if (this.supported.isPresent()) {
return DataResult.error(
() -> context
+ " key "
+ oldFieldName
+ " is deprecated starting from pack format "
+ (lastPreMinorVersion + 1)
+ ". Remove "
+ oldFieldName
+ " from your pack.mcmeta."
);
}
if (hasPackFormatField && this.format.isPresent()) {
String packFormatError = this.validatePackFormatForRange(majorMin, majorMax);
if (packFormatError != null) {
return DataResult.error(() -> packFormatError);
}
}
} else {
if (!this.supported.isPresent()) {
return DataResult.error(
() -> context
+ " declares support for format "
+ majorMin
+ ", but game versions supporting formats 17 to "
+ lastPreMinorVersion
+ " require a "
+ oldFieldName
+ " field. Add \""
+ oldFieldName
+ "\": ["
+ majorMin
+ ", "
+ lastPreMinorVersion
+ "] or require a version greater or equal to "
+ (lastPreMinorVersion + 1)
+ ".0."
);
}
InclusiveRange<Integer> oldSupportedVersions = this.supported.get();
if (oldSupportedVersions.minInclusive() != majorMin) {
return DataResult.error(
() -> context
+ " version declaration mismatch between "
+ oldFieldName
+ " (from "
+ oldSupportedVersions.minInclusive()
+ ") and min_format ("
+ this.min.get()
+ ")"
);
}
if (oldSupportedVersions.maxInclusive() != majorMax && oldSupportedVersions.maxInclusive() != lastPreMinorVersion) {
return DataResult.error(
() -> context
+ " version declaration mismatch between "
+ oldFieldName
+ " (up to "
+ oldSupportedVersions.maxInclusive()
+ ") and max_format ("
+ this.max.get()
+ ")"
);
}
if (hasPackFormatField) {
if (!this.format.isPresent()) {
return DataResult.error(
() -> context
+ " declares support for formats up to "
+ lastPreMinorVersion
+ ", but game versions supporting formats 17 to "
+ lastPreMinorVersion
+ " require a pack_format field. Add \"pack_format\": "
+ majorMin
+ " or require a version greater or equal to "
+ (lastPreMinorVersion + 1)
+ ".0."
);
}
String packFormatError = this.validatePackFormatForRange(majorMin, majorMax);
if (packFormatError != null) {
return DataResult.error(() -> packFormatError);
}
}
}
return DataResult.success(new InclusiveRange<>(this.min.get(), this.max.get()));
}
}
private DataResult<InclusiveRange<PackFormat>> validateOldFormat(
int lastPreMinorVersion, boolean hasPackFormatField, String context, String oldFieldName
) {
InclusiveRange<Integer> oldSupportedVersions = this.supported.get();
int min = oldSupportedVersions.minInclusive();
int max = oldSupportedVersions.maxInclusive();
if (max > lastPreMinorVersion) {
return DataResult.error(
() -> context
+ " declares support for version newer than "
+ lastPreMinorVersion
+ ", but is missing mandatory fields min_format and max_format"
);
} else {
if (hasPackFormatField) {
if (!this.format.isPresent()) {
return DataResult.error(
() -> context
+ " declares support for formats up to "
+ lastPreMinorVersion
+ ", but game versions supporting formats 17 to "
+ lastPreMinorVersion
+ " require a pack_format field. Add \"pack_format\": "
+ min
+ " or require a version greater or equal to "
+ (lastPreMinorVersion + 1)
+ ".0."
);
}
String packFormatError = this.validatePackFormatForRange(min, max);
if (packFormatError != null) {
return DataResult.error(() -> packFormatError);
}
}
return DataResult.success(new InclusiveRange<>(min, max).map(PackFormat::of));
}
}
private @Nullable String validatePackFormatForRange(int min, int max) {
int mainFormat = this.format.get();
if (mainFormat < min || mainFormat > max) {
return "Pack declared support for versions " + min + " to " + max + " but declared main format is " + mainFormat;
} else {
return mainFormat < 15
? "Multi-version packs cannot support minimum version of less than 15, since this will leave versions in range unable to load pack."
: null;
}
}
}
public interface IntermediaryFormatHolder {
PackFormat.IntermediaryFormat format();
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ExtraCodecs.compactListCodec()
- 引用位置:
-
- 引用位置:
参数/方法调用/返回值 - 关联成员:
InclusiveRange.codec()
- 引用位置: