Create symbol link for world

This commit is contained in:
IzzelAliz 2021-07-15 19:22:38 +08:00
parent 91b875fb6d
commit 47c1884141
7 changed files with 88 additions and 8 deletions

View File

@ -12,8 +12,10 @@ import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge;
import io.izzel.arclight.common.bridge.world.storage.MapDataBridge;
import io.izzel.arclight.common.bridge.world.storage.WorldInfoBridge;
import io.izzel.arclight.common.mixin.core.world.WorldMixin;
import io.izzel.arclight.common.mod.server.world.WorldSymlink;
import io.izzel.arclight.common.mod.util.ArclightCaptures;
import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
import io.izzel.arclight.i18n.ArclightConfig;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -137,6 +139,9 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
// damn spigot again
this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedWorldInfo) worldInfo));
((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey());
if (ArclightConfig.spec().getCompat().isSymlinkWorld()) {
WorldSymlink.create((DerivedWorldInfo) worldInfo, levelSave.getDimensionFolder(this.getDimensionKey()));
}
}
((ServerChunkProviderBridge) this.serverChunkProvider).bridge$setViewDistance(spigotConfig.viewDistance);
((WorldInfoBridge) this.$$worldDataServer).bridge$setWorld((ServerWorld) (Object) this);

View File

@ -1,6 +1,7 @@
package io.izzel.arclight.common.mixin.core.world.storage;
import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge;
import io.izzel.arclight.i18n.ArclightConfig;
import net.minecraft.util.RegistryKey;
import net.minecraft.world.DimensionType;
import net.minecraft.world.storage.DerivedWorldInfo;
@ -26,16 +27,29 @@ public class DerivedWorldInfoMixin implements DerivedWorldInfoBridge {
if (typeKey == null || typeKey == DimensionType.OVERWORLD) {
return this.delegate.getWorldName();
} else {
String worldName = this.delegate.getWorldName() + "/";
String suffix;
if (typeKey == DimensionType.THE_END) {
suffix = "DIM1";
} else if (typeKey == DimensionType.THE_NETHER) {
suffix = "DIM-1";
if (ArclightConfig.spec().getCompat().isSymlinkWorld()) {
String worldName = this.delegate.getWorldName() + "_";
String suffix;
if (typeKey == DimensionType.THE_END) {
suffix = "nether";
} else if (typeKey == DimensionType.THE_NETHER) {
suffix = "the_end";
} else {
suffix = (typeKey.getLocation().getNamespace() + "/" + typeKey.getLocation().getPath()).replace('/', '_');
}
return worldName + suffix;
} else {
suffix = typeKey.getLocation().getNamespace() + "/" + typeKey.getLocation().getPath();
String worldName = this.delegate.getWorldName() + "/";
String suffix;
if (typeKey == DimensionType.THE_END) {
suffix = "DIM1";
} else if (typeKey == DimensionType.THE_NETHER) {
suffix = "DIM-1";
} else {
suffix = typeKey.getLocation().getNamespace() + "/" + typeKey.getLocation().getPath();
}
return worldName + suffix;
}
return worldName + suffix;
}
}

View File

@ -0,0 +1,32 @@
package io.izzel.arclight.common.mod.server.world;
import io.izzel.arclight.common.mod.ArclightMod;
import net.minecraft.world.storage.DerivedWorldInfo;
import org.bukkit.Bukkit;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class WorldSymlink {
public static void create(DerivedWorldInfo worldInfo, File dimensionFolder) {
String name = worldInfo.getWorldName();
Path source = new File(Bukkit.getWorldContainer(), name).toPath();
Path dest = dimensionFolder.toPath();
try {
if (!Files.isSymbolicLink(source)) {
if (Files.exists(source)) {
ArclightMod.LOGGER.warn("symlink-file-exist", source);
return;
}
Files.createSymbolicLink(source, dest);
}
} catch (UnsupportedOperationException e) {
ArclightMod.LOGGER.warn("error-symlink", e);
} catch (IOException e) {
ArclightMod.LOGGER.error("Error creating symlink", e);
}
}
}

View File

@ -15,6 +15,10 @@ public class CompatSpec {
@Setting("entity-property-overrides")
private Map<String, EntityPropertySpec> entities;
// todo Enable this by default in 1.17
@Setting("symlink-world")
private boolean symlinkWorld;
public Map<String, MaterialPropertySpec> getMaterials() {
return materials;
}
@ -30,4 +34,8 @@ public class CompatSpec {
public Optional<EntityPropertySpec> getEntity(String key) {
return Optional.ofNullable(entities.get(key));
}
public boolean isSymlinkWorld() {
return symlinkWorld;
}
}

View File

@ -13,6 +13,7 @@ compatibility {
}
entity-property-overrides {
}
symlink-world = false
}
async-catcher {
dump = true

View File

@ -85,6 +85,7 @@ dfu-disable {
legacy-plugin = "Legacy plugin is not allowed when optimization.disable-data-fixer is enabled"
map-convert = "World upgrading is not allowed when optimization.disable-data-fixer is enabled"
}
error-symlink = "File system do not support symbol links"
comments {
_v.comment = [
@ -113,4 +114,13 @@ comments {
"EXCEPTION - Raise an error"
]
async-catcher.dump.comment = "Dump stack trace iformation in debug.log"
compatibility {
symlink-world.comment = [
"Create symbol links to mod dimension folder that matches Bukkit format"
"Enable this could improve plugin compotibility"
"Changing this on production server will cause changes to mod world names"
" and cause data loss on plugins relying world names"
"See https://github.com/IzzelAliz/Arclight/wiki/World-Symlink for more detail"
]
}
}

View File

@ -85,6 +85,8 @@ dfu-disable {
legacy-plugin = "Legacy 插件在 optimization.disable-data-fixer 启用时不可用"
map-convert = "地图升级转换在 optimization.disable-data-fixer 启用时不可用"
}
error-symlink = "文件系统不支持符号链接"
symlink-file-exist = "创建符号链接 {} 时文件已存在"
comments {
_v.comment = [
@ -113,4 +115,12 @@ comments {
"EXCEPTION - 抛出异常"
]
async-catcher.dump.comment = "是否在 debug 日志中打印堆栈信息"
compatibility {
symlink-world.comment = [
"为模组的维度创建符号链接"
"推荐启用以增强插件交互兼容性"
"变更此设置会导致模组世界名称变化,可能造成依赖世界名称的插件数据丢失"
"参见 https://github.com/IzzelAliz/Arclight/wiki/World-Symlink"
]
}
}