Create symbol link for world
This commit is contained in:
parent
91b875fb6d
commit
47c1884141
|
@ -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.MapDataBridge;
|
||||||
import io.izzel.arclight.common.bridge.world.storage.WorldInfoBridge;
|
import io.izzel.arclight.common.bridge.world.storage.WorldInfoBridge;
|
||||||
import io.izzel.arclight.common.mixin.core.world.WorldMixin;
|
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.ArclightCaptures;
|
||||||
import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
|
import io.izzel.arclight.common.mod.util.DelegateWorldInfo;
|
||||||
|
import io.izzel.arclight.i18n.ArclightConfig;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -137,6 +139,9 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
|
||||||
// damn spigot again
|
// damn spigot again
|
||||||
this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedWorldInfo) worldInfo));
|
this.$$worldDataServer = DelegateWorldInfo.wrap(((DerivedWorldInfo) worldInfo));
|
||||||
((DerivedWorldInfoBridge) worldInfo).bridge$setDimType(this.getTypeKey());
|
((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);
|
((ServerChunkProviderBridge) this.serverChunkProvider).bridge$setViewDistance(spigotConfig.viewDistance);
|
||||||
((WorldInfoBridge) this.$$worldDataServer).bridge$setWorld((ServerWorld) (Object) this);
|
((WorldInfoBridge) this.$$worldDataServer).bridge$setWorld((ServerWorld) (Object) this);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.izzel.arclight.common.mixin.core.world.storage;
|
package io.izzel.arclight.common.mixin.core.world.storage;
|
||||||
|
|
||||||
import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge;
|
import io.izzel.arclight.common.bridge.world.storage.DerivedWorldInfoBridge;
|
||||||
|
import io.izzel.arclight.i18n.ArclightConfig;
|
||||||
import net.minecraft.util.RegistryKey;
|
import net.minecraft.util.RegistryKey;
|
||||||
import net.minecraft.world.DimensionType;
|
import net.minecraft.world.DimensionType;
|
||||||
import net.minecraft.world.storage.DerivedWorldInfo;
|
import net.minecraft.world.storage.DerivedWorldInfo;
|
||||||
|
@ -26,16 +27,29 @@ public class DerivedWorldInfoMixin implements DerivedWorldInfoBridge {
|
||||||
if (typeKey == null || typeKey == DimensionType.OVERWORLD) {
|
if (typeKey == null || typeKey == DimensionType.OVERWORLD) {
|
||||||
return this.delegate.getWorldName();
|
return this.delegate.getWorldName();
|
||||||
} else {
|
} else {
|
||||||
String worldName = this.delegate.getWorldName() + "/";
|
if (ArclightConfig.spec().getCompat().isSymlinkWorld()) {
|
||||||
String suffix;
|
String worldName = this.delegate.getWorldName() + "_";
|
||||||
if (typeKey == DimensionType.THE_END) {
|
String suffix;
|
||||||
suffix = "DIM1";
|
if (typeKey == DimensionType.THE_END) {
|
||||||
} else if (typeKey == DimensionType.THE_NETHER) {
|
suffix = "nether";
|
||||||
suffix = "DIM-1";
|
} else if (typeKey == DimensionType.THE_NETHER) {
|
||||||
|
suffix = "the_end";
|
||||||
|
} else {
|
||||||
|
suffix = (typeKey.getLocation().getNamespace() + "/" + typeKey.getLocation().getPath()).replace('/', '_');
|
||||||
|
}
|
||||||
|
return worldName + suffix;
|
||||||
} else {
|
} 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,10 @@ public class CompatSpec {
|
||||||
@Setting("entity-property-overrides")
|
@Setting("entity-property-overrides")
|
||||||
private Map<String, EntityPropertySpec> entities;
|
private Map<String, EntityPropertySpec> entities;
|
||||||
|
|
||||||
|
// todo Enable this by default in 1.17
|
||||||
|
@Setting("symlink-world")
|
||||||
|
private boolean symlinkWorld;
|
||||||
|
|
||||||
public Map<String, MaterialPropertySpec> getMaterials() {
|
public Map<String, MaterialPropertySpec> getMaterials() {
|
||||||
return materials;
|
return materials;
|
||||||
}
|
}
|
||||||
|
@ -30,4 +34,8 @@ public class CompatSpec {
|
||||||
public Optional<EntityPropertySpec> getEntity(String key) {
|
public Optional<EntityPropertySpec> getEntity(String key) {
|
||||||
return Optional.ofNullable(entities.get(key));
|
return Optional.ofNullable(entities.get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSymlinkWorld() {
|
||||||
|
return symlinkWorld;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ compatibility {
|
||||||
}
|
}
|
||||||
entity-property-overrides {
|
entity-property-overrides {
|
||||||
}
|
}
|
||||||
|
symlink-world = false
|
||||||
}
|
}
|
||||||
async-catcher {
|
async-catcher {
|
||||||
dump = true
|
dump = true
|
||||||
|
|
|
@ -85,6 +85,7 @@ dfu-disable {
|
||||||
legacy-plugin = "Legacy plugin is not allowed when optimization.disable-data-fixer is enabled"
|
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"
|
map-convert = "World upgrading is not allowed when optimization.disable-data-fixer is enabled"
|
||||||
}
|
}
|
||||||
|
error-symlink = "File system do not support symbol links"
|
||||||
|
|
||||||
comments {
|
comments {
|
||||||
_v.comment = [
|
_v.comment = [
|
||||||
|
@ -113,4 +114,13 @@ comments {
|
||||||
"EXCEPTION - Raise an error"
|
"EXCEPTION - Raise an error"
|
||||||
]
|
]
|
||||||
async-catcher.dump.comment = "Dump stack trace iformation in debug.log"
|
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"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,8 @@ dfu-disable {
|
||||||
legacy-plugin = "Legacy 插件在 optimization.disable-data-fixer 启用时不可用"
|
legacy-plugin = "Legacy 插件在 optimization.disable-data-fixer 启用时不可用"
|
||||||
map-convert = "地图升级转换在 optimization.disable-data-fixer 启用时不可用"
|
map-convert = "地图升级转换在 optimization.disable-data-fixer 启用时不可用"
|
||||||
}
|
}
|
||||||
|
error-symlink = "文件系统不支持符号链接"
|
||||||
|
symlink-file-exist = "创建符号链接 {} 时文件已存在"
|
||||||
|
|
||||||
comments {
|
comments {
|
||||||
_v.comment = [
|
_v.comment = [
|
||||||
|
@ -113,4 +115,12 @@ comments {
|
||||||
"EXCEPTION - 抛出异常"
|
"EXCEPTION - 抛出异常"
|
||||||
]
|
]
|
||||||
async-catcher.dump.comment = "是否在 debug 日志中打印堆栈信息"
|
async-catcher.dump.comment = "是否在 debug 日志中打印堆栈信息"
|
||||||
|
compatibility {
|
||||||
|
symlink-world.comment = [
|
||||||
|
"为模组的维度创建符号链接"
|
||||||
|
"推荐启用以增强插件交互兼容性"
|
||||||
|
"变更此设置会导致模组世界名称变化,可能造成依赖世界名称的插件数据丢失"
|
||||||
|
"参见 https://github.com/IzzelAliz/Arclight/wiki/World-Symlink"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user