mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
Merge branch 'Xiao-MoMi:dev' into dev
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
import net.minecrell.pluginyml.paper.PaperPluginDescription
|
import net.minecrell.pluginyml.paper.PaperPluginDescription
|
||||||
import xyz.jpenilla.runpaper.task.RunServer
|
import xyz.jpenilla.runpaper.task.RunServer
|
||||||
import xyz.jpenilla.runtask.pluginsapi.DownloadPluginsSpec
|
|
||||||
import java.net.URI
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.gradleup.shadow") version "9.3.0"
|
id("com.gradleup.shadow") version "9.3.0"
|
||||||
@@ -224,10 +222,9 @@ fun registerPaperTask(
|
|||||||
version: String,
|
version: String,
|
||||||
dirName: String = version,
|
dirName: String = version,
|
||||||
javaVersion : Int = 21,
|
javaVersion : Int = 21,
|
||||||
serverJar: File? = null,
|
serverJar: File? = null
|
||||||
downloadPlugins: Action<DownloadPluginsSpec>? = null
|
|
||||||
) {
|
) {
|
||||||
listOf(version, "${version}-with-viaversion").forEach { taskName ->
|
listOf(version).forEach { taskName ->
|
||||||
tasks.register(taskName, RunServer::class) {
|
tasks.register(taskName, RunServer::class) {
|
||||||
group = "run dev server"
|
group = "run dev server"
|
||||||
minecraftVersion(version)
|
minecraftVersion(version)
|
||||||
@@ -245,18 +242,6 @@ fun registerPaperTask(
|
|||||||
jvmArgs("-Ddisable.watchdog=true")
|
jvmArgs("-Ddisable.watchdog=true")
|
||||||
jvmArgs("-Xlog:redefine+class*=info")
|
jvmArgs("-Xlog:redefine+class*=info")
|
||||||
jvmArgs("-XX:+AllowEnhancedClassRedefinition")
|
jvmArgs("-XX:+AllowEnhancedClassRedefinition")
|
||||||
if (taskName.contains("viaversion")) {
|
|
||||||
downloadPlugins {
|
|
||||||
url("https://ci.viaversion.com/job/ViaVersion/lastBuild/artifact/build/libs/${getJenkinsArtifactFileName("https://ci.viaversion.com/job/ViaVersion/lastSuccessfulBuild/api/json?tree=artifacts[*]")}")
|
|
||||||
url("https://ci.viaversion.com/view/ViaBackwards/job/ViaBackwards/662/artifact/build/libs/${getJenkinsArtifactFileName("https://ci.viaversion.com/job/ViaBackwards/lastSuccessfulBuild/api/json?tree=artifacts[*]")}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun getJenkinsArtifactFileName(url: String): String {
|
|
||||||
val response = URI.create(url).toURL().readText()
|
|
||||||
val regex = """"fileName":"([^"]+)"""".toRegex()
|
|
||||||
return regex.find(response)?.groupValues?.get(1) ?: throw Exception("fileName not found")
|
|
||||||
}
|
}
|
||||||
@@ -50,6 +50,7 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
|||||||
byte peek,
|
byte peek,
|
||||||
boolean interactive,
|
boolean interactive,
|
||||||
boolean interactionEntity,
|
boolean interactionEntity,
|
||||||
|
boolean invisible,
|
||||||
Direction direction) {
|
Direction direction) {
|
||||||
super(seats, position, canUseItemOn, blocksBuilding, canBeHitByProjectile);
|
super(seats, position, canUseItemOn, blocksBuilding, canBeHitByProjectile);
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
@@ -66,7 +67,9 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
|||||||
ShulkerData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedShulkerValues); // Invisible
|
ShulkerData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedShulkerValues); // Invisible
|
||||||
|
|
||||||
List<Object> cachedInteractionValues = new ArrayList<>();
|
List<Object> cachedInteractionValues = new ArrayList<>();
|
||||||
InteractionEntityData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, cachedInteractionValues);
|
if (invisible) {
|
||||||
|
InteractionEntityData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, cachedInteractionValues);
|
||||||
|
}
|
||||||
float shulkerHeight = (getPhysicalPeek(peek * 0.01F) + 1) * scale;
|
float shulkerHeight = (getPhysicalPeek(peek * 0.01F) + 1) * scale;
|
||||||
if (direction == Direction.UP) {
|
if (direction == Direction.UP) {
|
||||||
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues);
|
InteractionEntityData.Height.addEntityDataIfNotDefaultValue(shulkerHeight + 0.01f, cachedInteractionValues);
|
||||||
@@ -309,11 +312,12 @@ public class ShulkerFurnitureHitboxConfig extends AbstractFurnitureHitBoxConfig<
|
|||||||
boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
boolean canUseItemOn = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-use-item-on", true), "can-use-item-on");
|
||||||
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
boolean canBeHitByProjectile = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-be-hit-by-projectile", true), "can-be-hit-by-projectile");
|
||||||
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
boolean blocksBuilding = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blocks-building", true), "blocks-building");
|
||||||
|
boolean invisible = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("invisible", false), "invisible");
|
||||||
return new ShulkerFurnitureHitboxConfig(
|
return new ShulkerFurnitureHitboxConfig(
|
||||||
SeatConfig.fromObj(arguments.get("seats")),
|
SeatConfig.fromObj(arguments.get("seats")),
|
||||||
position,
|
position,
|
||||||
canUseItemOn, blocksBuilding, canBeHitByProjectile,
|
canUseItemOn, blocksBuilding, canBeHitByProjectile,
|
||||||
scale, peek, interactive, interactionEntity, directionEnum
|
scale, peek, interactive, interactionEntity, invisible, directionEnum
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,16 @@ resource-pack:
|
|||||||
# This option determines the location of the generated resource pack
|
# This option determines the location of the generated resource pack
|
||||||
# You can use either an absolute path or a relative path here
|
# You can use either an absolute path or a relative path here
|
||||||
path: "./generated/resource_pack.zip"
|
path: "./generated/resource_pack.zip"
|
||||||
|
# The minimum client version supported by CraftEngine is 1.16. If you need to provide support for lower client versions, please modify the resource pack yourself.
|
||||||
# Allowed values:
|
# Allowed values:
|
||||||
# - 1.20.1, 1.21, 1.21.8, etc.
|
# - 1.20.1, 1.21, 1.21.8, 26.1, etc.
|
||||||
# - latest: the latest client version
|
# - latest: the latest client version
|
||||||
# - server: the current server version
|
# - server: the current server version
|
||||||
supported-version:
|
supported-version:
|
||||||
min: server
|
min: server
|
||||||
max: latest
|
max: latest
|
||||||
|
# The description of your resource pack
|
||||||
|
description: "<gray>CraftEngine ResourcePack</gray>"
|
||||||
# Remove 1.21.5+ tinted_leaves particles
|
# Remove 1.21.5+ tinted_leaves particles
|
||||||
remove-tinted-leaves-particle: true
|
remove-tinted-leaves-particle: true
|
||||||
# Define the name of the overlay folders
|
# Define the name of the overlay folders
|
||||||
@@ -64,7 +67,6 @@ resource-pack:
|
|||||||
path: "pack.mcmeta"
|
path: "pack.mcmeta"
|
||||||
resolution:
|
resolution:
|
||||||
type: merge_pack_mcmeta
|
type: merge_pack_mcmeta
|
||||||
description: "<gray>CraftEngine ResourcePack</gray>"
|
|
||||||
- term:
|
- term:
|
||||||
type: exact
|
type: exact
|
||||||
path: "pack.png"
|
path: "pack.png"
|
||||||
@@ -94,13 +96,12 @@ resource-pack:
|
|||||||
resolution:
|
resolution:
|
||||||
type: merge_font
|
type: merge_font
|
||||||
# Validate if there is any error in the resource pack, such as missing textures or models.
|
# Validate if there is any error in the resource pack, such as missing textures or models.
|
||||||
# Validation may not always be accurate due to the presence of resource pack overlays.
|
|
||||||
# If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed.
|
# If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed.
|
||||||
validation:
|
validation:
|
||||||
enable: true
|
enable: true
|
||||||
# Fix textures that are not within the atlas. It is unreasonable to always rely on plugins to fix your mistakes.
|
# Fix textures that are not within the atlas. It is unreasonable to always rely on plugins to fix your mistakes.
|
||||||
# You should strive to make your resource pack more standardized after gaining some experience with resource packs.
|
# You should strive to make your resource pack more standardized after gaining some experience with resource packs.
|
||||||
# When a model file mixes textures from both the blocks atlas and the items atlas, you must manually fix the issue.
|
# The fix-atlas feature is not all-powerful since 1.21.11. In some cases, CraftEngine cannot fix it for you, and you will need to fix your model yourself.
|
||||||
fix-atlas: true
|
fix-atlas: true
|
||||||
# Optimize your resource pack by reducing its size without any quality loss.
|
# Optimize your resource pack by reducing its size without any quality loss.
|
||||||
optimization:
|
optimization:
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"pack": {
|
|
||||||
"pack_format": 15,
|
|
||||||
"description": "CraftEngine",
|
|
||||||
"supported_formats": {
|
|
||||||
"min_inclusive": 15,
|
|
||||||
"max_inclusive": 1000
|
|
||||||
},
|
|
||||||
"min_format": 15,
|
|
||||||
"max_format": 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -40,14 +40,16 @@ argument.parse.failure.either: "<red>Could not resolve <arg:1> or <arg:2> from '
|
|||||||
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' is not a named text color</red>"
|
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' is not a named text color</red>"
|
||||||
info.pack.load: "Loaded pack: <arg:0>. Default namespace: <arg:1>"
|
info.pack.load: "Loaded pack: <arg:0>. Default namespace: <arg:1>"
|
||||||
info.resource.load: "Loaded <arg:0> in <arg:1>ms (<arg:2>)"
|
info.resource.load: "Loaded <arg:0> in <arg:1>ms (<arg:2>)"
|
||||||
info.resource_pack.start: "Generating resource pack..."
|
info.resource_pack.generate.start: "Generating resource pack..."
|
||||||
info.resource_pack.generate: "Generated resource pack in <arg:0>ms"
|
info.resource_pack.generate.finish: "Generated resource pack in <arg:0>ms"
|
||||||
info.resource_pack.validate: "Validated resource pack in <arg:0>ms"
|
info.resource_pack.validate.start: "Validating resource pack... (Progress: <arg:0>/<arg:1> | Pack Format: <arg:2>~<arg:3> | Overlays: <arg:4>)"
|
||||||
info.resource_pack.optimize: "Optimized resource pack in <arg:0>ms"
|
info.resource_pack.validate.finish: "Validated resource pack in <arg:0>ms"
|
||||||
info.resource_pack.optimize.json: "> Optimizing json files..."
|
info.resource_pack.optimize.json: "> Optimizing json files..."
|
||||||
info.resource_pack.optimize.texture: "> Optimizing textures..."
|
info.resource_pack.optimize.texture: "> Optimizing textures..."
|
||||||
info.resource_pack.optimize.result: "□ Before/After/Ratio: <arg:0>/<arg:1>/<arg:2>%"
|
info.resource_pack.optimize.result: "□ Before/After/Ratio: <arg:0>/<arg:1>/<arg:2>%"
|
||||||
info.resource_pack.create: "Created resource pack zip in <arg:0>ms"
|
info.resource_pack.optimize.finish: "Optimized resource pack in <arg:0>ms"
|
||||||
|
info.resource_pack.create.start: "Creating the resource pack zip..."
|
||||||
|
info.resource_pack.create.finish: "Created resource pack zip in <arg:0>ms"
|
||||||
info.resource_pack.upload: "Completed uploading resource pack"
|
info.resource_pack.upload: "Completed uploading resource pack"
|
||||||
info.host.self.netty_server: "Netty HTTP server started on port: <arg:0>"
|
info.host.self.netty_server: "Netty HTTP server started on port: <arg:0>"
|
||||||
info.host.cache.load: "[<arg:0>] Loaded cached resource pack metadata"
|
info.host.cache.load: "[<arg:0>] Loaded cached resource pack metadata"
|
||||||
|
|||||||
@@ -40,14 +40,16 @@ argument.parse.failure.either: "<red>无法从 '<arg:0>' 解析 <arg:1> 或 <arg
|
|||||||
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' 不是颜色代码</red>"
|
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' 不是颜色代码</red>"
|
||||||
info.pack.load: "已加载包: <arg:0>. 默认命名空间: <arg:1>"
|
info.pack.load: "已加载包: <arg:0>. 默认命名空间: <arg:1>"
|
||||||
info.resource.load: "加载 <arg:0> 耗时 <arg:1>ms (<arg:2>)"
|
info.resource.load: "加载 <arg:0> 耗时 <arg:1>ms (<arg:2>)"
|
||||||
info.resource_pack.start: "正在开始生成资源包..."
|
info.resource_pack.generate.start: "正在开始生成资源包..."
|
||||||
info.resource_pack.generate: "生成资源包耗时 <arg:0>ms"
|
info.resource_pack.generate.finish: "生成资源包耗时 <arg:0>ms"
|
||||||
info.resource_pack.validate: "验证资源包耗时 <arg:0>ms"
|
info.resource_pack.validate.start: "正在验证资源包... (进度: <arg:0>/<arg:1> | 资源包格式: <arg:2>~<arg:3> | 叠加资源包: <arg:4>)"
|
||||||
info.resource_pack.optimize: "优化资源包耗时 <arg:0>ms"
|
info.resource_pack.validate.finish: "验证资源包耗时 <arg:0>ms"
|
||||||
info.resource_pack.optimize.json: "> 正在优化json文件..."
|
info.resource_pack.optimize.json: "> 正在优化json文件..."
|
||||||
info.resource_pack.optimize.texture: "> 正在优化贴图文件..."
|
info.resource_pack.optimize.texture: "> 正在优化贴图文件..."
|
||||||
info.resource_pack.optimize.result: "□ 优化前/优化后/比例: <arg:0>/<arg:1>/<arg:2>%"
|
info.resource_pack.optimize.result: "□ 优化前/优化后/比例: <arg:0>/<arg:1>/<arg:2>%"
|
||||||
info.resource_pack.create: "创建资源包文件耗时 <arg:0>ms"
|
info.resource_pack.optimize.finish: "优化资源包耗时 <arg:0>ms"
|
||||||
|
info.resource_pack.create.start: "正在创建资源包压缩文件..."
|
||||||
|
info.resource_pack.create.finish: "创建资源包文件耗时 <arg:0>ms"
|
||||||
info.resource_pack.upload: "资源包上传完成"
|
info.resource_pack.upload: "资源包上传完成"
|
||||||
info.host.self.netty_server: "Netty HTTP 服务已在端口 <arg:0> 开启"
|
info.host.self.netty_server: "Netty HTTP 服务已在端口 <arg:0> 开启"
|
||||||
info.host.cache.load: "[<arg:0>] 已加载缓存的资源包元数据"
|
info.host.cache.load: "[<arg:0>] 已加载缓存的资源包元数据"
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ public interface CustomBlock {
|
|||||||
@Nullable
|
@Nullable
|
||||||
LootTable<?> lootTable();
|
LootTable<?> lootTable();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
default String translationKey() {
|
||||||
|
Key id = id();
|
||||||
|
return "block." + id.namespace() + "." + id.value();
|
||||||
|
}
|
||||||
|
|
||||||
void execute(Context context, EventTrigger trigger);
|
void execute(Context context, EventTrigger trigger);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ public interface CustomFurniture {
|
|||||||
|
|
||||||
FurnitureSettings settings();
|
FurnitureSettings settings();
|
||||||
|
|
||||||
|
default String translationKey() {
|
||||||
|
Key id = this.id();
|
||||||
|
return "furniture." + id.namespace() + "." + id.value();
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
LootTable<?> lootTable();
|
LootTable<?> lootTable();
|
||||||
|
|
||||||
|
|||||||
@@ -89,30 +89,6 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected void applyDataModifiers(Map<String, Object> dataSection, Consumer<ItemDataModifier<I>> callback) {
|
|
||||||
ExceptionCollector<LocalizedResourceConfigException> errorCollector = new ExceptionCollector<>();
|
|
||||||
if (dataSection != null) {
|
|
||||||
for (Map.Entry<String, Object> dataEntry : dataSection.entrySet()) {
|
|
||||||
Object value = dataEntry.getValue();
|
|
||||||
if (value == null) continue;
|
|
||||||
String key = dataEntry.getKey();
|
|
||||||
int idIndex = key.indexOf('#');
|
|
||||||
if (idIndex != -1) {
|
|
||||||
key = key.substring(0, idIndex);
|
|
||||||
}
|
|
||||||
Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(key, Key.DEFAULT_NAMESPACE))).ifPresent(factory -> {
|
|
||||||
try {
|
|
||||||
callback.accept((ItemDataModifier<I>) factory.create(value));
|
|
||||||
} catch (LocalizedResourceConfigException e) {
|
|
||||||
errorCollector.add(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errorCollector.throwIfPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigParser[] parsers() {
|
public ConfigParser[] parsers() {
|
||||||
return new ConfigParser[]{this.itemParser, this.equipmentParser};
|
return new ConfigParser[]{this.itemParser, this.equipmentParser};
|
||||||
@@ -391,19 +367,19 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isModernFormatRequired() {
|
private boolean isModernFormatRequired() {
|
||||||
return Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4);
|
return Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsLegacyCompatibility() {
|
private boolean needsLegacyCompatibility() {
|
||||||
return Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4);
|
return Config.packMinVersion().isBelow(MinecraftVersion.V1_21_4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsCustomModelDataCompatibility() {
|
private boolean needsCustomModelDataCompatibility() {
|
||||||
return Config.packMinVersion().isBelow(MinecraftVersions.V1_21_2);
|
return Config.packMinVersion().isBelow(MinecraftVersion.V1_21_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsItemModelCompatibility() {
|
private boolean needsItemModelCompatibility() {
|
||||||
return Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && VersionHelper.isOrAbove1_21_2(); //todo 能否通过客户端包解决问题
|
return Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_2) && VersionHelper.isOrAbove1_21_2(); //todo 能否通过客户端包解决问题
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Key, IdAllocator> idAllocators() {
|
public Map<Key, IdAllocator> idAllocators() {
|
||||||
@@ -613,7 +589,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
|||||||
|
|
||||||
// 应用物品数据
|
// 应用物品数据
|
||||||
try {
|
try {
|
||||||
applyDataModifiers(MiscUtils.castToMap(section.get("data"), true), itemBuilder::dataModifier);
|
ItemDataModifiers.applyDataModifiers(MiscUtils.castToMap(section.get("data"), true), itemBuilder::dataModifier);
|
||||||
} catch (LocalizedResourceConfigException e) {
|
} catch (LocalizedResourceConfigException e) {
|
||||||
collector.add(e);
|
collector.add(e);
|
||||||
}
|
}
|
||||||
@@ -621,7 +597,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
|||||||
// 应用客户端侧数据
|
// 应用客户端侧数据
|
||||||
try {
|
try {
|
||||||
if (VersionHelper.PREMIUM) {
|
if (VersionHelper.PREMIUM) {
|
||||||
applyDataModifiers(MiscUtils.castToMap(section.get("client-bound-data"), true), itemBuilder::clientBoundDataModifier);
|
ItemDataModifiers.applyDataModifiers(MiscUtils.castToMap(section.get("client-bound-data"), true), itemBuilder::clientBoundDataModifier);
|
||||||
}
|
}
|
||||||
} catch (LocalizedResourceConfigException e) {
|
} catch (LocalizedResourceConfigException e) {
|
||||||
collector.add(e);
|
collector.add(e);
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ public interface CustomItem<I> extends BuildableItem<I> {
|
|||||||
|
|
||||||
UniqueKey uniqueId();
|
UniqueKey uniqueId();
|
||||||
|
|
||||||
|
default String translationKey() {
|
||||||
|
Key id = this.id();
|
||||||
|
return "item." + id.namespace() + "." + id.value();
|
||||||
|
}
|
||||||
|
|
||||||
Key material();
|
Key material();
|
||||||
|
|
||||||
Key clientBoundMaterial();
|
Key clientBoundMaterial();
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package net.momirealms.craftengine.core.item.modifier;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
|
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||||
|
import net.momirealms.craftengine.core.plugin.context.event.EventConditions;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class ConditionalModifier<I> implements ItemDataModifier<I> {
|
||||||
|
public static final Factory<?> FACTORY = new Factory<>();
|
||||||
|
private final Predicate<Context> condition;
|
||||||
|
private final ItemDataModifier<I>[] modifiers;
|
||||||
|
|
||||||
|
public ConditionalModifier(Predicate<Context> condition, ItemDataModifier<I>[] modifiers) {
|
||||||
|
this.modifiers = modifiers;
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Key type() {
|
||||||
|
return ItemDataModifiers.CONDITIONAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item<I> apply(Item<I> item, ItemBuildContext context) {
|
||||||
|
if (this.condition.test(context)) {
|
||||||
|
for (ItemDataModifier<I> m : this.modifiers) {
|
||||||
|
item = item.apply(m, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item<I> prepareNetworkItem(Item<I> item, ItemBuildContext context, CompoundTag networkData) {
|
||||||
|
if (this.condition.test(context)) {
|
||||||
|
for (ItemDataModifier<I> m : this.modifiers) {
|
||||||
|
item = m.prepareNetworkItem(item, context, networkData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory<I> implements ItemDataModifierFactory<I> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public ItemDataModifier<I> create(Object arg) {
|
||||||
|
Map<String, Object> conditionalData = ResourceConfigUtils.getAsMap(arg, "conditional");
|
||||||
|
List<Condition<Context>> conditions = ResourceConfigUtils.parseConfigAsList(conditionalData.get("conditions"), EventConditions::fromMap);
|
||||||
|
List<ItemDataModifier<I>> modifiers = new ArrayList<>();
|
||||||
|
ItemDataModifiers.applyDataModifiers(ResourceConfigUtils.getAsMap(conditionalData.get("data"), "conditional.data"), m -> modifiers.add((ItemDataModifier<I>) m));
|
||||||
|
return new ConditionalModifier<>(MiscUtils.allOf(conditions), modifiers.toArray(new ItemDataModifier[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,13 +4,19 @@ import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
|||||||
import net.momirealms.craftengine.core.item.modifier.lore.DynamicLoreModifier;
|
import net.momirealms.craftengine.core.item.modifier.lore.DynamicLoreModifier;
|
||||||
import net.momirealms.craftengine.core.item.modifier.lore.LoreModifier;
|
import net.momirealms.craftengine.core.item.modifier.lore.LoreModifier;
|
||||||
import net.momirealms.craftengine.core.item.modifier.lore.OverwritableLoreModifier;
|
import net.momirealms.craftengine.core.item.modifier.lore.OverwritableLoreModifier;
|
||||||
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
import net.momirealms.craftengine.core.registry.Registries;
|
import net.momirealms.craftengine.core.registry.Registries;
|
||||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||||
|
import net.momirealms.craftengine.core.util.ExceptionCollector;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public final class ItemDataModifiers {
|
public final class ItemDataModifiers {
|
||||||
private ItemDataModifiers() {}
|
private ItemDataModifiers() {}
|
||||||
|
|
||||||
@@ -51,6 +57,8 @@ public final class ItemDataModifiers {
|
|||||||
public static final Key OVERWRITABLE_LORE = Key.of("craftengine:overwritable-lore");
|
public static final Key OVERWRITABLE_LORE = Key.of("craftengine:overwritable-lore");
|
||||||
public static final Key MAX_DAMAGE = Key.of("craftengine:max-damage");
|
public static final Key MAX_DAMAGE = Key.of("craftengine:max-damage");
|
||||||
public static final Key BLOCK_STATE = Key.of("craftengine:block-state");
|
public static final Key BLOCK_STATE = Key.of("craftengine:block-state");
|
||||||
|
public static final Key CONDITIONAL = Key.of("craftengine:conditional");
|
||||||
|
public static final Key CONDITION = Key.of("craftengine:condition");
|
||||||
|
|
||||||
public static <T> void register(Key key, ItemDataModifierFactory<T> factory) {
|
public static <T> void register(Key key, ItemDataModifierFactory<T> factory) {
|
||||||
((WritableRegistry<ItemDataModifierFactory<?>>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY)
|
((WritableRegistry<ItemDataModifierFactory<?>>) BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY)
|
||||||
@@ -61,6 +69,30 @@ public final class ItemDataModifiers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <I> void applyDataModifiers(Map<String, Object> dataSection, Consumer<ItemDataModifier<I>> callback) {
|
||||||
|
ExceptionCollector<LocalizedResourceConfigException> errorCollector = new ExceptionCollector<>();
|
||||||
|
if (dataSection != null) {
|
||||||
|
for (Map.Entry<String, Object> dataEntry : dataSection.entrySet()) {
|
||||||
|
Object value = dataEntry.getValue();
|
||||||
|
if (value == null) continue;
|
||||||
|
String key = dataEntry.getKey();
|
||||||
|
int idIndex = key.indexOf('#');
|
||||||
|
if (idIndex != -1) {
|
||||||
|
key = key.substring(0, idIndex);
|
||||||
|
}
|
||||||
|
Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(key, Key.DEFAULT_NAMESPACE))).ifPresent(factory -> {
|
||||||
|
try {
|
||||||
|
callback.accept((ItemDataModifier<I>) factory.create(value));
|
||||||
|
} catch (LocalizedResourceConfigException e) {
|
||||||
|
errorCollector.add(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorCollector.throwIfPresent();
|
||||||
|
}
|
||||||
|
|
||||||
public static void init() {}
|
public static void init() {}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -106,5 +138,9 @@ public final class ItemDataModifiers {
|
|||||||
register(ITEM_MODEL, ItemModelModifier.FACTORY);
|
register(ITEM_MODEL, ItemModelModifier.FACTORY);
|
||||||
register(EQUIPPABLE, EquippableModifier.FACTORY);
|
register(EQUIPPABLE, EquippableModifier.FACTORY);
|
||||||
}
|
}
|
||||||
|
if (VersionHelper.PREMIUM) {
|
||||||
|
register(CONDITIONAL, ConditionalModifier.FACTORY);
|
||||||
|
register(CONDITION, ConditionalModifier.FACTORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
|||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class OverwritableItemModelModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
public class OverwritableItemModelModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||||
public static final Factory<?> FACTORY = new Factory<>();
|
public static final Factory<?> FACTORY = new Factory<>();
|
||||||
private final Key data;
|
private final Key data;
|
||||||
@@ -21,7 +24,7 @@ public class OverwritableItemModelModifier<I> implements SimpleNetworkItemDataMo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Key type() {
|
public Key type() {
|
||||||
return ItemDataModifiers.OVERWRITABLE_CUSTOM_MODEL_DATA;
|
return ItemDataModifiers.OVERWRITABLE_ITEM_MODEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.momirealms.craftengine.core.item.recipe.result;
|
package net.momirealms.craftengine.core.item.recipe.result;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||||
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifiers;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
import net.momirealms.craftengine.core.registry.Registries;
|
import net.momirealms.craftengine.core.registry.Registries;
|
||||||
@@ -22,10 +23,7 @@ public class PostProcessors {
|
|||||||
registerPostProcessorType(APPLY_DATA, args -> {
|
registerPostProcessorType(APPLY_DATA, args -> {
|
||||||
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
|
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
|
||||||
Map<String, Object> data = ResourceConfigUtils.getAsMap(args.get("data"), "data");
|
Map<String, Object> data = ResourceConfigUtils.getAsMap(args.get("data"), "data");
|
||||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
ItemDataModifiers.applyDataModifiers(data, modifiers::add);
|
||||||
Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(entry.getKey(), Key.DEFAULT_NAMESPACE)))
|
|
||||||
.ifPresent(factory -> modifiers.add(factory.create(entry.getValue())));
|
|
||||||
}
|
|
||||||
return new ApplyItemDataPostProcessor<>(modifiers.toArray(new ItemDataModifier[0]));
|
return new ApplyItemDataPostProcessor<>(modifiers.toArray(new ItemDataModifier[0]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.item.updater.impl;
|
|||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||||
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifiers;
|
||||||
import net.momirealms.craftengine.core.item.updater.ItemUpdater;
|
import net.momirealms.craftengine.core.item.updater.ItemUpdater;
|
||||||
import net.momirealms.craftengine.core.item.updater.ItemUpdaterType;
|
import net.momirealms.craftengine.core.item.updater.ItemUpdaterType;
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
@@ -39,10 +40,9 @@ public class ApplyDataOperation<I> implements ItemUpdater<I> {
|
|||||||
public ItemUpdater<I> create(Key item, Map<String, Object> args) {
|
public ItemUpdater<I> create(Key item, Map<String, Object> args) {
|
||||||
List<ItemDataModifier<I>> modifiers = new ArrayList<>();
|
List<ItemDataModifier<I>> modifiers = new ArrayList<>();
|
||||||
Map<String, Object> data = ResourceConfigUtils.getAsMap(args.get("data"), "data");
|
Map<String, Object> data = ResourceConfigUtils.getAsMap(args.get("data"), "data");
|
||||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
ItemDataModifiers.applyDataModifiers(data, m -> {
|
||||||
Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(entry.getKey(), Key.DEFAULT_NAMESPACE)))
|
modifiers.add((ItemDataModifier<I>) m);
|
||||||
.ifPresent(factory -> modifiers.add((ItemDataModifier<I>) factory.create(entry.getValue())));
|
});
|
||||||
}
|
|
||||||
return new ApplyDataOperation<>(modifiers);
|
return new ApplyDataOperation<>(modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.loot.function;
|
|||||||
import net.momirealms.craftengine.core.item.Item;
|
import net.momirealms.craftengine.core.item.Item;
|
||||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||||
|
import net.momirealms.craftengine.core.item.modifier.ItemDataModifiers;
|
||||||
import net.momirealms.craftengine.core.loot.LootConditions;
|
import net.momirealms.craftengine.core.loot.LootConditions;
|
||||||
import net.momirealms.craftengine.core.loot.LootContext;
|
import net.momirealms.craftengine.core.loot.LootContext;
|
||||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||||
@@ -42,10 +43,7 @@ public class ApplyDataFunction<T> extends AbstractLootConditionalFunction<T> {
|
|||||||
public LootFunction<A> create(Map<String, Object> arguments) {
|
public LootFunction<A> create(Map<String, Object> arguments) {
|
||||||
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
|
List<ItemDataModifier<?>> modifiers = new ArrayList<>();
|
||||||
Map<String, Object> data = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("data"), "warning.config.loot_table.function.apply_data.missing_data"), "data");
|
Map<String, Object> data = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(arguments.get("data"), "warning.config.loot_table.function.apply_data.missing_data"), "data");
|
||||||
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
ItemDataModifiers.applyDataModifiers(data, modifiers::add);
|
||||||
Optional.ofNullable(BuiltInRegistries.ITEM_DATA_MODIFIER_FACTORY.getValue(Key.withDefaultNamespace(entry.getKey(), Key.DEFAULT_NAMESPACE)))
|
|
||||||
.ifPresent(factory -> modifiers.add(factory.create(entry.getValue())));
|
|
||||||
}
|
|
||||||
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
|
||||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||||
.orElse(Collections.emptyList());
|
.orElse(Collections.emptyList());
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ import net.momirealms.craftengine.core.pack.conflict.resolution.ResolutionCondit
|
|||||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
import net.momirealms.craftengine.core.pack.host.ResourcePackHost;
|
||||||
import net.momirealms.craftengine.core.pack.host.ResourcePackHosts;
|
import net.momirealms.craftengine.core.pack.host.ResourcePackHosts;
|
||||||
import net.momirealms.craftengine.core.pack.host.impl.NoneHost;
|
import net.momirealms.craftengine.core.pack.host.impl.NoneHost;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.Overlay;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.PackMcMeta;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.PackVersion;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.overlay.OverlayCombination;
|
||||||
import net.momirealms.craftengine.core.pack.model.ItemModel;
|
import net.momirealms.craftengine.core.pack.model.ItemModel;
|
||||||
import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel;
|
import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel;
|
||||||
import net.momirealms.craftengine.core.pack.model.ModernItemModel;
|
import net.momirealms.craftengine.core.pack.model.ModernItemModel;
|
||||||
@@ -207,6 +211,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
VANILLA_TEXTURES.add(Key.of("minecraft", "font/unicode_page_" + String.format("%02x", i)));
|
VANILLA_TEXTURES.add(Key.of("minecraft", "font/unicode_page_" + String.format("%02x", i)));
|
||||||
}
|
}
|
||||||
|
VANILLA_TEXTURES.add(Key.of("minecraft", "missingno"));
|
||||||
loadInternalList("internal/textures/processed.json", VANILLA_TEXTURES::add);
|
loadInternalList("internal/textures/processed.json", VANILLA_TEXTURES::add);
|
||||||
loadInternalList("internal/sounds/processed.json", VANILLA_SOUNDS::add);
|
loadInternalList("internal/sounds/processed.json", VANILLA_SOUNDS::add);
|
||||||
|
|
||||||
@@ -740,8 +745,8 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateResourcePack() throws Exception {
|
public void generateResourcePack() {
|
||||||
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.start"));
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.generate.start"));
|
||||||
long time1 = System.currentTimeMillis();
|
long time1 = System.currentTimeMillis();
|
||||||
|
|
||||||
// Create cache data
|
// Create cache data
|
||||||
@@ -784,22 +789,36 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
this.generateClientLang(generatedPackPath);
|
this.generateClientLang(generatedPackPath);
|
||||||
this.generateEquipments(generatedPackPath, revisions::add);
|
this.generateEquipments(generatedPackPath, revisions::add);
|
||||||
this.generateParticle(generatedPackPath);
|
this.generateParticle(generatedPackPath);
|
||||||
this.generatePackMetadata(generatedPackPath.resolve("pack.mcmeta"), revisions);
|
|
||||||
|
Path packMcMetaPath = generatedPackPath.resolve("pack.mcmeta");
|
||||||
|
JsonObject packMcMeta = Files.isRegularFile(packMcMetaPath) ? GsonHelper.readJsonFile(packMcMetaPath).getAsJsonObject() : new JsonObject();
|
||||||
|
// 生成revision overlay
|
||||||
|
this.generateRevisionOverlays(packMcMeta, revisions);
|
||||||
|
|
||||||
if (Config.excludeShaders()) {
|
if (Config.excludeShaders()) {
|
||||||
this.removeAllShaders(generatedPackPath);
|
this.removeAllShaders(generatedPackPath);
|
||||||
}
|
}
|
||||||
long time2 = System.currentTimeMillis();
|
long time2 = System.currentTimeMillis();
|
||||||
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.generate", String.valueOf(time2 - time1)));
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.generate.finish", String.valueOf(time2 - time1)));
|
||||||
|
// 校验资源包
|
||||||
if (Config.validateResourcePack()) {
|
if (Config.validateResourcePack()) {
|
||||||
this.validateResourcePack(generatedPackPath);
|
this.validateResourcePack(generatedPackPath, packMcMeta);
|
||||||
}
|
}
|
||||||
long time3 = System.currentTimeMillis();
|
long time3 = System.currentTimeMillis();
|
||||||
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.validate", String.valueOf(time3 - time2)));
|
if (Config.validateResourcePack()) {
|
||||||
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.validate.finish", String.valueOf(time3 - time2)));
|
||||||
|
}
|
||||||
|
// 验证完成后,应该重新校验pack.mcmeta并写入
|
||||||
|
this.validatePackMetadata(generatedPackPath.resolve("pack.mcmeta"), packMcMeta);
|
||||||
|
// 优化资源包
|
||||||
if (Config.optimizeResourcePack()) {
|
if (Config.optimizeResourcePack()) {
|
||||||
this.optimizeResourcePack(generatedPackPath);
|
this.optimizeResourcePack(generatedPackPath);
|
||||||
}
|
}
|
||||||
long time4 = System.currentTimeMillis();
|
long time4 = System.currentTimeMillis();
|
||||||
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.optimize", String.valueOf(time4 - time3)));
|
if (Config.optimizeResourcePack()) {
|
||||||
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.optimize.finish", String.valueOf(time4 - time3)));
|
||||||
|
}
|
||||||
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.create.start"));
|
||||||
Path finalPath = resourcePackPath();
|
Path finalPath = resourcePackPath();
|
||||||
Files.createDirectories(finalPath.getParent());
|
Files.createDirectories(finalPath.getParent());
|
||||||
try {
|
try {
|
||||||
@@ -808,34 +827,69 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
this.plugin.logger().severe("Error zipping resource pack", e);
|
this.plugin.logger().severe("Error zipping resource pack", e);
|
||||||
}
|
}
|
||||||
long time5 = System.currentTimeMillis();
|
long time5 = System.currentTimeMillis();
|
||||||
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.create", String.valueOf(time5 - time4)));
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.create.finish", String.valueOf(time5 - time4)));
|
||||||
this.generationEventDispatcher.accept(generatedPackPath, finalPath);
|
this.generationEventDispatcher.accept(generatedPackPath, finalPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.plugin.logger().severe("Error generating resource pack", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePackMetadata(Path path, Set<Revision> revisions) throws IOException {
|
private void validatePackMetadata(Path path, JsonObject rawMeta) throws IOException {
|
||||||
JsonObject rawMeta;
|
// 获取设定的最大和最小值
|
||||||
boolean changed = false;
|
PackVersion minVersion = Config.packMinVersion().packFormat();
|
||||||
if (!Files.exists(path)) {
|
PackVersion maxVersion = Config.packMaxVersion().packFormat();
|
||||||
rawMeta = new JsonObject();
|
|
||||||
changed = true;
|
// 设置pack
|
||||||
} else {
|
{
|
||||||
rawMeta = GsonHelper.readJsonFile(path).getAsJsonObject();
|
JsonObject packJson = new JsonObject();
|
||||||
}
|
rawMeta.add("pack", packJson);
|
||||||
if (!rawMeta.has("pack")) {
|
JsonElement description = AdventureHelper.componentToJsonElement(AdventureHelper.miniMessage().deserialize(Config.packDescription()));
|
||||||
JsonObject pack = new JsonObject();
|
packJson.add("description", description);
|
||||||
rawMeta.add("pack", pack);
|
// 需要旧版本兼容性
|
||||||
pack.addProperty("pack_format", Config.packMinVersion().packFormat());
|
// https://minecraft.wiki/w/Java_Edition_25w31a
|
||||||
JsonObject supportedFormats = new JsonObject();
|
if (minVersion.isBelow(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
|
||||||
supportedFormats.addProperty("min_inclusive", Config.packMinVersion().packFormat());
|
packJson.addProperty("pack_format", minVersion.major());
|
||||||
supportedFormats.addProperty("max_inclusive", Config.packMaxVersion().packFormat());
|
JsonObject supportedVersions = new JsonObject();
|
||||||
pack.add("supported_formats", supportedFormats);
|
supportedVersions.addProperty("min_inclusive", minVersion.major());
|
||||||
changed = true;
|
supportedVersions.addProperty("max_inclusive", maxVersion.major());
|
||||||
}
|
packJson.add("supported_formats", supportedVersions);
|
||||||
if (revisions.isEmpty()) {
|
|
||||||
if (changed) {
|
|
||||||
GsonHelper.writeJsonFile(rawMeta, path);
|
|
||||||
}
|
}
|
||||||
|
// 到达了1.21.9
|
||||||
|
if (maxVersion.isAtOrAbove(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
|
||||||
|
// 同时要兼容低版本
|
||||||
|
packJson.add("min_format", minVersion.getAsJsonArray());
|
||||||
|
packJson.add("max_format", maxVersion.getAsJsonArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证overlay
|
||||||
|
{
|
||||||
|
PackMcMeta mcMeta = new PackMcMeta(rawMeta);
|
||||||
|
List<Overlay> overlays = mcMeta.overlays();
|
||||||
|
if (!overlays.isEmpty()) {
|
||||||
|
boolean legacySupported = false; // https://minecraft.wiki/w/Java_Edition_25w31a
|
||||||
|
for (Overlay overlay : overlays) {
|
||||||
|
if (overlay.minVersion().isBelow(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
|
||||||
|
legacySupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonArray newOverlayEntries = new JsonArray();
|
||||||
|
for (Overlay overlay : overlays) {
|
||||||
|
newOverlayEntries.add(overlay.getAsOverlayEntry(legacySupported));
|
||||||
|
}
|
||||||
|
JsonObject overlaysJson = new JsonObject();
|
||||||
|
overlaysJson.add("entries", newOverlayEntries);
|
||||||
|
rawMeta.add("overlays", overlaysJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GsonHelper.writeJsonFile(rawMeta, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里都是随便写写的,重点在之后的校验里
|
||||||
|
private void generateRevisionOverlays(JsonObject rawMeta, Set<Revision> revisions) throws IOException {
|
||||||
|
if (revisions.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JsonObject overlays;
|
JsonObject overlays;
|
||||||
@@ -854,22 +908,21 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
for (Revision revision : revisions) {
|
for (Revision revision : revisions) {
|
||||||
JsonObject entry = new JsonObject();
|
JsonObject entry = new JsonObject();
|
||||||
JsonObject formats = new JsonObject();
|
JsonArray formatsArray = new JsonArray();
|
||||||
entry.add("formats", formats);
|
entry.add("formats", formatsArray);
|
||||||
formats.addProperty("min_inclusive", revision.minPackVersion());
|
formatsArray.add(revision.minPackVersion().major());
|
||||||
formats.addProperty("max_inclusive", revision.maxPackVersion());
|
formatsArray.add(revision.maxPackVersion().major());
|
||||||
entry.addProperty("min_format", revision.minPackVersion());
|
entry.add("min_format", revision.minPackVersion().getAsJsonArray());
|
||||||
entry.addProperty("max_format", revision.maxPackVersion());
|
entry.add("max_format", revision.maxPackVersion().getAsJsonArray());
|
||||||
entry.addProperty("directory", Config.createOverlayFolderName(revision.versionString()));
|
entry.addProperty("directory", Config.createOverlayFolderName(revision.versionString()));
|
||||||
entries.add(entry);
|
entries.add(entry);
|
||||||
}
|
}
|
||||||
GsonHelper.writeJsonFile(rawMeta, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeAllShaders(Path path) {
|
private void removeAllShaders(Path path) {
|
||||||
List<Path> rootPaths;
|
List<Path> rootPaths;
|
||||||
try {
|
try {
|
||||||
rootPaths = FileUtils.collectOverlays(path);
|
rootPaths = MiscUtils.init(FileUtils.collectOverlays(path), a -> a.addFirst(path));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
plugin.logger().warn("Failed to collect overlays for " + path.toAbsolutePath(), e);
|
plugin.logger().warn("Failed to collect overlays for " + path.toAbsolutePath(), e);
|
||||||
return;
|
return;
|
||||||
@@ -889,7 +942,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
// 收集全部overlay
|
// 收集全部overlay
|
||||||
Path[] rootPaths;
|
Path[] rootPaths;
|
||||||
try {
|
try {
|
||||||
rootPaths = FileUtils.collectOverlays(path).toArray(new Path[0]);
|
rootPaths = MiscUtils.init(FileUtils.collectOverlays(path), a -> a.addFirst(path)).toArray(new Path[0]);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
this.plugin.logger().warn("Failed to collect overlays for " + path.toAbsolutePath(), e);
|
this.plugin.logger().warn("Failed to collect overlays for " + path.toAbsolutePath(), e);
|
||||||
return;
|
return;
|
||||||
@@ -1173,17 +1226,162 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
private void validateResourcePack(Path path, JsonObject packMetaJson) {
|
||||||
private void validateResourcePack(Path path) {
|
PackMcMeta packMeta = new PackMcMeta(packMetaJson);
|
||||||
// 收集全部overlay
|
List<OverlayCombination.Segment> segments = new ArrayList<>();
|
||||||
Path[] rootPaths;
|
// 完全小于1.21.11或完全大于1.21.11
|
||||||
try {
|
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_11) || Config.packMinVersion().isAtOrAbove(MinecraftVersion.V1_21_11)) {
|
||||||
rootPaths = FileUtils.collectOverlays(path).toArray(new Path[0]);
|
OverlayCombination combination = new OverlayCombination(packMeta.overlays(), Config.packMinVersion().majorPackFormat(), Config.packMaxVersion().majorPackFormat());
|
||||||
} catch (IOException e) {
|
while (combination.hasNext()) {
|
||||||
this.plugin.logger().warn("Failed to collect overlays for " + path.toAbsolutePath(), e);
|
OverlayCombination.Segment segment = combination.nextSegment();
|
||||||
return;
|
if (segment != null) {
|
||||||
|
segments.add(segment);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 混合版本
|
||||||
|
else {
|
||||||
|
OverlayCombination combinationLegacy = new OverlayCombination(packMeta.overlays(), Config.packMinVersion().majorPackFormat(), 72 /* 25w44a */);
|
||||||
|
while (combinationLegacy.hasNext()) {
|
||||||
|
OverlayCombination.Segment segment = combinationLegacy.nextSegment();
|
||||||
|
if (segment != null) {
|
||||||
|
segments.add(segment);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverlayCombination combinationModern = new OverlayCombination(packMeta.overlays(), 73 /* 25w45a */, Config.packMaxVersion().majorPackFormat());
|
||||||
|
while (combinationModern.hasNext()) {
|
||||||
|
OverlayCombination.Segment segment = combinationModern.nextSegment();
|
||||||
|
if (segment != null) {
|
||||||
|
segments.add(segment);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AtlasFixer itemFixer = new AtlasFixer();
|
||||||
|
AtlasFixer blockFixer = new AtlasFixer();
|
||||||
|
|
||||||
|
boolean hasNonOverlaySupport = false;
|
||||||
|
if (!segments.isEmpty()) {
|
||||||
|
// 第一个segment一定是最小的
|
||||||
|
hasNonOverlaySupport = segments.getFirst().min() <= MinecraftVersion.V1_20_1.packFormat().major();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0, size = segments.size(); i < size; i++) {
|
||||||
|
OverlayCombination.Segment segment = segments.get(i);
|
||||||
|
List<Path> rootPathList = new ArrayList<>();
|
||||||
|
rootPathList.add(path);
|
||||||
|
List<Overlay> overlayInOrder = new ArrayList<>(segment.overlays().size());
|
||||||
|
for (Overlay overlay : packMeta.overlays()) {
|
||||||
|
if (segment.overlays().contains(overlay)) {
|
||||||
|
Path resolve = path.resolve(overlay.directory());
|
||||||
|
if (Files.isDirectory(resolve)) {
|
||||||
|
overlayInOrder.add(overlay);
|
||||||
|
rootPathList.add(resolve);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.validate.start",
|
||||||
|
String.valueOf(i + 1), String.valueOf(size), String.valueOf(segment.min()), String.valueOf(segment.max()), overlayInOrder.stream().map(Overlay::directory).toList().toString()));
|
||||||
|
ValidationResult result = validateOverlayedResourcePack(rootPathList.toArray(new Path[0]), segment.max() >= MinecraftVersion.V1_21_11.packFormat().major());
|
||||||
|
if (Config.fixTextureAtlas() && !Config.enableObfuscation()) {
|
||||||
|
// 有修复物品
|
||||||
|
if (result.fixedItemAtlas != null) {
|
||||||
|
itemFixer.addEntry(segment.min(), segment.max(), result.fixedItemAtlas);
|
||||||
|
}
|
||||||
|
// 有修复方块
|
||||||
|
if (result.fixedBlockAtlas != null) {
|
||||||
|
blockFixer.addEntry(segment.min(), segment.max(), result.fixedBlockAtlas);
|
||||||
|
} else if (hasNonOverlaySupport) {
|
||||||
|
// 如果有低版本的支持,那么要通过overlay复原atlas
|
||||||
|
blockFixer.addEntry(segment.min(), segment.max(), Objects.requireNonNullElseGet(result.originalBlockAtlas, JsonObject::new));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试修复atlas
|
||||||
|
if (Config.fixTextureAtlas() && !Config.enableObfuscation()) {
|
||||||
|
Map<String, JsonObject> atlasToAdd = new LinkedHashMap<>();
|
||||||
|
// 物品
|
||||||
|
for (AtlasFixer.Entry entry : itemFixer.entries()) {
|
||||||
|
int min = entry.min();
|
||||||
|
int max = entry.max();
|
||||||
|
String directoryName = Config.createOverlayFolderName(min + "-" + max);
|
||||||
|
Path atlasPath = path.resolve(directoryName)
|
||||||
|
.resolve("assets")
|
||||||
|
.resolve("minecraft")
|
||||||
|
.resolve("atlases")
|
||||||
|
.resolve("items.json");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(atlasPath.getParent());
|
||||||
|
GsonHelper.writeJsonFile(entry.atlas(), atlasPath);
|
||||||
|
if (!atlasToAdd.containsKey(directoryName)) {
|
||||||
|
Overlay overlay = new Overlay(new PackVersion(min), new PackVersion(max), directoryName);
|
||||||
|
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry(true));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.plugin.logger().warn("Failed to write atlas " + atlasPath.toAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 方块
|
||||||
|
for (AtlasFixer.Entry entry : blockFixer.entries()) {
|
||||||
|
int min = entry.min();
|
||||||
|
int max = entry.max();
|
||||||
|
String directoryName = Config.createOverlayFolderName(min + "-" + max);
|
||||||
|
// 这个版本不认可overlay,得把atlas直接写进主包内
|
||||||
|
if (min <= MinecraftVersion.V1_20_1.packFormat().major()) {
|
||||||
|
Path atlasPath = path.resolve("assets")
|
||||||
|
.resolve("minecraft")
|
||||||
|
.resolve("atlases")
|
||||||
|
.resolve("blocks.json");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(atlasPath.getParent());
|
||||||
|
GsonHelper.writeJsonFile(entry.atlas(), atlasPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.plugin.logger().warn("Failed to write atlas " + atlasPath.toAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Path atlasPath = path.resolve(directoryName)
|
||||||
|
.resolve("assets")
|
||||||
|
.resolve("minecraft")
|
||||||
|
.resolve("atlases")
|
||||||
|
.resolve("blocks.json");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(atlasPath.getParent());
|
||||||
|
GsonHelper.writeJsonFile(entry.atlas(), atlasPath);
|
||||||
|
if (!atlasToAdd.containsKey(directoryName)) {
|
||||||
|
Overlay overlay = new Overlay(new PackVersion(min), new PackVersion(max), directoryName);
|
||||||
|
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry(true));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
this.plugin.logger().warn("Failed to write atlas " + atlasPath.toAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject overlaysJson = packMetaJson.getAsJsonObject("overlays");
|
||||||
|
if (overlaysJson == null) {
|
||||||
|
overlaysJson = new JsonObject();
|
||||||
|
packMetaJson.add("overlays", overlaysJson);
|
||||||
|
}
|
||||||
|
JsonArray overlayEntries = overlaysJson.getAsJsonArray("entries");
|
||||||
|
if (overlayEntries == null) {
|
||||||
|
overlayEntries = new JsonArray();
|
||||||
|
overlaysJson.add("entries", overlayEntries);
|
||||||
|
}
|
||||||
|
for (JsonElement entry : atlasToAdd.values()) {
|
||||||
|
overlayEntries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
|
private ValidationResult validateOverlayedResourcePack(Path[] rootPaths, boolean above1_21_11) {
|
||||||
Multimap<Key, Key> glyphToFonts = HashMultimap.create(128, 32); // 图片到字体的映射
|
Multimap<Key, Key> glyphToFonts = HashMultimap.create(128, 32); // 图片到字体的映射
|
||||||
Multimap<Key, Key> modelToItemDefinitions = HashMultimap.create(128, 4); // 模型到物品的映射
|
Multimap<Key, Key> modelToItemDefinitions = HashMultimap.create(128, 4); // 模型到物品的映射
|
||||||
Multimap<Key, String> modelToBlockStates = HashMultimap.create(128, 32); // 模型到方块的映射
|
Multimap<Key, String> modelToBlockStates = HashMultimap.create(128, 32); // 模型到方块的映射
|
||||||
@@ -1191,8 +1389,8 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
Multimap<Key, Key> textureToEquipments = HashMultimap.create(128, 8); // 纹理到盔甲的映射
|
Multimap<Key, Key> textureToEquipments = HashMultimap.create(128, 8); // 纹理到盔甲的映射
|
||||||
Multimap<Key, Key> oggToSoundEvents = HashMultimap.create(128, 4); // 音频到声音的映射
|
Multimap<Key, Key> oggToSoundEvents = HashMultimap.create(128, 4); // 音频到声音的映射
|
||||||
|
|
||||||
Map<Path, JsonObject> blockAtlasJsons = new LinkedHashMap<>();
|
JsonObject lastBlocksAtlas = null;
|
||||||
Map<Path, JsonObject> itemAtlasJsons = new LinkedHashMap<>();
|
JsonObject lastItemAtlas = null;
|
||||||
|
|
||||||
// 如果需要验证资源包,则需要先读取所有atlas
|
// 如果需要验证资源包,则需要先读取所有atlas
|
||||||
for (Path rootPath : rootPaths) {
|
for (Path rootPath : rootPaths) {
|
||||||
@@ -1203,37 +1401,27 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
.resolve("blocks.json");
|
.resolve("blocks.json");
|
||||||
if (Files.exists(blockAtlasFile)) {
|
if (Files.exists(blockAtlasFile)) {
|
||||||
try {
|
try {
|
||||||
JsonObject atlasJsonObject = GsonHelper.readJsonFile(blockAtlasFile).getAsJsonObject();
|
lastBlocksAtlas = GsonHelper.readJsonFile(blockAtlasFile).getAsJsonObject();
|
||||||
blockAtlasJsons.put(blockAtlasFile, atlasJsonObject);
|
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
TranslationManager.instance().log("warning.config.resource_pack.generation.malformatted_json", blockAtlasFile.toAbsolutePath().toString());
|
TranslationManager.instance().log("warning.config.resource_pack.generation.malformatted_json", blockAtlasFile.toAbsolutePath().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Path itemAtlasFile = rootPath
|
if (above1_21_11) {
|
||||||
.resolve("assets")
|
Path itemAtlasFile = rootPath
|
||||||
.resolve("minecraft")
|
.resolve("assets")
|
||||||
.resolve("atlases")
|
.resolve("minecraft")
|
||||||
.resolve("items.json");
|
.resolve("atlases")
|
||||||
if (Files.exists(itemAtlasFile)) {
|
.resolve("items.json");
|
||||||
try {
|
if (Files.exists(itemAtlasFile)) {
|
||||||
JsonObject atlasJsonObject = GsonHelper.readJsonFile(itemAtlasFile).getAsJsonObject();
|
try {
|
||||||
itemAtlasJsons.put(itemAtlasFile, atlasJsonObject);
|
lastItemAtlas = GsonHelper.readJsonFile(itemAtlasFile).getAsJsonObject();
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
TranslationManager.instance().log("warning.config.resource_pack.generation.malformatted_json", itemAtlasFile.toAbsolutePath().toString());
|
TranslationManager.instance().log("warning.config.resource_pack.generation.malformatted_json", itemAtlasFile.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加必要的基础atlas路径,方便后续修复
|
|
||||||
Path defaultBlockAtlas = path.resolve("assets").resolve("minecraft").resolve("atlases").resolve("blocks.json");
|
|
||||||
if (!blockAtlasJsons.containsKey(defaultBlockAtlas)) {
|
|
||||||
blockAtlasJsons.put(defaultBlockAtlas, new JsonObject());
|
|
||||||
}
|
|
||||||
Path defaultItemAtlas = path.resolve("assets").resolve("minecraft").resolve("atlases").resolve("items.json");
|
|
||||||
if (!itemAtlasJsons.containsKey(defaultItemAtlas)) {
|
|
||||||
itemAtlasJsons.put(defaultItemAtlas, new JsonObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
||||||
@@ -1242,16 +1430,15 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
Atlas blockAtlas = new Atlas(MiscUtils.make(new ArrayList<>(4), k -> {
|
Atlas blockAtlas;
|
||||||
k.add(blockAtlasJsons.get(defaultBlockAtlas));
|
Atlas itemAtlas;
|
||||||
k.add(this.vanillaBlockAtlas);
|
if (above1_21_11) {
|
||||||
return k;
|
blockAtlas = new Atlas(ListUtils.newNonNullList(lastBlocksAtlas, this.vanillaBlockAtlas));
|
||||||
}));
|
itemAtlas = new Atlas(ListUtils.newNonNullList(lastItemAtlas, this.vanillaItemAtlas));
|
||||||
Atlas itemAtlas = new Atlas(MiscUtils.make(new ArrayList<>(4), k -> {
|
} else {
|
||||||
k.add(itemAtlasJsons.get(defaultItemAtlas));
|
blockAtlas = new Atlas(ListUtils.newNonNullList(lastBlocksAtlas, this.vanillaBlockAtlas, this.vanillaItemAtlas));
|
||||||
k.add(this.vanillaItemAtlas);
|
itemAtlas = null;
|
||||||
return k;
|
}
|
||||||
}));
|
|
||||||
|
|
||||||
for (Path rootPath : rootPaths) {
|
for (Path rootPath : rootPaths) {
|
||||||
Path assetsPath = rootPath.resolve("assets");
|
Path assetsPath = rootPath.resolve("assets");
|
||||||
@@ -1263,7 +1450,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
namespaces = FileUtils.collectNamespaces(assetsPath);
|
namespaces = FileUtils.collectNamespaces(assetsPath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
this.plugin.logger().warn("Failed to collect namespaces for " + assetsPath.toAbsolutePath(), e);
|
this.plugin.logger().warn("Failed to collect namespaces for " + assetsPath.toAbsolutePath(), e);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Path namespacePath : namespaces) {
|
for (Path namespacePath : namespaces) {
|
||||||
@@ -1564,7 +1751,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
Key spritePath = texture.getValue();
|
Key spritePath = texture.getValue();
|
||||||
|
|
||||||
// 方块纹理不应该在item图集内,这样必然出问题
|
// 方块纹理不应该在item图集内,这样必然出问题
|
||||||
boolean definedInItemAtlas = itemAtlas.isDefined(spritePath);
|
boolean definedInItemAtlas = itemAtlas != null && itemAtlas.isDefined(spritePath);
|
||||||
if (definedInItemAtlas) {
|
if (definedInItemAtlas) {
|
||||||
TranslationManager.instance().log("warning.config.resource_pack.generation.multiple_atlases",
|
TranslationManager.instance().log("warning.config.resource_pack.generation.multiple_atlases",
|
||||||
entry.getKey().asString(), "minecraft:textures/atlas/blocks.png",
|
entry.getKey().asString(), "minecraft:textures/atlas/blocks.png",
|
||||||
@@ -1614,7 +1801,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
for (Map.Entry<String, Key> texture : textures.entrySet()) {
|
for (Map.Entry<String, Key> texture : textures.entrySet()) {
|
||||||
Key spritePath = texture.getValue();
|
Key spritePath = texture.getValue();
|
||||||
boolean definedInBlockAtlas = blockAtlas.isDefined(spritePath);
|
boolean definedInBlockAtlas = blockAtlas.isDefined(spritePath);
|
||||||
boolean definedInItemAtlas = itemAtlas.isDefined(spritePath);
|
boolean definedInItemAtlas = itemAtlas != null && itemAtlas.isDefined(spritePath);
|
||||||
|
|
||||||
// 双倍定义
|
// 双倍定义
|
||||||
if (definedInItemAtlas && definedInBlockAtlas) {
|
if (definedInItemAtlas && definedInBlockAtlas) {
|
||||||
@@ -1668,59 +1855,71 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
|
|
||||||
// 尝试修复
|
// 尝试修复
|
||||||
if (Config.fixTextureAtlas()) {
|
if (Config.fixTextureAtlas()) {
|
||||||
// 只用了方块图集,那么修复的东西丢方块图集
|
if (above1_21_11) {
|
||||||
if (blockAtlasInUse) {
|
// 只用了方块图集,那么修复的东西丢方块图集
|
||||||
|
if (blockAtlasInUse) {
|
||||||
|
for (Key key : tempTextureToFix) {
|
||||||
|
blockAtlasesToFix.put(key, entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 只用了物品图集,那么修复的东西丢物品图集
|
||||||
|
if (itemAtlasInUse) {
|
||||||
|
for (Key key : tempTextureToFix) {
|
||||||
|
itemAtlasesToFix.put(key, entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果都没有,先暂定
|
||||||
|
if (!itemAtlasInUse && !blockAtlasInUse) {
|
||||||
|
for (Key key : tempTextureToFix) {
|
||||||
|
anyAtlasesToFix.put(key, entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 对于较低的版本,全部塞blocks里
|
||||||
for (Key key : tempTextureToFix) {
|
for (Key key : tempTextureToFix) {
|
||||||
blockAtlasesToFix.put(key, entry.getKey());
|
blockAtlasesToFix.put(key, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 只用了物品图集,那么修复的东西丢物品图集
|
|
||||||
if (itemAtlasInUse) {
|
|
||||||
for (Key key : tempTextureToFix) {
|
|
||||||
itemAtlasesToFix.put(key, entry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 如果都没有,先暂定
|
|
||||||
if (!itemAtlasInUse && !blockAtlasInUse) {
|
|
||||||
for (Key key : tempTextureToFix) {
|
|
||||||
anyAtlasesToFix.put(key, entry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.fixTextureAtlas() && !Config.enableObfuscation()) {
|
ValidationResult result = null;
|
||||||
// 获取两个 Multimap 的所有 key
|
|
||||||
// 找出相同的 key
|
|
||||||
Set<Key> commonKeys = new LinkedHashSet<>(blockAtlasesToFix.keySet());
|
|
||||||
commonKeys.retainAll(itemAtlasesToFix.keySet());
|
|
||||||
|
|
||||||
// 都是有问题的模型
|
if (Config.fixTextureAtlas() && !Config.enableObfuscation()) {
|
||||||
if (!commonKeys.isEmpty()) {
|
|
||||||
for (Key sprite : commonKeys) {
|
if (above1_21_11) {
|
||||||
List<Key> duplicated = new ArrayList<>();
|
// 获取两个 Multimap 的所有 key
|
||||||
duplicated.addAll(blockAtlasesToFix.get(sprite));
|
// 找出相同的 key
|
||||||
duplicated.addAll(itemAtlasesToFix.get(sprite));
|
Set<Key> commonKeys = new LinkedHashSet<>(blockAtlasesToFix.keySet());
|
||||||
TranslationManager.instance().log("warning.config.resource_pack.generation.duplicated_sprite", duplicated.toString(), sprite.asString(), "minecraft:textures/atlas/blocks.png", "minecraft:textures/atlas/items.png");
|
commonKeys.retainAll(itemAtlasesToFix.keySet());
|
||||||
for (Key duplicatedModel : duplicated) {
|
|
||||||
// model已经塌房了,就不进入后续遍历了
|
// 都是有问题的模型
|
||||||
blockModels.remove(duplicatedModel);
|
if (!commonKeys.isEmpty()) {
|
||||||
itemModels.remove(duplicatedModel);
|
for (Key sprite : commonKeys) {
|
||||||
|
List<Key> duplicated = new ArrayList<>();
|
||||||
|
duplicated.addAll(blockAtlasesToFix.get(sprite));
|
||||||
|
duplicated.addAll(itemAtlasesToFix.get(sprite));
|
||||||
|
TranslationManager.instance().log("warning.config.resource_pack.generation.duplicated_sprite", duplicated.toString(), sprite.asString(), "minecraft:textures/atlas/blocks.png", "minecraft:textures/atlas/items.png");
|
||||||
|
for (Key duplicatedModel : duplicated) {
|
||||||
|
// model已经塌房了,就不进入后续遍历了
|
||||||
|
blockModels.remove(duplicatedModel);
|
||||||
|
itemModels.remove(duplicatedModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 将任意atlas的优先分配到items上,非必要不要到blocks上
|
// 将任意atlas的优先分配到items上,非必要不要到blocks上
|
||||||
for (Map.Entry<Key, Collection<Key>> entry : anyAtlasesToFix.asMap().entrySet()) {
|
for (Map.Entry<Key, Collection<Key>> entry : anyAtlasesToFix.asMap().entrySet()) {
|
||||||
if (blockAtlasesToFix.containsKey(entry.getKey())) {
|
if (blockAtlasesToFix.containsKey(entry.getKey())) {
|
||||||
blockAtlasesToFix.putAll(entry.getKey(), entry.getValue());
|
blockAtlasesToFix.putAll(entry.getKey(), entry.getValue());
|
||||||
} else {
|
} else {
|
||||||
itemAtlasesToFix.putAll(entry.getKey(), entry.getValue());
|
itemAtlasesToFix.putAll(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 清空任意atlas分配,因为已经重分配了
|
// 清空任意atlas分配,因为已经重分配了
|
||||||
anyAtlasesToFix.clear();
|
anyAtlasesToFix.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -1728,14 +1927,8 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
后续我们先对剩余的正常模型进行贴图路径验证(此阶段不验证那些存在atlas问题的模型,理论已被全部移除)
|
后续我们先对剩余的正常模型进行贴图路径验证(此阶段不验证那些存在atlas问题的模型,理论已被全部移除)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
JsonObject fixedItemAtlas = null;
|
||||||
// 如果最低支持版本太低了,那么全部塞blocks.json里
|
if (!itemAtlasesToFix.isEmpty() && itemAtlas != null) {
|
||||||
if (!Config.packMinVersion().isAtOrAbove(MinecraftVersions.V1_21_11)) {
|
|
||||||
blockAtlasesToFix.putAll(itemAtlasesToFix);
|
|
||||||
itemAtlasesToFix.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!itemAtlasesToFix.isEmpty()) {
|
|
||||||
List<JsonObject> sourcesToAdd = new ArrayList<>(itemAtlasesToFix.size());
|
List<JsonObject> sourcesToAdd = new ArrayList<>(itemAtlasesToFix.size());
|
||||||
for (Key itemTexture : itemAtlasesToFix.keySet()) {
|
for (Key itemTexture : itemAtlasesToFix.keySet()) {
|
||||||
itemAtlas.addSingle(itemTexture);
|
itemAtlas.addSingle(itemTexture);
|
||||||
@@ -1744,25 +1937,18 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
source.addProperty("resource", itemTexture.asString());
|
source.addProperty("resource", itemTexture.asString());
|
||||||
sourcesToAdd.add(source);
|
sourcesToAdd.add(source);
|
||||||
}
|
}
|
||||||
for (Map.Entry<Path, JsonObject> atlas : itemAtlasJsons.entrySet()) {
|
fixedItemAtlas = lastItemAtlas == null ? new JsonObject() : lastItemAtlas;
|
||||||
JsonObject right = atlas.getValue();
|
JsonArray sources = fixedItemAtlas.getAsJsonArray("sources");
|
||||||
JsonArray sources = right.getAsJsonArray("sources");
|
if (sources == null) {
|
||||||
if (sources == null) {
|
sources = new JsonArray();
|
||||||
sources = new JsonArray();
|
fixedItemAtlas.add("sources", sources);
|
||||||
right.add("sources", sources);
|
}
|
||||||
}
|
for (JsonObject source : sourcesToAdd) {
|
||||||
for (JsonObject source : sourcesToAdd) {
|
sources.add(source);
|
||||||
sources.add(source);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Files.createDirectories(atlas.getKey().getParent());
|
|
||||||
GsonHelper.writeJsonFile(right, atlas.getKey());
|
|
||||||
} catch (IOException e) {
|
|
||||||
this.plugin.logger().warn("Failed to write atlas to json file", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonObject fixedBlockAtlas = null;
|
||||||
if (!blockAtlasesToFix.isEmpty()) {
|
if (!blockAtlasesToFix.isEmpty()) {
|
||||||
List<JsonObject> sourcesToAdd = new ArrayList<>(blockAtlasesToFix.size());
|
List<JsonObject> sourcesToAdd = new ArrayList<>(blockAtlasesToFix.size());
|
||||||
for (Key blockTexture : blockAtlasesToFix.keySet()) {
|
for (Key blockTexture : blockAtlasesToFix.keySet()) {
|
||||||
@@ -1772,23 +1958,20 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
source.addProperty("resource", blockTexture.asString());
|
source.addProperty("resource", blockTexture.asString());
|
||||||
sourcesToAdd.add(source);
|
sourcesToAdd.add(source);
|
||||||
}
|
}
|
||||||
for (Map.Entry<Path, JsonObject> atlas : blockAtlasJsons.entrySet()) {
|
fixedBlockAtlas = lastBlocksAtlas == null ? new JsonObject() : lastBlocksAtlas;
|
||||||
JsonObject right = atlas.getValue();
|
JsonArray sources = fixedBlockAtlas.getAsJsonArray("sources");
|
||||||
JsonArray sources = right.getAsJsonArray("sources");
|
if (sources == null) {
|
||||||
if (sources == null) {
|
sources = new JsonArray();
|
||||||
sources = new JsonArray();
|
fixedBlockAtlas.add("sources", sources);
|
||||||
right.add("sources", sources);
|
|
||||||
}
|
|
||||||
for (JsonObject source : sourcesToAdd) {
|
|
||||||
sources.add(source);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Files.createDirectories(atlas.getKey().getParent());
|
|
||||||
GsonHelper.writeJsonFile(right, atlas.getKey());
|
|
||||||
} catch (IOException e) {
|
|
||||||
this.plugin.logger().warn("Failed to write atlas to json file", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (JsonObject source : sourcesToAdd) {
|
||||||
|
sources.add(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 至少有一个修复
|
||||||
|
if (fixedBlockAtlas != null || fixedItemAtlas != null) {
|
||||||
|
result = new ValidationResult(fixedItemAtlas, lastItemAtlas, fixedBlockAtlas, lastBlocksAtlas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1809,7 +1992,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
Map<String, Key> textures = entry.getValue().textures;
|
Map<String, Key> textures = entry.getValue().textures;
|
||||||
for (Map.Entry<String, Key> texture : textures.entrySet()) {
|
for (Map.Entry<String, Key> texture : textures.entrySet()) {
|
||||||
Key spritePath = texture.getValue();
|
Key spritePath = texture.getValue();
|
||||||
Key sourceTexturePath = itemAtlas.getSourceTexturePath(spritePath);
|
Key sourceTexturePath = itemAtlas == null ? null : itemAtlas.getSourceTexturePath(spritePath);
|
||||||
if (sourceTexturePath != null) {
|
if (sourceTexturePath != null) {
|
||||||
textureToModels.put(sourceTexturePath, entry.getKey());
|
textureToModels.put(sourceTexturePath, entry.getKey());
|
||||||
} else {
|
} else {
|
||||||
@@ -1832,12 +2015,23 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_model_texture", entry.getValue().stream().distinct().toList().toString(), texturePath);
|
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_model_texture", entry.getValue().toString(), texturePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
result = new ValidationResult(null, lastItemAtlas, null, lastBlocksAtlas);
|
||||||
|
}
|
||||||
|
|
||||||
// todo 验证 unstitch 和 paletted permutations
|
// todo 验证 unstitch 和 paletted permutations
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected record ValidationResult(JsonObject fixedItemAtlas,
|
||||||
|
JsonObject originalItemAtlas,
|
||||||
|
JsonObject fixedBlockAtlas,
|
||||||
|
JsonObject originalBlockAtlas) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 经过这一步拿到的模型为包含全部父贴图的模型
|
// 经过这一步拿到的模型为包含全部父贴图的模型
|
||||||
@@ -1968,7 +2162,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
|
|
||||||
private void generateParticle(Path generatedPackPath) {
|
private void generateParticle(Path generatedPackPath) {
|
||||||
if (!Config.removeTintedLeavesParticle()) return;
|
if (!Config.removeTintedLeavesParticle()) return;
|
||||||
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_5)) return;
|
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_5)) return;
|
||||||
JsonObject particleJson = new JsonObject();
|
JsonObject particleJson = new JsonObject();
|
||||||
JsonArray textures = new JsonArray();
|
JsonArray textures = new JsonArray();
|
||||||
textures.add("empty");
|
textures.add("empty");
|
||||||
@@ -2004,8 +2198,8 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
List<Tuple<Key, Boolean, Boolean>> collectedTrims = new ArrayList<>();
|
List<Tuple<Key, Boolean, Boolean>> collectedTrims = new ArrayList<>();
|
||||||
|
|
||||||
// 为trim类型提供的两个兼容性值
|
// 为trim类型提供的两个兼容性值
|
||||||
boolean needLegacyCompatibility = Config.packMinVersion().isBelow(MinecraftVersions.V1_21_2);
|
boolean needLegacyCompatibility = Config.packMinVersion().isBelow(MinecraftVersion.V1_21_2);
|
||||||
boolean needModernCompatibility = Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2);
|
boolean needModernCompatibility = Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_2);
|
||||||
|
|
||||||
for (Equipment equipment : this.plugin.itemManager().equipments().values()) {
|
for (Equipment equipment : this.plugin.itemManager().equipments().values()) {
|
||||||
if (equipment instanceof ComponentBasedEquipment componentBasedEquipment) {
|
if (equipment instanceof ComponentBasedEquipment componentBasedEquipment) {
|
||||||
@@ -2185,7 +2379,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) {
|
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_4)) {
|
||||||
Path equipmentPath = generatedPackPath
|
Path equipmentPath = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2218,7 +2412,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
this.plugin.logger().severe("Error writing equipment file", e);
|
this.plugin.logger().severe("Error writing equipment file", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4)) {
|
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_2) && Config.packMinVersion().isBelow(MinecraftVersion.V1_21_4)) {
|
||||||
Path equipmentPath = generatedPackPath
|
Path equipmentPath = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2274,7 +2468,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean shouldPreserve = false;
|
boolean shouldPreserve = false;
|
||||||
if (Config.packMinVersion().isBelow(MinecraftVersions.V1_21_2)) {
|
if (Config.packMinVersion().isBelow(MinecraftVersion.V1_21_2)) {
|
||||||
Path legacyTarget = generatedPackPath
|
Path legacyTarget = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2294,7 +2488,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
shouldPreserve = true;
|
shouldPreserve = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2)) {
|
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_2)) {
|
||||||
Path modernTarget = generatedPackPath
|
Path modernTarget = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2333,7 +2527,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
boolean shouldPreserve = false;
|
boolean shouldPreserve = false;
|
||||||
if (Config.packMinVersion().isBelow(MinecraftVersions.V1_21_2)) {
|
if (Config.packMinVersion().isBelow(MinecraftVersion.V1_21_2)) {
|
||||||
Path legacyTarget = generatedPackPath
|
Path legacyTarget = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2353,7 +2547,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
shouldPreserve = true;
|
shouldPreserve = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2)) {
|
if (Config.packMaxVersion().isAtOrAbove(MinecraftVersion.V1_21_2)) {
|
||||||
Path modernTarget = generatedPackPath
|
Path modernTarget = generatedPackPath
|
||||||
.resolve("assets")
|
.resolve("assets")
|
||||||
.resolve(assetId.namespace())
|
.resolve(assetId.namespace())
|
||||||
@@ -2636,8 +2830,8 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateModernItemModels1_21_2(Path generatedPackPath) {
|
private void generateModernItemModels1_21_2(Path generatedPackPath) {
|
||||||
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_2)) return;
|
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_2)) return;
|
||||||
if (Config.packMinVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) return;
|
if (Config.packMinVersion().isAtOrAbove(MinecraftVersion.V1_21_4)) return;
|
||||||
|
|
||||||
// 此段代码生成1.21.2专用的item model文件,情况非常复杂!
|
// 此段代码生成1.21.2专用的item model文件,情况非常复杂!
|
||||||
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().modernItemModels1_21_2().entrySet()) {
|
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().modernItemModels1_21_2().entrySet()) {
|
||||||
@@ -2719,7 +2913,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateModernItemModels1_21_4(Path generatedPackPath, Consumer<Revision> callback) {
|
private void generateModernItemModels1_21_4(Path generatedPackPath, Consumer<Revision> callback) {
|
||||||
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_4)) return;
|
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_4)) return;
|
||||||
for (Map.Entry<Key, ModernItemModel> entry : this.plugin.itemManager().modernItemModels1_21_4().entrySet()) {
|
for (Map.Entry<Key, ModernItemModel> entry : this.plugin.itemManager().modernItemModels1_21_4().entrySet()) {
|
||||||
Key key = entry.getKey();
|
Key key = entry.getKey();
|
||||||
Path itemPath = generatedPackPath
|
Path itemPath = generatedPackPath
|
||||||
@@ -2773,7 +2967,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateModernItemOverrides(Path generatedPackPath, Consumer<Revision> callback) {
|
private void generateModernItemOverrides(Path generatedPackPath, Consumer<Revision> callback) {
|
||||||
if (Config.packMaxVersion().isBelow(MinecraftVersions.V1_21_4)) return;
|
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_4)) return;
|
||||||
for (Map.Entry<Key, TreeMap<Integer, ModernItemModel>> entry : this.plugin.itemManager().modernItemOverrides().entrySet()) {
|
for (Map.Entry<Key, TreeMap<Integer, ModernItemModel>> entry : this.plugin.itemManager().modernItemOverrides().entrySet()) {
|
||||||
Key vanillaItemModel = entry.getKey();
|
Key vanillaItemModel = entry.getKey();
|
||||||
Path overridedItemPath = generatedPackPath
|
Path overridedItemPath = generatedPackPath
|
||||||
@@ -2864,7 +3058,7 @@ public abstract class AbstractPackManager implements PackManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateLegacyItemOverrides(Path generatedPackPath) {
|
private void generateLegacyItemOverrides(Path generatedPackPath) {
|
||||||
if (Config.packMinVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) return;
|
if (Config.packMinVersion().isAtOrAbove(MinecraftVersion.V1_21_4)) return;
|
||||||
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().legacyItemOverrides().entrySet()) {
|
for (Map.Entry<Key, TreeSet<LegacyOverridesModel>> entry : this.plugin.itemManager().legacyItemOverrides().entrySet()) {
|
||||||
Key vanillaLegacyModel = entry.getKey();
|
Key vanillaLegacyModel = entry.getKey();
|
||||||
Path overridedItemPath = generatedPackPath
|
Path overridedItemPath = generatedPackPath
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package net.momirealms.craftengine.core.pack;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class AtlasFixer {
|
||||||
|
private final List<Entry> entries;
|
||||||
|
|
||||||
|
public AtlasFixer() {
|
||||||
|
this.entries = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 理论是从小到大加的
|
||||||
|
public void addEntry(int min, int max, JsonObject atlas) {
|
||||||
|
if (this.entries.isEmpty()) {
|
||||||
|
this.entries.add(new Entry(min, max, atlas));
|
||||||
|
} else {
|
||||||
|
Entry last = this.entries.getLast();
|
||||||
|
// 相同则扩大区间
|
||||||
|
if (last.atlas.equals(atlas)) {
|
||||||
|
last.setMax(max);
|
||||||
|
}
|
||||||
|
// 不同则另加元素
|
||||||
|
else {
|
||||||
|
this.entries.add(new Entry(min, max, atlas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entry> entries() {
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class Entry {
|
||||||
|
private int min, max;
|
||||||
|
private final JsonObject atlas;
|
||||||
|
|
||||||
|
public Entry(int min, int max, JsonObject atlas) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.atlas = atlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int min() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int max() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject atlas() {
|
||||||
|
return atlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMin(int min) {
|
||||||
|
this.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(int max) {
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import net.momirealms.craftengine.core.plugin.Manageable;
|
|||||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ public final class Atlas {
|
|||||||
if (this.filtered.test(texture)) return null;
|
if (this.filtered.test(texture)) return null;
|
||||||
// single直接包含
|
// single直接包含
|
||||||
if (this.single.contains(texture)) return texture;
|
if (this.single.contains(texture)) return texture;
|
||||||
|
// 被unstitch或者调色盘定义
|
||||||
|
if (this.defined.contains(texture)) return null;
|
||||||
String path = texture.value();
|
String path = texture.value();
|
||||||
// 路径匹配
|
// 路径匹配
|
||||||
for (Map.Entry<String, String> entry : this.directory.entrySet()) {
|
for (Map.Entry<String, String> entry : this.directory.entrySet()) {
|
||||||
|
|||||||
@@ -6,30 +6,26 @@ import com.google.gson.JsonElement;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import net.momirealms.craftengine.core.pack.conflict.PathContext;
|
import net.momirealms.craftengine.core.pack.conflict.PathContext;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.PackVersion;
|
||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.Pair;
|
import net.momirealms.craftengine.core.util.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static net.momirealms.craftengine.core.pack.mcmeta.PackVersion.MAX_PACK_VERSION;
|
||||||
|
import static net.momirealms.craftengine.core.pack.mcmeta.PackVersion.MIN_PACK_VERSION;
|
||||||
|
|
||||||
public class ResolutionMergePackMcMeta implements Resolution {
|
public class ResolutionMergePackMcMeta implements Resolution {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
public static final Set<String> STANDARD_PACK_KEYS = ImmutableSet.of("pack", "features", "filter", "overlays", "language");
|
public static final Set<String> STANDARD_PACK_KEYS = ImmutableSet.of("pack", "features", "filter", "overlays", "language");
|
||||||
public static final PackVersion MIN_PACK_VERSION = new PackVersion(15, 0); // 1.20
|
|
||||||
public static final PackVersion MAX_PACK_VERSION = new PackVersion(1000, 0); // future
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
public ResolutionMergePackMcMeta(String description) {
|
public static void merge(Path file1, Path file2) throws IOException {
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void merge(Path file1, Path file2, JsonElement customDescription) throws IOException {
|
|
||||||
// 第一步,解析全部的mcmeta文件为json对象
|
// 第一步,解析全部的mcmeta文件为json对象
|
||||||
JsonObject mcmeta1;
|
JsonObject mcmeta1;
|
||||||
try {
|
try {
|
||||||
@@ -46,25 +42,37 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JsonObject merged = new JsonObject();
|
JsonObject merged = new JsonObject();
|
||||||
// 第三步,处理pack区域
|
|
||||||
JsonObject pack1 = mcmeta1.getAsJsonObject("pack");
|
// 注释: 无需处理,由后续验证合并
|
||||||
JsonObject pack2 = mcmeta2.getAsJsonObject("pack");
|
// //第二步,处理pack区域
|
||||||
JsonObject mergedPack = new JsonObject();
|
// JsonObject pack1 = mcmeta1.getAsJsonObject("pack");
|
||||||
mergedPack.add("description", customDescription);
|
// JsonObject pack2 = mcmeta2.getAsJsonObject("pack");
|
||||||
merged.add("pack", mergedPack);
|
// JsonObject mergedPack = new JsonObject();
|
||||||
mergePack(mergedPack, pack1, pack2);
|
// merged.add("pack", mergedPack);
|
||||||
|
// mergePack(mergedPack, pack1, pack2);
|
||||||
|
|
||||||
// 第三步,合并overlays
|
// 第三步,合并overlays
|
||||||
List<JsonObject> overlays = new ArrayList<>();
|
List<JsonObject> overlays = new ArrayList<>();
|
||||||
collectOverlays(mcmeta1.getAsJsonObject("overlays"), overlays::add);
|
collectOverlays(mcmeta1.getAsJsonObject("overlays"), overlays::add);
|
||||||
collectOverlays(mcmeta2.getAsJsonObject("overlays"), overlays::add);
|
collectOverlays(mcmeta2.getAsJsonObject("overlays"), overlays::add);
|
||||||
if (!overlays.isEmpty()) {
|
if (!overlays.isEmpty()) {
|
||||||
JsonObject mergedOverlay = new JsonObject();
|
Map<String, JsonObject> overlayMap = new LinkedHashMap<>();
|
||||||
JsonArray entries = new JsonArray();
|
for (JsonObject overlay : overlays) {
|
||||||
for (JsonObject entry : overlays) {
|
JsonPrimitive directory = overlay.getAsJsonPrimitive("directory");
|
||||||
entries.add(entry);
|
if (directory != null) {
|
||||||
|
// 名字相同的大概率内部版本也一致,不进一步处理了
|
||||||
|
overlayMap.put(directory.getAsString(), overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!overlayMap.isEmpty()) {
|
||||||
|
JsonObject mergedOverlay = new JsonObject();
|
||||||
|
JsonArray entries = new JsonArray();
|
||||||
|
for (JsonObject entry : overlayMap.values()) {
|
||||||
|
entries.add(entry);
|
||||||
|
}
|
||||||
|
mergedOverlay.add("entries", entries);
|
||||||
|
merged.add("overlays", mergedOverlay);
|
||||||
}
|
}
|
||||||
mergedOverlay.add("entries", entries);
|
|
||||||
merged.add("overlays", mergedOverlay);
|
|
||||||
}
|
}
|
||||||
// 第四步,合并filter
|
// 第四步,合并filter
|
||||||
List<JsonObject> filters = new ArrayList<>();
|
List<JsonObject> filters = new ArrayList<>();
|
||||||
@@ -150,110 +158,46 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
JsonObject entryJson = entry.getAsJsonObject();
|
JsonObject entryJson = entry.getAsJsonObject();
|
||||||
if (entryJson == null) continue;
|
if (entryJson == null) continue;
|
||||||
Pair<PackVersion, PackVersion> supportedVersions = getSupportedVersions(entryJson);
|
Pair<PackVersion, PackVersion> supportedVersions = getSupportedVersions(entryJson);
|
||||||
PackVersion min = supportedVersions.left();
|
PackVersion min = PackVersion.getHigher(supportedVersions.left(), PackVersion.MIN_OVERLAY_VERSION);
|
||||||
PackVersion max = supportedVersions.right();
|
PackVersion max = PackVersion.getHigher(supportedVersions.right(), PackVersion.MIN_OVERLAY_VERSION);
|
||||||
// 旧版格式支持
|
// 旧版格式支持
|
||||||
JsonObject supportedFormats = new JsonObject();
|
JsonArray supportedFormats = new JsonArray();
|
||||||
supportedFormats.addProperty("min_inclusive", min.major);
|
supportedFormats.add(min.major());
|
||||||
supportedFormats.addProperty("max_inclusive", max.major);
|
supportedFormats.add(max.major());
|
||||||
entryJson.add("formats", supportedFormats);
|
entryJson.add("formats", supportedFormats);
|
||||||
// 新版格式支持
|
// 新版格式支持
|
||||||
JsonArray minFormat = new JsonArray();
|
JsonArray minFormat = new JsonArray();
|
||||||
minFormat.add(min.major);
|
minFormat.add(min.major());
|
||||||
minFormat.add(min.minor);
|
minFormat.add(min.minor());
|
||||||
entryJson.add("min_format", minFormat);
|
entryJson.add("min_format", minFormat);
|
||||||
JsonArray maxFormat = new JsonArray();
|
JsonArray maxFormat = new JsonArray();
|
||||||
maxFormat.add(max.major);
|
maxFormat.add(max.major());
|
||||||
maxFormat.add(max.minor);
|
maxFormat.add(max.minor());
|
||||||
entryJson.add("max_format", maxFormat);
|
entryJson.add("max_format", maxFormat);
|
||||||
overlayCollector.accept(entryJson);
|
overlayCollector.accept(entryJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PackVersion(int major, int minor) implements Comparable<PackVersion> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(@NotNull ResolutionMergePackMcMeta.PackVersion o) {
|
|
||||||
// 首先比较 major 版本
|
|
||||||
int majorCompare = Integer.compare(this.major, o.major);
|
|
||||||
if (majorCompare != 0) {
|
|
||||||
return majorCompare;
|
|
||||||
}
|
|
||||||
// 如果 major 相同,则比较 minor 版本
|
|
||||||
return Integer.compare(this.minor, o.minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回两个版本中较小的那个(版本较低的)
|
|
||||||
*/
|
|
||||||
public static PackVersion getLower(PackVersion v1, PackVersion v2) {
|
|
||||||
if (v1 == null) return v2;
|
|
||||||
if (v2 == null) return v1;
|
|
||||||
return v1.compareTo(v2) <= 0 ? v1 : v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回两个版本中较大的那个(版本较高的)
|
|
||||||
*/
|
|
||||||
public static PackVersion getHigher(PackVersion v1, PackVersion v2) {
|
|
||||||
if (v1 == null) return v2;
|
|
||||||
if (v2 == null) return v1;
|
|
||||||
return v1.compareTo(v2) >= 0 ? v1 : v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PackVersion getLowest(List<PackVersion> versions) {
|
|
||||||
if (versions == null || versions.isEmpty()) {
|
|
||||||
return MIN_PACK_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackVersion lowest = versions.getFirst();
|
|
||||||
for (int i = 1; i < versions.size(); i++) {
|
|
||||||
lowest = getLower(lowest, versions.get(i));
|
|
||||||
}
|
|
||||||
return lowest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PackVersion getHighest(List<PackVersion> versions) {
|
|
||||||
if (versions == null || versions.isEmpty()) {
|
|
||||||
return MAX_PACK_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
PackVersion highest = versions.getFirst();
|
|
||||||
for (int i = 1; i < versions.size(); i++) {
|
|
||||||
highest = getHigher(highest, versions.get(i));
|
|
||||||
}
|
|
||||||
return highest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PackVersion parse(float num) {
|
|
||||||
String str = String.valueOf(num);
|
|
||||||
String[] parts = str.split("\\.");
|
|
||||||
int integerPart = Integer.parseInt(parts[0]);
|
|
||||||
int decimalPart = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
|
|
||||||
return new PackVersion(integerPart, decimalPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void mergePack(JsonObject merged, JsonObject pack1, JsonObject pack2) {
|
public static void mergePack(JsonObject merged, JsonObject pack1, JsonObject pack2) {
|
||||||
Pair<PackVersion, PackVersion> pack1Version = getSupportedVersions(pack1);
|
Pair<PackVersion, PackVersion> pack1Version = getSupportedVersions(pack1);
|
||||||
Pair<PackVersion, PackVersion> pack2Version = getSupportedVersions(pack2);
|
Pair<PackVersion, PackVersion> pack2Version = getSupportedVersions(pack2);
|
||||||
PackVersion min = PackVersion.getLower(pack1Version.left(), pack2Version.left());
|
PackVersion min = Config.packMinVersion().packFormat();
|
||||||
PackVersion max = PackVersion.getHigher(pack1Version.right(), pack2Version.right());
|
PackVersion max = PackVersion.getHigher(PackVersion.getHigher(pack1Version.right(), pack2Version.right()), Config.packMaxVersion().packFormat());
|
||||||
// 旧版格式支持
|
// 旧版格式支持
|
||||||
JsonObject supportedFormats = new JsonObject();
|
JsonObject supportedFormats = new JsonObject();
|
||||||
supportedFormats.addProperty("min_inclusive", min.major);
|
supportedFormats.addProperty("min_inclusive", min.major());
|
||||||
supportedFormats.addProperty("max_inclusive", max.major);
|
supportedFormats.addProperty("max_inclusive", max.major());
|
||||||
merged.add("supported_formats", supportedFormats);
|
merged.add("supported_formats", supportedFormats);
|
||||||
merged.addProperty("pack_format", min.major);
|
merged.addProperty("pack_format", min.major());
|
||||||
// 新版格式支持
|
// 新版格式支持
|
||||||
JsonArray minFormat = new JsonArray();
|
JsonArray minFormat = new JsonArray();
|
||||||
minFormat.add(min.major);
|
minFormat.add(min.major());
|
||||||
minFormat.add(min.minor);
|
minFormat.add(min.minor());
|
||||||
merged.add("min_format", minFormat);
|
merged.add("min_format", minFormat);
|
||||||
JsonArray maxFormat = new JsonArray();
|
JsonArray maxFormat = new JsonArray();
|
||||||
maxFormat.add(max.major);
|
maxFormat.add(max.major());
|
||||||
maxFormat.add(max.minor);
|
maxFormat.add(max.minor());
|
||||||
merged.add("max_format", maxFormat);
|
merged.add("max_format", maxFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,15 +241,15 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
case JsonArray array -> {
|
case JsonArray array -> {
|
||||||
if (array.isEmpty()) return Pair.of(MIN_PACK_VERSION, MAX_PACK_VERSION);
|
if (array.isEmpty()) return Pair.of(MIN_PACK_VERSION, MAX_PACK_VERSION);
|
||||||
if (array.size() == 1) {
|
if (array.size() == 1) {
|
||||||
return new Pair<>(new PackVersion(GsonHelper.getAsInt(array.get(0), MIN_PACK_VERSION.major), 0), MAX_PACK_VERSION);
|
return new Pair<>(new PackVersion(GsonHelper.getAsInt(array.get(0), MIN_PACK_VERSION.major()), 0), MAX_PACK_VERSION);
|
||||||
}
|
}
|
||||||
if (array.size() == 2) {
|
if (array.size() == 2) {
|
||||||
return new Pair<>(new PackVersion(GsonHelper.getAsInt(array.get(0), MIN_PACK_VERSION.major), 0), new PackVersion(GsonHelper.getAsInt(array.get(1), MAX_PACK_VERSION.major), 0));
|
return new Pair<>(new PackVersion(GsonHelper.getAsInt(array.get(0), MIN_PACK_VERSION.major()), 0), new PackVersion(GsonHelper.getAsInt(array.get(1), MAX_PACK_VERSION.major()), 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case JsonObject object -> {
|
case JsonObject object -> {
|
||||||
int min = GsonHelper.getAsInt(object.get("min_inclusive"), MIN_PACK_VERSION.major);
|
int min = GsonHelper.getAsInt(object.get("min_inclusive"), MIN_PACK_VERSION.major());
|
||||||
int max = GsonHelper.getAsInt(object.get("max_inclusive"), MAX_PACK_VERSION.major);
|
int max = GsonHelper.getAsInt(object.get("max_inclusive"), MAX_PACK_VERSION.major());
|
||||||
return new Pair<>(new PackVersion(min, 0), new PackVersion(max, 0));
|
return new Pair<>(new PackVersion(min, 0), new PackVersion(max, 0));
|
||||||
}
|
}
|
||||||
default -> {
|
default -> {
|
||||||
@@ -318,10 +262,10 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
if (format instanceof JsonArray array) {
|
if (format instanceof JsonArray array) {
|
||||||
if (array.isEmpty()) return defaultVersion;
|
if (array.isEmpty()) return defaultVersion;
|
||||||
if (array.size() == 1) {
|
if (array.size() == 1) {
|
||||||
return new PackVersion(GsonHelper.getAsInt(array.get(0), defaultVersion.major), 0);
|
return new PackVersion(GsonHelper.getAsInt(array.get(0), defaultVersion.major()), 0);
|
||||||
}
|
}
|
||||||
if (array.size() == 2) {
|
if (array.size() == 2) {
|
||||||
return new PackVersion(GsonHelper.getAsInt(array.get(0), defaultVersion.major), GsonHelper.getAsInt(array.get(1), defaultVersion.minor));
|
return new PackVersion(GsonHelper.getAsInt(array.get(0), defaultVersion.major()), GsonHelper.getAsInt(array.get(1), defaultVersion.minor()));
|
||||||
}
|
}
|
||||||
} else if (format instanceof JsonPrimitive jsonPrimitive) {
|
} else if (format instanceof JsonPrimitive jsonPrimitive) {
|
||||||
float version = jsonPrimitive.getAsFloat();
|
float version = jsonPrimitive.getAsFloat();
|
||||||
@@ -333,7 +277,7 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
@Override
|
@Override
|
||||||
public void run(PathContext existing, PathContext conflict) {
|
public void run(PathContext existing, PathContext conflict) {
|
||||||
try {
|
try {
|
||||||
merge(existing.path(), conflict.path(), AdventureHelper.componentToJsonElement(AdventureHelper.miniMessage().deserialize(this.description)));
|
merge(existing.path(), conflict.path());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CraftEngine.instance().logger().severe("Failed to merge pack.mcmeta when resolving file conflicts for '" + existing.path() + "' and '" + conflict.path() + "'", e);
|
CraftEngine.instance().logger().severe("Failed to merge pack.mcmeta when resolving file conflicts for '" + existing.path() + "' and '" + conflict.path() + "'", e);
|
||||||
}
|
}
|
||||||
@@ -347,8 +291,7 @@ public class ResolutionMergePackMcMeta implements Resolution {
|
|||||||
public static class Factory implements ResolutionFactory {
|
public static class Factory implements ResolutionFactory {
|
||||||
@Override
|
@Override
|
||||||
public Resolution create(Map<String, Object> arguments) {
|
public Resolution create(Map<String, Object> arguments) {
|
||||||
String description = arguments.getOrDefault("description", "<gray>CraftEngine ResourcePack</gray>").toString();
|
return new ResolutionMergePackMcMeta();
|
||||||
return new ResolutionMergePackMcMeta(description);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package net.momirealms.craftengine.core.pack.mcmeta;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||||
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
|
import net.momirealms.craftengine.core.util.Pair;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Overlay {
|
||||||
|
private final PackVersion minVersion;
|
||||||
|
private final PackVersion maxVersion;
|
||||||
|
private final String directory;
|
||||||
|
|
||||||
|
public Overlay(PackVersion minVersion,
|
||||||
|
PackVersion maxVersion,
|
||||||
|
String directory
|
||||||
|
) {
|
||||||
|
this.minVersion = minVersion;
|
||||||
|
this.maxVersion = maxVersion;
|
||||||
|
this.directory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Overlay(JsonObject overlay) {
|
||||||
|
this.directory = overlay.get("directory").getAsString();
|
||||||
|
Pair<PackVersion, PackVersion> supportedVersions = getSupportedVersions(overlay);
|
||||||
|
this.minVersion = supportedVersions.left();
|
||||||
|
this.maxVersion = supportedVersions.right();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Overlay{" +
|
||||||
|
"minVersion=" + minVersion +
|
||||||
|
", maxVersion=" + maxVersion +
|
||||||
|
", directory='" + directory + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject getAsOverlayEntry(boolean legacy) {
|
||||||
|
JsonObject entry = new JsonObject();
|
||||||
|
entry.addProperty("directory", this.directory);
|
||||||
|
JsonArray minFormat = new JsonArray();
|
||||||
|
minFormat.add(new JsonPrimitive(this.minVersion.major()));
|
||||||
|
minFormat.add(new JsonPrimitive(this.minVersion.minor()));
|
||||||
|
entry.add("min_format", minFormat);
|
||||||
|
JsonArray maxFormat = new JsonArray();
|
||||||
|
maxFormat.add(new JsonPrimitive(this.maxVersion.major()));
|
||||||
|
maxFormat.add(new JsonPrimitive(this.maxVersion.minor()));
|
||||||
|
entry.add("max_format", maxFormat);
|
||||||
|
if (legacy) {
|
||||||
|
JsonArray formats = new JsonArray();
|
||||||
|
formats.add(new JsonPrimitive(this.minVersion.major()));
|
||||||
|
formats.add(new JsonPrimitive(this.maxVersion.major()));
|
||||||
|
entry.add("formats", formats);
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackVersion minVersion() {
|
||||||
|
return minVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackVersion maxVersion() {
|
||||||
|
return maxVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String directory() {
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean test(MinecraftVersion version) {
|
||||||
|
return version.packFormat().isAtOrAbove(this.minVersion) && version.packFormat().isAtOrBelow(this.maxVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<PackVersion, PackVersion> getSupportedVersions(JsonObject pack) {
|
||||||
|
List<PackVersion> minVersions = new ArrayList<>();
|
||||||
|
List<PackVersion> maxVersions = new ArrayList<>();
|
||||||
|
if (pack.has("min_format")) {
|
||||||
|
minVersions.add(getFormatVersion(pack.get("min_format")));
|
||||||
|
}
|
||||||
|
if (pack.has("max_format")) {
|
||||||
|
maxVersions.add(getFormatVersion(pack.get("max_format")));
|
||||||
|
}
|
||||||
|
if (pack.has("formats")) {
|
||||||
|
Pair<PackVersion, PackVersion> supportedFormats = parseSupportedFormats(pack.get("formats"));
|
||||||
|
minVersions.add(supportedFormats.left());
|
||||||
|
maxVersions.add(supportedFormats.right());
|
||||||
|
}
|
||||||
|
return Pair.of(
|
||||||
|
PackVersion.getLowest(minVersions),
|
||||||
|
PackVersion.getHighest(maxVersions)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PackVersion getFormatVersion(JsonElement format) {
|
||||||
|
if (format instanceof JsonArray array) {
|
||||||
|
if (array.size() == 1) {
|
||||||
|
return new PackVersion(GsonHelper.getAsInt(array.get(0), 15), 0);
|
||||||
|
}
|
||||||
|
if (array.size() == 2) {
|
||||||
|
return new PackVersion(GsonHelper.getAsInt(array.get(0), 15), GsonHelper.getAsInt(array.get(1), 1000));
|
||||||
|
}
|
||||||
|
} else if (format instanceof JsonPrimitive jsonPrimitive) {
|
||||||
|
float version = jsonPrimitive.getAsFloat();
|
||||||
|
return PackVersion.parse(version);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown overlay version format: " + format);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pair<PackVersion, PackVersion> parseSupportedFormats(JsonElement formats) {
|
||||||
|
switch (formats) {
|
||||||
|
case JsonPrimitive jsonPrimitive -> {
|
||||||
|
return new Pair<>(new PackVersion(jsonPrimitive.getAsInt(), 0), new PackVersion(jsonPrimitive.getAsInt(), 0));
|
||||||
|
}
|
||||||
|
case JsonArray array -> {
|
||||||
|
if (array.size() == 2) {
|
||||||
|
return new Pair<>(new PackVersion(GsonHelper.getAsInt(array.get(0), 15), 0), new PackVersion(GsonHelper.getAsInt(array.get(1), 1000), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case JsonObject object -> {
|
||||||
|
int min = GsonHelper.getAsInt(object.get("min_inclusive"), 15);
|
||||||
|
int max = GsonHelper.getAsInt(object.get("max_inclusive"), 1000);
|
||||||
|
return new Pair<>(new PackVersion(min, 0), new PackVersion(max, 0));
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported overlay version format: " + formats);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package net.momirealms.craftengine.core.pack.mcmeta;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PackMcMeta {
|
||||||
|
private final List<Overlay> overlays;
|
||||||
|
|
||||||
|
public PackMcMeta(JsonObject mcmeta) {
|
||||||
|
this.overlays = getOverlays(mcmeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Overlay> getOverlays(JsonObject mcmeta) {
|
||||||
|
List<Overlay> overlays = new ArrayList<>();
|
||||||
|
JsonObject overlaysJson = mcmeta.getAsJsonObject("overlays");
|
||||||
|
if (overlaysJson != null) {
|
||||||
|
JsonArray entries = overlaysJson.getAsJsonArray("entries");
|
||||||
|
if (entries != null) {
|
||||||
|
for (JsonElement overlayJson : entries) {
|
||||||
|
if (overlayJson instanceof JsonObject overlayJsonObj) {
|
||||||
|
overlays.add(new Overlay(overlayJsonObj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return overlays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Overlay> overlays() {
|
||||||
|
return this.overlays;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package net.momirealms.craftengine.core.pack.mcmeta;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record PackVersion(int major, int minor) implements Comparable<PackVersion> {
|
||||||
|
public static final PackVersion MIN_PACK_VERSION = new PackVersion(15, 0); // 1.20
|
||||||
|
public static final PackVersion MIN_OVERLAY_VERSION = new PackVersion(18, 0); // 1.20
|
||||||
|
public static final PackVersion PACK_FORMAT_CHANGE_VERSION = new PackVersion(65, 0); // 25w31a
|
||||||
|
public static final PackVersion MAX_PACK_VERSION = new PackVersion(1000, 0); // future
|
||||||
|
|
||||||
|
public PackVersion(int major) {
|
||||||
|
this(major, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull PackVersion o) {
|
||||||
|
// 首先比较 major 版本
|
||||||
|
int majorCompare = Integer.compare(this.major, o.major);
|
||||||
|
if (majorCompare != 0) {
|
||||||
|
return majorCompare;
|
||||||
|
}
|
||||||
|
// 如果 major 相同,则比较 minor 版本
|
||||||
|
return Integer.compare(this.minor, o.minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAtOrAbove(PackVersion other) {
|
||||||
|
return this.compareTo(other) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAbove(PackVersion other) {
|
||||||
|
return this.compareTo(other) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAtOrBelow(PackVersion other) {
|
||||||
|
return this.compareTo(other) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBelow(PackVersion other) {
|
||||||
|
return this.compareTo(other) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String asString() {
|
||||||
|
if (this.minor == 0) {
|
||||||
|
return String.valueOf(this.major);
|
||||||
|
} else {
|
||||||
|
return this.major + "." + this.minor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonArray getAsJsonArray() {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
array.add(this.major);
|
||||||
|
array.add(this.minor);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回两个版本中较小的那个(版本较低的)
|
||||||
|
*/
|
||||||
|
public static PackVersion getLower(PackVersion v1, PackVersion v2) {
|
||||||
|
if (v1 == null) return v2;
|
||||||
|
if (v2 == null) return v1;
|
||||||
|
return v1.compareTo(v2) <= 0 ? v1 : v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回两个版本中较大的那个(版本较高的)
|
||||||
|
*/
|
||||||
|
public static PackVersion getHigher(PackVersion v1, PackVersion v2) {
|
||||||
|
if (v1 == null) return v2;
|
||||||
|
if (v2 == null) return v1;
|
||||||
|
return v1.compareTo(v2) >= 0 ? v1 : v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackVersion getLowest(List<PackVersion> versions) {
|
||||||
|
if (versions == null || versions.isEmpty()) {
|
||||||
|
return MIN_PACK_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackVersion lowest = versions.getFirst();
|
||||||
|
for (int i = 1; i < versions.size(); i++) {
|
||||||
|
lowest = getLower(lowest, versions.get(i));
|
||||||
|
}
|
||||||
|
return lowest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackVersion getHighest(List<PackVersion> versions) {
|
||||||
|
if (versions == null || versions.isEmpty()) {
|
||||||
|
return MAX_PACK_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackVersion highest = versions.getFirst();
|
||||||
|
for (int i = 1; i < versions.size(); i++) {
|
||||||
|
highest = getHigher(highest, versions.get(i));
|
||||||
|
}
|
||||||
|
return highest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PackVersion parse(float num) {
|
||||||
|
String str = String.valueOf(num);
|
||||||
|
String[] parts = str.split("\\.");
|
||||||
|
int integerPart = Integer.parseInt(parts[0]);
|
||||||
|
int decimalPart = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
|
||||||
|
return new PackVersion(integerPart, decimalPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package net.momirealms.craftengine.core.pack.mcmeta.overlay;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.Overlay;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class OverlayCombination {
|
||||||
|
private final List<VersionBasedEvent> versionBasedEvents;
|
||||||
|
private final List<Overlay> currentOverlays;
|
||||||
|
private int cursor;
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
public OverlayCombination(List<Overlay> overlays, int minVersion, int maxVersion) {
|
||||||
|
this.versionBasedEvents = new ArrayList<>();
|
||||||
|
this.currentOverlays = new ArrayList<>();
|
||||||
|
this.version = minVersion;
|
||||||
|
this.cursor = 0;
|
||||||
|
|
||||||
|
Map<Integer, List<Event>> eventsByVersion = new TreeMap<>();
|
||||||
|
eventsByVersion.computeIfAbsent(minVersion, k -> new ArrayList<>());
|
||||||
|
eventsByVersion.computeIfAbsent(maxVersion + 1, k -> new ArrayList<>());
|
||||||
|
for (Overlay overlay : overlays) {
|
||||||
|
if (overlay.minVersion().major() > maxVersion) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (overlay.maxVersion().major() < minVersion) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取最小中的较大值
|
||||||
|
int join = Math.max(overlay.minVersion().major(), minVersion);
|
||||||
|
// 去最大中的较小值
|
||||||
|
int leave = Math.min(overlay.maxVersion().major(), maxVersion);
|
||||||
|
List<Event> joinEvents = eventsByVersion.computeIfAbsent(join, k -> new ArrayList<>());
|
||||||
|
joinEvents.add(new Event(overlay, Operation.JOIN));
|
||||||
|
List<Event> leaveEvents = eventsByVersion.computeIfAbsent(leave + 1, k -> new ArrayList<>());
|
||||||
|
leaveEvents.add(new Event(overlay, Operation.LEAVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, List<Event>> entry : eventsByVersion.entrySet()) {
|
||||||
|
this.versionBasedEvents.add(new VersionBasedEvent(entry.getKey(), entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return this.cursor < this.versionBasedEvents.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public OverlayCombination.Segment nextSegment() {
|
||||||
|
Segment next = next();
|
||||||
|
if (next == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 第一次100%有问题
|
||||||
|
if (next.min > next.max) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private OverlayCombination.Segment next() {
|
||||||
|
// 已经没有事件里
|
||||||
|
if (this.cursor >= this.versionBasedEvents.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 获取事件
|
||||||
|
VersionBasedEvent events = this.versionBasedEvents.get(this.cursor++);
|
||||||
|
// 将上一个版本和上次记录的版本打为一个overlay返回
|
||||||
|
Segment segment = new Segment(this.version, events.version - 1, Set.copyOf(this.currentOverlays));
|
||||||
|
this.version = events.version;
|
||||||
|
// 变更当前成员
|
||||||
|
for (Event event : events.events) {
|
||||||
|
if (event.operation() == Operation.LEAVE) {
|
||||||
|
this.currentOverlays.remove(event.overlay);
|
||||||
|
} else if (event.operation() == Operation.JOIN) {
|
||||||
|
this.currentOverlays.add(event.overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Segment(int min, int max, Set<Overlay> overlays) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return "OverlaySegment{" +
|
||||||
|
"min=" + min +
|
||||||
|
", max=" + max +
|
||||||
|
", overlays=" + overlays +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record Event(Overlay overlay, Operation operation) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return "Event{" +
|
||||||
|
"overlay=" + overlay +
|
||||||
|
", operation=" + operation +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record VersionBasedEvent(int version, List<Event> events) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return "VersionBasedEvent{" +
|
||||||
|
"version=" + version +
|
||||||
|
", events=" + events +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Operation {
|
||||||
|
JOIN, LEAVE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import com.google.gson.JsonObject;
|
|||||||
import net.momirealms.craftengine.core.pack.revision.Revision;
|
import net.momirealms.craftengine.core.pack.revision.Revision;
|
||||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersions;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -33,13 +32,13 @@ public class ModernItemModel {
|
|||||||
|
|
||||||
public JsonObject toJson(MinecraftVersion version) {
|
public JsonObject toJson(MinecraftVersion version) {
|
||||||
JsonObject json = new JsonObject();
|
JsonObject json = new JsonObject();
|
||||||
if (this.oversizedInGui && version.isAtOrAbove(MinecraftVersions.V1_21_6)) {
|
if (this.oversizedInGui && version.isAtOrAbove(MinecraftVersion.V1_21_6)) {
|
||||||
json.addProperty("oversized_in_gui", true);
|
json.addProperty("oversized_in_gui", true);
|
||||||
}
|
}
|
||||||
if (!this.handAnimationOnSwap) {
|
if (!this.handAnimationOnSwap) {
|
||||||
json.addProperty("hand_animation_on_swap", false);
|
json.addProperty("hand_animation_on_swap", false);
|
||||||
}
|
}
|
||||||
if (this.swapAnimationScale != 1.0f && version.isAtOrAbove(MinecraftVersions.V1_21_11)) {
|
if (this.swapAnimationScale != 1.0f && version.isAtOrAbove(MinecraftVersion.V1_21_11)) {
|
||||||
json.addProperty("swap_animation_scale", this.swapAnimationScale);
|
json.addProperty("swap_animation_scale", this.swapAnimationScale);
|
||||||
}
|
}
|
||||||
json.add("model", this.itemModel.apply(version));
|
json.add("model", this.itemModel.apply(version));
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import net.momirealms.craftengine.core.pack.revision.Revision;
|
|||||||
import net.momirealms.craftengine.core.pack.revision.Revisions;
|
import net.momirealms.craftengine.core.pack.revision.Revisions;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersions;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -38,7 +37,7 @@ public class DisplayContextSelectProperty implements SelectProperty {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable JsonElement remap(JsonElement element, MinecraftVersion version) {
|
public @Nullable JsonElement remap(JsonElement element, MinecraftVersion version) {
|
||||||
if (version.isBelow(MinecraftVersions.V1_21_9) && element instanceof JsonPrimitive primitive && primitive.isString()) {
|
if (version.isBelow(MinecraftVersion.V1_21_9) && element instanceof JsonPrimitive primitive && primitive.isString()) {
|
||||||
if (primitive.getAsString().equals("on_shelf")) {
|
if (primitive.getAsString().equals("on_shelf")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import net.momirealms.craftengine.core.pack.revision.Revision;
|
|||||||
import net.momirealms.craftengine.core.pack.revision.Revisions;
|
import net.momirealms.craftengine.core.pack.revision.Revisions;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersions;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -31,7 +30,7 @@ public class PlayerHeadSpecialModel implements SpecialModel {
|
|||||||
@Override
|
@Override
|
||||||
public JsonObject apply(MinecraftVersion version) {
|
public JsonObject apply(MinecraftVersion version) {
|
||||||
JsonObject json = new JsonObject();
|
JsonObject json = new JsonObject();
|
||||||
if (version.isAtOrAbove(MinecraftVersions.V1_21_6)) {
|
if (version.isAtOrAbove(MinecraftVersion.V1_21_6)) {
|
||||||
json.addProperty("type", type().toString());
|
json.addProperty("type", type().toString());
|
||||||
} else {
|
} else {
|
||||||
json.addProperty("type", SpecialModels.HEAD.toString());
|
json.addProperty("type", SpecialModels.HEAD.toString());
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package net.momirealms.craftengine.core.pack.overlay;
|
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public class ResourcePackOverlay {
|
|
||||||
private final MinecraftVersion minVersion;
|
|
||||||
private final MinecraftVersion maxVersion;
|
|
||||||
private final Path folder;
|
|
||||||
|
|
||||||
public ResourcePackOverlay(MinecraftVersion minVersion,
|
|
||||||
MinecraftVersion maxVersion,
|
|
||||||
Path folder
|
|
||||||
) {
|
|
||||||
this.minVersion = minVersion;
|
|
||||||
this.maxVersion = maxVersion;
|
|
||||||
this.folder = folder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MinecraftVersion minVersion() {
|
|
||||||
return minVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MinecraftVersion maxVersion() {
|
|
||||||
return maxVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path folder() {
|
|
||||||
return folder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
package net.momirealms.craftengine.core.pack.revision;
|
package net.momirealms.craftengine.core.pack.revision;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.PackVersion;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersions;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public interface Revision {
|
public interface Revision {
|
||||||
|
|
||||||
int minPackVersion();
|
PackVersion minPackVersion();
|
||||||
|
|
||||||
int maxPackVersion();
|
PackVersion maxPackVersion();
|
||||||
|
|
||||||
String versionString();
|
String versionString();
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ public interface Revision {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MinecraftVersion maxVersion() {
|
public MinecraftVersion maxVersion() {
|
||||||
return MinecraftVersions.FUTURE;
|
return MinecraftVersion.FUTURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -48,7 +48,7 @@ public interface Revision {
|
|||||||
@Override
|
@Override
|
||||||
public String versionString() {
|
public String versionString() {
|
||||||
if (this.versionString == null) {
|
if (this.versionString == null) {
|
||||||
this.versionString = this.minVersion.version().replace(".", "_");
|
this.versionString = this.minVersion.packFormat().asString();
|
||||||
}
|
}
|
||||||
return this.versionString;
|
return this.versionString;
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,12 @@ public interface Revision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int maxPackVersion() {
|
public PackVersion maxPackVersion() {
|
||||||
return MinecraftVersions.FUTURE.packFormat();
|
return MinecraftVersion.FUTURE.packFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int minPackVersion() {
|
public PackVersion minPackVersion() {
|
||||||
return this.minVersion.packFormat();
|
return this.minVersion.packFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,19 +111,19 @@ public interface Revision {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int minPackVersion() {
|
public PackVersion minPackVersion() {
|
||||||
return this.minVersion.packFormat();
|
return this.minVersion.packFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int maxPackVersion() {
|
public PackVersion maxPackVersion() {
|
||||||
return this.maxVersion.packFormat();
|
return this.maxVersion.packFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String versionString() {
|
public String versionString() {
|
||||||
if (this.versionString == null) {
|
if (this.versionString == null) {
|
||||||
this.versionString = this.minVersion.version().replace(".", "_") + "-" + this.maxVersion.version().replace(".", "_");
|
this.versionString = this.minVersion.packFormat().asString() + "-" + this.maxVersion.packFormat().asString();
|
||||||
}
|
}
|
||||||
return this.versionString;
|
return this.versionString;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package net.momirealms.craftengine.core.pack.revision;
|
package net.momirealms.craftengine.core.pack.revision;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.MinecraftVersions;
|
import net.momirealms.craftengine.core.util.MinecraftVersion;
|
||||||
|
|
||||||
public final class Revisions {
|
public final class Revisions {
|
||||||
private Revisions() {}
|
private Revisions() {}
|
||||||
|
|
||||||
public static final Revision SINCE_1_21_6 = Revision.since(MinecraftVersions.V1_21_6);
|
public static final Revision SINCE_1_21_6 = Revision.since(MinecraftVersion.V1_21_6);
|
||||||
public static final Revision SINCE_1_21_2 = Revision.since(MinecraftVersions.V1_21_2);
|
public static final Revision SINCE_1_21_2 = Revision.since(MinecraftVersion.V1_21_2);
|
||||||
public static final Revision SINCE_1_21_9 = Revision.since(MinecraftVersions.V1_21_9);
|
public static final Revision SINCE_1_21_9 = Revision.since(MinecraftVersion.V1_21_9);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public class Config {
|
|||||||
protected List<String> resource_pack$merge_external_zips;
|
protected List<String> resource_pack$merge_external_zips;
|
||||||
protected Set<String> resource_pack$exclude_file_extensions;
|
protected Set<String> resource_pack$exclude_file_extensions;
|
||||||
protected Path resource_pack$path;
|
protected Path resource_pack$path;
|
||||||
|
protected String resource_pack$description;
|
||||||
|
|
||||||
protected boolean resource_pack$protection$crash_tools$method_1;
|
protected boolean resource_pack$protection$crash_tools$method_1;
|
||||||
protected boolean resource_pack$protection$crash_tools$method_2;
|
protected boolean resource_pack$protection$crash_tools$method_2;
|
||||||
@@ -329,6 +330,7 @@ public class Config {
|
|||||||
|
|
||||||
// resource pack
|
// resource pack
|
||||||
resource_pack$path = resolvePath(config.getString("resource-pack.path", "./generated/resource_pack.zip"));
|
resource_pack$path = resolvePath(config.getString("resource-pack.path", "./generated/resource_pack.zip"));
|
||||||
|
resource_pack$description = config.getString("resource-pack.description", "<gray>CraftEngine ResourcePack</gray>");
|
||||||
resource_pack$override_uniform_font = config.getBoolean("resource-pack.override-uniform-font", false);
|
resource_pack$override_uniform_font = config.getBoolean("resource-pack.override-uniform-font", false);
|
||||||
resource_pack$generate_mod_assets = config.getBoolean("resource-pack.generate-mod-assets", false);
|
resource_pack$generate_mod_assets = config.getBoolean("resource-pack.generate-mod-assets", false);
|
||||||
resource_pack$remove_tinted_leaves_particle = config.getBoolean("resource-pack.remove-tinted-leaves-particle", true);
|
resource_pack$remove_tinted_leaves_particle = config.getBoolean("resource-pack.remove-tinted-leaves-particle", true);
|
||||||
@@ -609,12 +611,12 @@ public class Config {
|
|||||||
|
|
||||||
private static MinecraftVersion getVersion(String version) {
|
private static MinecraftVersion getVersion(String version) {
|
||||||
if (version.equalsIgnoreCase("latest")) {
|
if (version.equalsIgnoreCase("latest")) {
|
||||||
return new MinecraftVersion(PluginProperties.getValue("latest-version"));
|
return MinecraftVersion.byName(PluginProperties.getValue("latest-version"));
|
||||||
}
|
}
|
||||||
if (version.equalsIgnoreCase("server")) {
|
if (version.equalsIgnoreCase("server")) {
|
||||||
return VersionHelper.MINECRAFT_VERSION;
|
return VersionHelper.MINECRAFT_VERSION;
|
||||||
}
|
}
|
||||||
return MinecraftVersion.parse(version);
|
return MinecraftVersion.byName(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Locale forcedLocale() {
|
public static Locale forcedLocale() {
|
||||||
@@ -1130,6 +1132,10 @@ public class Config {
|
|||||||
return instance.equipment$sacrificed_vanilla_armor$humanoid_leggings;
|
return instance.equipment$sacrificed_vanilla_armor$humanoid_leggings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String packDescription() {
|
||||||
|
return instance.resource_pack$description;
|
||||||
|
}
|
||||||
|
|
||||||
public static String sacrificedVanillaArmorType() {
|
public static String sacrificedVanillaArmorType() {
|
||||||
return instance.equipment$sacrificed_vanilla_armor$type;
|
return instance.equipment$sacrificed_vanilla_armor$type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ import java.util.Optional;
|
|||||||
public class MerchantTradeFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
public class MerchantTradeFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||||
private final String title;
|
private final String title;
|
||||||
private final PlayerSelector<CTX> selector;
|
private final PlayerSelector<CTX> selector;
|
||||||
private final LazyReference<List<MerchantOffer<?>>> offers;
|
private final java.util.function.Function<Player, List<MerchantOffer<?>>> offers;
|
||||||
|
|
||||||
public MerchantTradeFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, String title, LazyReference<List<MerchantOffer<?>>> offers) {
|
public MerchantTradeFunction(List<Condition<CTX>> predicates, @Nullable PlayerSelector<CTX> selector, String title, java.util.function.Function<Player, List<MerchantOffer<?>>> offers) {
|
||||||
super(predicates);
|
super(predicates);
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
@@ -38,12 +38,12 @@ public class MerchantTradeFunction<CTX extends Context> extends AbstractConditio
|
|||||||
public void runInternal(CTX ctx) {
|
public void runInternal(CTX ctx) {
|
||||||
if (this.selector == null) {
|
if (this.selector == null) {
|
||||||
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
|
ctx.getOptionalParameter(DirectContextParameters.PLAYER).ifPresent(it -> {
|
||||||
CraftEngine.instance().guiManager().openMerchant(it, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, ctx.tagResolvers()), this.offers.get());
|
CraftEngine.instance().guiManager().openMerchant(it, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, ctx.tagResolvers()), this.offers.apply(it));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (Player viewer : this.selector.get(ctx)) {
|
for (Player viewer : this.selector.get(ctx)) {
|
||||||
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
|
RelationalContext relationalContext = ViewerContext.of(ctx, PlayerOptionalContext.of(viewer));
|
||||||
CraftEngine.instance().guiManager().openMerchant(viewer, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, relationalContext.tagResolvers()), this.offers.get());
|
CraftEngine.instance().guiManager().openMerchant(viewer, this.title == null ? null : AdventureHelper.miniMessage().deserialize(this.title, relationalContext.tagResolvers()), this.offers.apply(viewer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,27 +71,27 @@ public class MerchantTradeFunction<CTX extends Context> extends AbstractConditio
|
|||||||
return new TempOffer(cost1, cost2, result, exp);
|
return new TempOffer(cost1, cost2, result, exp);
|
||||||
});
|
});
|
||||||
return new MerchantTradeFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), title,
|
return new MerchantTradeFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), title,
|
||||||
LazyReference.lazyReference(() -> {
|
(player) -> {
|
||||||
List<MerchantOffer<?>> offers = new ArrayList<>(merchantOffers.size());
|
List<MerchantOffer<?>> offers = new ArrayList<>(merchantOffers.size());
|
||||||
for (TempOffer offer : merchantOffers) {
|
for (TempOffer offer : merchantOffers) {
|
||||||
Item cost1 = parseIngredient(offer.cost1);
|
Item cost1 = parseIngredient(offer.cost1, player);
|
||||||
Optional cost2 = Optional.ofNullable(parseIngredient(offer.cost2));
|
Optional cost2 = Optional.ofNullable(parseIngredient(offer.cost2, player));
|
||||||
Item result = parseIngredient(offer.result);
|
Item result = parseIngredient(offer.result, player);
|
||||||
offers.add(new MerchantOffer<>(cost1, cost2, result, false, 0, Integer.MAX_VALUE, offer.exp, 0, 0, 0));
|
offers.add(new MerchantOffer<>(cost1, cost2, result, false, 0, Integer.MAX_VALUE, offer.exp, 0, 0, 0));
|
||||||
}
|
}
|
||||||
return offers;
|
return offers;
|
||||||
}));
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public record TempOffer(Object cost1, Object cost2, Object result, int exp) {
|
public record TempOffer(Object cost1, Object cost2, Object result, int exp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Item<?> parseIngredient(Object arguments) {
|
private Item<?> parseIngredient(Object arguments, Player player) {
|
||||||
if (arguments == null) return null;
|
if (arguments == null) return null;
|
||||||
if (arguments instanceof Map<?,?> map) {
|
if (arguments instanceof Map<?,?> map) {
|
||||||
Map<String, Object> args = MiscUtils.castToMap(map, false);
|
Map<String, Object> args = MiscUtils.castToMap(map, false);
|
||||||
String itemName = args.getOrDefault("item", "minecraft:stone").toString();
|
String itemName = args.getOrDefault("item", "minecraft:stone").toString();
|
||||||
Item<Object> item = createSafeItem(itemName);
|
Item<Object> item = createSafeItem(itemName, player);
|
||||||
if (args.containsKey("count")) {
|
if (args.containsKey("count")) {
|
||||||
item.count(ResourceConfigUtils.getAsInt(args.get("count"), "count"));
|
item.count(ResourceConfigUtils.getAsInt(args.get("count"), "count"));
|
||||||
}
|
}
|
||||||
@@ -104,15 +104,15 @@ public class MerchantTradeFunction<CTX extends Context> extends AbstractConditio
|
|||||||
return item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
String itemName = arguments.toString();
|
String itemName = arguments.toString();
|
||||||
return createSafeItem(itemName);
|
return createSafeItem(itemName, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Item<Object> createSafeItem(String itemName) {
|
private Item<Object> createSafeItem(String itemName, Player player) {
|
||||||
Key itemId = Key.of(itemName);
|
Key itemId = Key.of(itemName);
|
||||||
Item<Object> item = CraftEngine.instance().itemManager().createWrappedItem(itemId, null);
|
Item<Object> item = CraftEngine.instance().itemManager().createWrappedItem(itemId, player);
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
item = CraftEngine.instance().itemManager().createWrappedItem(ItemKeys.STONE, null);
|
item = CraftEngine.instance().itemManager().createWrappedItem(ItemKeys.STONE, player);
|
||||||
assert item != null;
|
assert item != null;
|
||||||
item.itemNameComponent(Component.text(itemName).color(NamedTextColor.RED));
|
item.itemNameComponent(Component.text(itemName).color(NamedTextColor.RED));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,18 @@ public class LangData {
|
|||||||
if (id.contains("[") && id.contains("]")) {
|
if (id.contains("[") && id.contains("]")) {
|
||||||
ImmutableBlockState parsed = BlockStateParser.deserialize(id);
|
ImmutableBlockState parsed = BlockStateParser.deserialize(id);
|
||||||
if (parsed == null) return List.of(id);
|
if (parsed == null) return List.of(id);
|
||||||
return List.of("block." + stateToRealBlockId(parsed));
|
return List.of(translationKey(parsed));
|
||||||
} else {
|
} else {
|
||||||
Key blockId = Key.of(id);
|
Key blockId = Key.of(id);
|
||||||
Optional<CustomBlock> blockOptional = CraftEngine.instance().blockManager().blockById(blockId);
|
Optional<CustomBlock> blockOptional = CraftEngine.instance().blockManager().blockById(blockId);
|
||||||
if (blockOptional.isPresent()) {
|
if (blockOptional.isPresent()) {
|
||||||
List<ImmutableBlockState> states = blockOptional.get().variantProvider().states();
|
List<ImmutableBlockState> states = blockOptional.get().variantProvider().states();
|
||||||
if (states.size() == 1) {
|
if (states.size() == 1) {
|
||||||
return List.of("block." + stateToRealBlockId(states.getFirst()));
|
return List.of(translationKey(states.getFirst()));
|
||||||
} else {
|
} else {
|
||||||
ArrayList<String> processed = new ArrayList<>();
|
ArrayList<String> processed = new ArrayList<>();
|
||||||
for (ImmutableBlockState state : states) {
|
for (ImmutableBlockState state : states) {
|
||||||
processed.add("block." + stateToRealBlockId(state));
|
processed.add(translationKey(state));
|
||||||
}
|
}
|
||||||
return processed;
|
return processed;
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ public class LangData {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String stateToRealBlockId(ImmutableBlockState state) {
|
public static String translationKey(ImmutableBlockState state) {
|
||||||
String id = state.customBlockState().literalObject().toString();
|
String id = state.customBlockState().literalObject().toString();
|
||||||
int first = -1, last = -1;
|
int first = -1, last = -1;
|
||||||
for (int i = 0; i < id.length(); i++) {
|
for (int i = 0; i < id.length(); i++) {
|
||||||
@@ -113,6 +113,6 @@ public class LangData {
|
|||||||
chars[i] = '.';
|
chars[i] = '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new String(chars);
|
return "block." + new String(chars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
@@ -67,9 +68,21 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Path> collectOverlays(Path resourcePackFolder, Predicate<String> directoryPredicate) throws IOException {
|
||||||
|
List<Path> folders = new ObjectArrayList<>();
|
||||||
|
try (Stream<Path> paths = Files.list(resourcePackFolder)) {
|
||||||
|
folders.addAll(paths
|
||||||
|
.filter(Files::isDirectory)
|
||||||
|
.filter(path -> directoryPredicate.test(path.getFileName().toString()))
|
||||||
|
.filter(path -> !path.getFileName().toString().equals("assets"))
|
||||||
|
.filter(path -> Files.exists(path.resolve("assets")))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
return folders;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Path> collectOverlays(Path resourcePackFolder) throws IOException {
|
public static List<Path> collectOverlays(Path resourcePackFolder) throws IOException {
|
||||||
List<Path> folders = new ObjectArrayList<>();
|
List<Path> folders = new ObjectArrayList<>();
|
||||||
folders.add(resourcePackFolder);
|
|
||||||
try (Stream<Path> paths = Files.list(resourcePackFolder)) {
|
try (Stream<Path> paths = Files.list(resourcePackFolder)) {
|
||||||
folders.addAll(paths
|
folders.addAll(paths
|
||||||
.filter(Files::isDirectory)
|
.filter(Files::isDirectory)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.core.util;
|
package net.momirealms.craftengine.core.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,4 +14,13 @@ public final class ListUtils {
|
|||||||
if (list.size() == 2) return List.of(list.get(0), list.get(1));
|
if (list.size() == 2) return List.of(list.get(0), list.get(1));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public static <T> List<T> newNonNullList(T... elements) {
|
||||||
|
List<T> list = new ArrayList<>(elements.length);
|
||||||
|
for (T element : elements) {
|
||||||
|
if (element != null) list.add(element);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,132 @@
|
|||||||
package net.momirealms.craftengine.core.util;
|
package net.momirealms.craftengine.core.util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import java.util.Map;
|
import com.google.common.collect.Multimap;
|
||||||
|
import net.momirealms.craftengine.core.pack.mcmeta.PackVersion;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MinecraftVersion implements Comparable<MinecraftVersion> {
|
||||||
|
private static final Map<Integer, PackVersion> PACK_FORMATS = new HashMap<>();
|
||||||
|
|
||||||
public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
|
||||||
public static final Map<Integer, Integer> PACK_FORMATS = new HashMap<>();
|
|
||||||
static {
|
static {
|
||||||
PACK_FORMATS.put(1_20_00, 15);
|
PACK_FORMATS.put(1_16_00, new PackVersion(5, 0));
|
||||||
PACK_FORMATS.put(1_20_01, 15);
|
PACK_FORMATS.put(1_16_01, new PackVersion(5, 0));
|
||||||
PACK_FORMATS.put(1_20_02, 18);
|
PACK_FORMATS.put(1_16_02, new PackVersion(6, 0));
|
||||||
PACK_FORMATS.put(1_20_03, 22);
|
PACK_FORMATS.put(1_16_03, new PackVersion(6, 0));
|
||||||
PACK_FORMATS.put(1_20_04, 22);
|
PACK_FORMATS.put(1_16_04, new PackVersion(6, 0));
|
||||||
PACK_FORMATS.put(1_20_05, 32);
|
PACK_FORMATS.put(1_16_05, new PackVersion(6, 0));
|
||||||
PACK_FORMATS.put(1_20_06, 32);
|
PACK_FORMATS.put(1_17_00, new PackVersion(7, 0));
|
||||||
PACK_FORMATS.put(1_21_00, 34);
|
PACK_FORMATS.put(1_17_01, new PackVersion(7, 0));
|
||||||
PACK_FORMATS.put(1_21_01, 34);
|
PACK_FORMATS.put(1_18_00, new PackVersion(8, 0));
|
||||||
PACK_FORMATS.put(1_21_02, 42);
|
PACK_FORMATS.put(1_18_01, new PackVersion(8, 0));
|
||||||
PACK_FORMATS.put(1_21_03, 42);
|
PACK_FORMATS.put(1_18_02, new PackVersion(8, 0));
|
||||||
PACK_FORMATS.put(1_21_04, 46);
|
PACK_FORMATS.put(1_19_00, new PackVersion(9, 0));
|
||||||
PACK_FORMATS.put(1_21_05, 55);
|
PACK_FORMATS.put(1_19_01, new PackVersion(9, 0));
|
||||||
PACK_FORMATS.put(1_21_06, 63);
|
PACK_FORMATS.put(1_19_02, new PackVersion(9, 0));
|
||||||
PACK_FORMATS.put(1_21_07, 64);
|
PACK_FORMATS.put(1_19_03, new PackVersion(12, 0));
|
||||||
PACK_FORMATS.put(1_21_08, 64);
|
PACK_FORMATS.put(1_19_04, new PackVersion(13, 0));
|
||||||
PACK_FORMATS.put(1_21_09, 69);
|
PACK_FORMATS.put(1_20_00, new PackVersion(15, 0));
|
||||||
PACK_FORMATS.put(1_21_10, 69);
|
PACK_FORMATS.put(1_20_01, new PackVersion(15, 0));
|
||||||
PACK_FORMATS.put(1_21_11, 75);
|
PACK_FORMATS.put(1_20_02, new PackVersion(18, 0));
|
||||||
PACK_FORMATS.put(1_99_99, 1000);
|
PACK_FORMATS.put(1_20_03, new PackVersion(22, 0));
|
||||||
|
PACK_FORMATS.put(1_20_04, new PackVersion(22, 0));
|
||||||
|
PACK_FORMATS.put(1_20_05, new PackVersion(32, 0));
|
||||||
|
PACK_FORMATS.put(1_20_06, new PackVersion(32, 0));
|
||||||
|
PACK_FORMATS.put(1_21_00, new PackVersion(34, 0));
|
||||||
|
PACK_FORMATS.put(1_21_01, new PackVersion(34, 0));
|
||||||
|
PACK_FORMATS.put(1_21_02, new PackVersion(42, 0));
|
||||||
|
PACK_FORMATS.put(1_21_03, new PackVersion(42, 0));
|
||||||
|
PACK_FORMATS.put(1_21_04, new PackVersion(46, 0));
|
||||||
|
PACK_FORMATS.put(1_21_05, new PackVersion(55, 0));
|
||||||
|
PACK_FORMATS.put(1_21_06, new PackVersion(63, 0));
|
||||||
|
PACK_FORMATS.put(1_21_07, new PackVersion(64, 0));
|
||||||
|
PACK_FORMATS.put(1_21_08, new PackVersion(64, 0));
|
||||||
|
PACK_FORMATS.put(1_21_09, new PackVersion(69, 0));
|
||||||
|
PACK_FORMATS.put(1_21_10, new PackVersion(69, 0));
|
||||||
|
PACK_FORMATS.put(1_21_11, new PackVersion(75, 0));
|
||||||
|
PACK_FORMATS.put(1_26_01, new PackVersion(76, 0));
|
||||||
|
PACK_FORMATS.put(1_99_99, new PackVersion(1000, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Map<String, MinecraftVersion> BY_NAME = new LinkedHashMap<>();
|
||||||
|
private static final Multimap<Integer, MinecraftVersion> BY_PACK_FORMAT = ArrayListMultimap.create();
|
||||||
|
public static final MinecraftVersion V1_16 = new MinecraftVersion("1.16");
|
||||||
|
public static final MinecraftVersion V1_16_1 = new MinecraftVersion("1.16.1");
|
||||||
|
public static final MinecraftVersion V1_16_2 = new MinecraftVersion("1.16.2");
|
||||||
|
public static final MinecraftVersion V1_16_3 = new MinecraftVersion("1.16.3");
|
||||||
|
public static final MinecraftVersion V1_16_4 = new MinecraftVersion("1.16.4");
|
||||||
|
public static final MinecraftVersion V1_16_5 = new MinecraftVersion("1.16.5");
|
||||||
|
public static final MinecraftVersion V1_17 = new MinecraftVersion("1.17");
|
||||||
|
public static final MinecraftVersion V1_17_1 = new MinecraftVersion("1.17.1");
|
||||||
|
public static final MinecraftVersion V1_18 = new MinecraftVersion("1.18");
|
||||||
|
public static final MinecraftVersion V1_18_1 = new MinecraftVersion("1.18.1");
|
||||||
|
public static final MinecraftVersion V1_18_2 = new MinecraftVersion("1.18.2");
|
||||||
|
public static final MinecraftVersion V1_19 = new MinecraftVersion("1.19");
|
||||||
|
public static final MinecraftVersion V1_19_1 = new MinecraftVersion("1.19.1");
|
||||||
|
public static final MinecraftVersion V1_19_2 = new MinecraftVersion("1.19.2");
|
||||||
|
public static final MinecraftVersion V1_19_3 = new MinecraftVersion("1.19.3");
|
||||||
|
public static final MinecraftVersion V1_19_4 = new MinecraftVersion("1.19.4");
|
||||||
|
public static final MinecraftVersion V1_20 = new MinecraftVersion("1.20");
|
||||||
|
public static final MinecraftVersion V1_20_1 = new MinecraftVersion("1.20.1");
|
||||||
|
public static final MinecraftVersion V1_20_2 = new MinecraftVersion("1.20.2");
|
||||||
|
public static final MinecraftVersion V1_20_3 = new MinecraftVersion("1.20.3");
|
||||||
|
public static final MinecraftVersion V1_20_4 = new MinecraftVersion("1.20.4");
|
||||||
|
public static final MinecraftVersion V1_20_5 = new MinecraftVersion("1.20.5");
|
||||||
|
public static final MinecraftVersion V1_20_6 = new MinecraftVersion("1.20.6");
|
||||||
|
public static final MinecraftVersion V1_21 = new MinecraftVersion("1.21");
|
||||||
|
public static final MinecraftVersion V1_21_1 = new MinecraftVersion("1.21.1");
|
||||||
|
public static final MinecraftVersion V1_21_2 = new MinecraftVersion("1.21.2");
|
||||||
|
public static final MinecraftVersion V1_21_3 = new MinecraftVersion("1.21.3");
|
||||||
|
public static final MinecraftVersion V1_21_4 = new MinecraftVersion("1.21.4");
|
||||||
|
public static final MinecraftVersion V1_21_5 = new MinecraftVersion("1.21.5");
|
||||||
|
public static final MinecraftVersion V1_21_6 = new MinecraftVersion("1.21.6");
|
||||||
|
public static final MinecraftVersion V1_21_7 = new MinecraftVersion("1.21.7");
|
||||||
|
public static final MinecraftVersion V1_21_8 = new MinecraftVersion("1.21.8");
|
||||||
|
public static final MinecraftVersion V1_21_9 = new MinecraftVersion("1.21.9");
|
||||||
|
public static final MinecraftVersion V1_21_10 = new MinecraftVersion("1.21.10");
|
||||||
|
public static final MinecraftVersion V1_21_11 = new MinecraftVersion("1.21.11");
|
||||||
|
public static final MinecraftVersion V26_1 = new MinecraftVersion("26.1");
|
||||||
|
public static final MinecraftVersion FUTURE = new MinecraftVersion("99.99");
|
||||||
|
|
||||||
private final int version;
|
private final int version;
|
||||||
private final String versionString;
|
private final String versionString;
|
||||||
private final int packFormat;
|
private final PackVersion packFormat;
|
||||||
|
|
||||||
public static MinecraftVersion parse(final String version) {
|
public static MinecraftVersion byName(final String version) {
|
||||||
return new MinecraftVersion(version);
|
MinecraftVersion mcV = BY_NAME.get(version);
|
||||||
|
if (mcV == null) {
|
||||||
|
throw new IllegalArgumentException("Unsupported version: " + version);
|
||||||
|
}
|
||||||
|
return mcV;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MinecraftVersion> byMajorPackFormat(final int packFormat) {
|
||||||
|
List<MinecraftVersion> minecraftVersions = (List<MinecraftVersion>) BY_PACK_FORMAT.get(packFormat);
|
||||||
|
if (minecraftVersions.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Unsupported pack format: " + packFormat);
|
||||||
|
}
|
||||||
|
return minecraftVersions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String version() {
|
public String version() {
|
||||||
return versionString;
|
return versionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int packFormat() {
|
public PackVersion packFormat() {
|
||||||
return packFormat;
|
return this.packFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftVersion(String version) {
|
public int majorPackFormat() {
|
||||||
|
return packFormat().major();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MinecraftVersion(String version) {
|
||||||
this.version = VersionHelper.parseVersionToInteger(version);
|
this.version = VersionHelper.parseVersionToInteger(version);
|
||||||
this.versionString = version;
|
this.versionString = version;
|
||||||
this.packFormat = PACK_FORMATS.get(this.version);
|
this.packFormat = Objects.requireNonNull(PACK_FORMATS.get(this.version));
|
||||||
|
BY_NAME.put(this.versionString, this);
|
||||||
|
BY_PACK_FORMAT.put(this.packFormat.major(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAtOrAbove(MinecraftVersion other) {
|
public boolean isAtOrAbove(MinecraftVersion other) {
|
||||||
@@ -58,7 +137,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
|||||||
return version <= other.version;
|
return version <= other.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAt(MinecraftVersion other) {
|
public boolean is(MinecraftVersion other) {
|
||||||
return version == other.version;
|
return version == other.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +157,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return version;
|
return this.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package net.momirealms.craftengine.core.util;
|
|
||||||
|
|
||||||
public final class MinecraftVersions {
|
|
||||||
private MinecraftVersions() {}
|
|
||||||
|
|
||||||
public static final MinecraftVersion V1_20 = new MinecraftVersion("1.20");
|
|
||||||
public static final MinecraftVersion V1_20_1 = new MinecraftVersion("1.20.1");
|
|
||||||
public static final MinecraftVersion V1_20_2 = new MinecraftVersion("1.20.2");
|
|
||||||
public static final MinecraftVersion V1_20_3 = new MinecraftVersion("1.20.3");
|
|
||||||
public static final MinecraftVersion V1_20_4 = new MinecraftVersion("1.20.4");
|
|
||||||
public static final MinecraftVersion V1_20_5 = new MinecraftVersion("1.20.5");
|
|
||||||
public static final MinecraftVersion V1_20_6 = new MinecraftVersion("1.20.6");
|
|
||||||
public static final MinecraftVersion V1_21 = new MinecraftVersion("1.21");
|
|
||||||
public static final MinecraftVersion V1_21_1 = new MinecraftVersion("1.21.1");
|
|
||||||
public static final MinecraftVersion V1_21_2 = new MinecraftVersion("1.21.2");
|
|
||||||
public static final MinecraftVersion V1_21_3 = new MinecraftVersion("1.21.3");
|
|
||||||
public static final MinecraftVersion V1_21_4 = new MinecraftVersion("1.21.4");
|
|
||||||
public static final MinecraftVersion V1_21_5 = new MinecraftVersion("1.21.5");
|
|
||||||
public static final MinecraftVersion V1_21_6 = new MinecraftVersion("1.21.6");
|
|
||||||
public static final MinecraftVersion V1_21_7 = new MinecraftVersion("1.21.7");
|
|
||||||
public static final MinecraftVersion V1_21_8 = new MinecraftVersion("1.21.8");
|
|
||||||
public static final MinecraftVersion V1_21_9 = new MinecraftVersion("1.21.9");
|
|
||||||
public static final MinecraftVersion V1_21_10 = new MinecraftVersion("1.21.10");
|
|
||||||
public static final MinecraftVersion V1_21_11 = new MinecraftVersion("1.21.11");
|
|
||||||
public static final MinecraftVersion FUTURE = new MinecraftVersion("1.99.99");
|
|
||||||
}
|
|
||||||
@@ -38,6 +38,7 @@ public class VersionHelper {
|
|||||||
private static final boolean v1_21_9;
|
private static final boolean v1_21_9;
|
||||||
private static final boolean v1_21_10;
|
private static final boolean v1_21_10;
|
||||||
private static final boolean v1_21_11;
|
private static final boolean v1_21_11;
|
||||||
|
private static final boolean v26_1;
|
||||||
private static final Class<?> UNOBFUSCATED_CLAZZ = Objects.requireNonNull(ReflectionUtils.getClazz(
|
private static final Class<?> UNOBFUSCATED_CLAZZ = Objects.requireNonNull(ReflectionUtils.getClazz(
|
||||||
"net.minecraft.obfuscate.DontObfuscate", // 因为无混淆版本没有这个类所以说多写几个防止找不到了
|
"net.minecraft.obfuscate.DontObfuscate", // 因为无混淆版本没有这个类所以说多写几个防止找不到了
|
||||||
"net.minecraft.data.Main",
|
"net.minecraft.data.Main",
|
||||||
@@ -57,7 +58,7 @@ public class VersionHelper {
|
|||||||
.split("-", 2)[0] // 1.21.10-rc1 -> 1.21.10
|
.split("-", 2)[0] // 1.21.10-rc1 -> 1.21.10
|
||||||
.split("_", 2)[0]; // 1.21.11_unobfuscated -> 1.21.11
|
.split("_", 2)[0]; // 1.21.11_unobfuscated -> 1.21.11
|
||||||
|
|
||||||
MINECRAFT_VERSION = new MinecraftVersion(versionString);
|
MINECRAFT_VERSION = MinecraftVersion.byName(versionString);
|
||||||
|
|
||||||
String[] split = versionString.split("\\.");
|
String[] split = versionString.split("\\.");
|
||||||
int major = Integer.parseInt(split[1]);
|
int major = Integer.parseInt(split[1]);
|
||||||
@@ -86,6 +87,7 @@ public class VersionHelper {
|
|||||||
v1_21_9 = version >= 12109;
|
v1_21_9 = version >= 12109;
|
||||||
v1_21_10 = version >= 12110;
|
v1_21_10 = version >= 12110;
|
||||||
v1_21_11 = version >= 12111;
|
v1_21_11 = version >= 12111;
|
||||||
|
v26_1 = version >= 12601;
|
||||||
|
|
||||||
majorVersion = major;
|
majorVersion = major;
|
||||||
minorVersion = minor;
|
minorVersion = minor;
|
||||||
@@ -102,8 +104,9 @@ public class VersionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int parseVersionToInteger(String versionString) {
|
public static int parseVersionToInteger(String versionString) {
|
||||||
int major = 0;
|
int v1 = 0;
|
||||||
int minor = 0;
|
int v2 = 0;
|
||||||
|
int v3 = 0;
|
||||||
int currentNumber = 0;
|
int currentNumber = 0;
|
||||||
int part = 0;
|
int part = 0;
|
||||||
for (int i = 0; i < versionString.length(); i++) {
|
for (int i = 0; i < versionString.length(); i++) {
|
||||||
@@ -111,8 +114,11 @@ public class VersionHelper {
|
|||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
currentNumber = currentNumber * 10 + (c - '0');
|
currentNumber = currentNumber * 10 + (c - '0');
|
||||||
} else if (c == '.') {
|
} else if (c == '.') {
|
||||||
|
if (part == 0) {
|
||||||
|
v1 = currentNumber;
|
||||||
|
}
|
||||||
if (part == 1) {
|
if (part == 1) {
|
||||||
major = currentNumber;
|
v2 = currentNumber;
|
||||||
}
|
}
|
||||||
part++;
|
part++;
|
||||||
currentNumber = 0;
|
currentNumber = 0;
|
||||||
@@ -121,12 +127,23 @@ public class VersionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (part == 1) {
|
// 处理最后一个数字部分
|
||||||
major = currentNumber;
|
if (part == 0) { // 没有点号:如 "26"
|
||||||
} else if (part == 2) {
|
v1 = currentNumber;
|
||||||
minor = currentNumber;
|
} else if (part == 1) { // 一个点号:如 "26.1"
|
||||||
|
v2 = currentNumber;
|
||||||
|
} else if (part == 2) { // 两个点号:如 "1.2.3"
|
||||||
|
v3 = currentNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新版命名法
|
||||||
|
if (v1 >= 26) {
|
||||||
|
return 10000 + v1 * 100 + v2;
|
||||||
|
}
|
||||||
|
// 旧版命名法
|
||||||
|
else {
|
||||||
|
return 10000 + v2 * 100 + v3;
|
||||||
}
|
}
|
||||||
return 10000 + major * 100 + minor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int majorVersion() {
|
public static int majorVersion() {
|
||||||
@@ -269,4 +286,8 @@ public class VersionHelper {
|
|||||||
public static boolean isOrAbove1_21_11() {
|
public static boolean isOrAbove1_21_11() {
|
||||||
return v1_21_11;
|
return v1_21_11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOrAbove26_1() {
|
||||||
|
return v26_1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
org.gradle.jvmargs=-Xmx4G
|
org.gradle.jvmargs=-Xmx4G
|
||||||
|
|
||||||
# Project settings
|
# Project settings
|
||||||
project_version=0.0.66.4
|
project_version=0.0.66.6
|
||||||
config_version=62
|
config_version=64
|
||||||
lang_version=45
|
lang_version=46
|
||||||
project_group=net.momirealms
|
project_group=net.momirealms
|
||||||
latest_supported_version=1.21.11
|
latest_supported_version=1.21.11
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ zstd_version=1.5.7-6
|
|||||||
commons_io_version=2.21.0
|
commons_io_version=2.21.0
|
||||||
commons_lang3_version=3.20.0
|
commons_lang3_version=3.20.0
|
||||||
sparrow_nbt_version=0.10.9
|
sparrow_nbt_version=0.10.9
|
||||||
sparrow_util_version=0.74
|
sparrow_util_version=0.76
|
||||||
fastutil_version=8.5.18
|
fastutil_version=8.5.18
|
||||||
netty_version=4.1.128.Final
|
netty_version=4.1.128.Final
|
||||||
joml_version=1.10.8
|
joml_version=1.10.8
|
||||||
|
|||||||
Reference in New Issue
Block a user