new
This commit is contained in:
parent
d123f33c1d
commit
ed6d879a19
39
README.md
39
README.md
@ -1,2 +1,41 @@
|
||||
# MinecraftRegionPurge
|
||||
清理无用区域以便于新版本生成
|
||||
|
||||
|
||||
|
||||
## 这是什么
|
||||
|
||||
对于已经生成的区块来说,这些新地形将不会生成。对于一些已经运行相当久的服务器来说,玩家只有不停向外探索从未生成的区域才能体验到新地形。
|
||||
|
||||
最好的解决方案就是将没有玩家使用的区块全部删除,游戏会在下次有玩家经过时生成新的区块。但是这对于地图相当大的服务器来说仍是一个不可接受的任务,因为地图太大了,玩家居住的又相当分散,服主很难根据mca文件判断哪些应该删除哪些不应该。
|
||||
|
||||
💡这个脚本的诞生就是为了解决这样的苦恼!💡
|
||||
|
||||
脚本会根据玩家的领地自动计算出哪些mca文件是有效的,哪些是无效的。同时还可以根据计算得出的结果自动删除那些无效的区域文件。
|
||||
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
1. 提取有领地的mca文件列表;
|
||||
2. 导出mca列表;
|
||||
3. 生成dynmap用的标记,便于可视化区域;
|
||||
4. 清理没有领地的废弃区域;
|
||||
5. 自动识别不同的世界以及存档位置;
|
||||
|
||||
|
||||
|
||||
## 前置条件
|
||||
|
||||
1. Linux系统的服务器;
|
||||
2. 安装有领地插件;
|
||||
|
||||
|
||||
|
||||
## 使用方法
|
||||
|
||||
```
|
||||
chmod +x RegionPurge.sh
|
||||
./RegionPurge <你的服务端根目录>
|
||||
```
|
||||
|
||||
|
297
RegionPurge.sh
Normal file
297
RegionPurge.sh
Normal file
@ -0,0 +1,297 @@
|
||||
#!/bin/bash
|
||||
|
||||
server_root_path=""
|
||||
residence_save_path=""
|
||||
world_name=""
|
||||
world_save_path=""
|
||||
mca_list="" # (r.x.z.mca r.x.z.mca ...)
|
||||
cord_list="" # (x1 y1 z1 x2 y2 z2 x1 y1 z1 x2 y2 z2 ...)
|
||||
|
||||
# Find Residence plugin save path
|
||||
# return: residence save path
|
||||
function get_residence_save_path() {
|
||||
residence_save_path=$server_root_path/plugins/Residence/Save/Worlds
|
||||
if [ -d "$residence_save_path" ]; then
|
||||
printf "找到 Residence 插件存档路径 %s\n" "$residence_save_path"
|
||||
else
|
||||
printf "错误 - Residence 插件存档路径不存在"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Find world save path
|
||||
# return: world save path
|
||||
function get_world_save_path() {
|
||||
# 如果是 world 则路径为 world/
|
||||
# 否则路径为 $world_name/DIM-1/
|
||||
if [ "$world_name" == "world" ]; then
|
||||
world_save_path=$server_root_path/world
|
||||
else
|
||||
world_save_path=$server_root_path/$world_name/DIM-1
|
||||
fi
|
||||
if [ -d "$world_save_path" ]; then
|
||||
printf "找到世界存档路径 %s\n" "$world_save_path"
|
||||
else
|
||||
printf "错误 - 世界存档路径不存在"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Select world
|
||||
function select_world() {
|
||||
local world_list
|
||||
world_list=$(ls -1 "${residence_save_path}/" | grep '\.yml$' | tr '\n' ' ')
|
||||
local world_list_array
|
||||
IFS=' ' read -r -a world_list_array <<<"$world_list"
|
||||
local world_list_length=${#world_list_array[@]}
|
||||
printf "找到 %s 个世界\n" "$world_list_length"
|
||||
for ((i = 0; i < world_list_length; i++)); do
|
||||
world_list_array[i]=${world_list_array[i]%.yml}
|
||||
world_list_array[i]=${world_list_array[i]#res_}
|
||||
printf "%s. %s\n" "$i" "${world_list_array[i]}"
|
||||
done
|
||||
while true; do
|
||||
printf "请输入要操作的世界序号 (0 ~ %d) 或 q 退出\n" "$((world_list_length - 1))"
|
||||
printf "> "
|
||||
read -r world_index
|
||||
if [ "$world_index" -ge 0 ] && [ "$world_index" -lt "$world_list_length" ]; then
|
||||
world_name=${world_list_array[world_index]}
|
||||
break
|
||||
elif [ "$world_index" == "q" ]; then
|
||||
printf "退出\n"
|
||||
exit 0
|
||||
else
|
||||
printf "输入错误,请重新输入\n"
|
||||
continue
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Write mca file list to csv file with format 'filename, x, z, x, z, \n'
|
||||
function export_mca_list_to_csv() {
|
||||
local mca_list_array
|
||||
IFS=' ' read -r -a mca_list_array <<<"$mca_list"
|
||||
local mca_list_length=${#mca_list_array[@]}
|
||||
echo "file_name,mca_x,mca_z,x1,x2,x3,x4,z1,z2,z3,z4,">mca_list.csv
|
||||
for ((i = 0; i < mca_list_length; i++)); do
|
||||
local mca_file_name=${mca_list_array[i]}
|
||||
local mca_file_name_array
|
||||
IFS='.' read -r -a mca_file_name_array <<<"$mca_file_name"
|
||||
local x=${mca_file_name_array[1]}
|
||||
local z=${mca_file_name_array[2]}
|
||||
local x1=$((x * 512))
|
||||
local x2=$((x * 512 + 511))
|
||||
local x3=$((x * 512))
|
||||
local x4=$((x * 512 + 511))
|
||||
local z1=$((z * 512))
|
||||
local z2=$((z * 512))
|
||||
local z3=$((z * 512 + 511))
|
||||
local z4=$((z * 512 + 511))
|
||||
echo "$mca_file_name,$x,$z,$x1,$x2,$x3,$x4,$z1,$z2,$z3,$z4,">>mca_list.csv
|
||||
done
|
||||
printf "共 %s 个mca 已导出 mca 文件列表到 mca_list.csv\n" "$mca_list_length"
|
||||
}
|
||||
|
||||
# Generate dynmap areas.yml file
|
||||
function generate_dynmap_areas() {
|
||||
local mca_list_array
|
||||
IFS=' ' read -r -a mca_list_array <<<"$mca_list"
|
||||
local mca_list_length=${#mca_list_array[@]}
|
||||
echo "areas:" >areas.yml
|
||||
for ((i = 0; i < mca_list_length; i++)); do
|
||||
local mca_file_name=${mca_list_array[i]}
|
||||
local mca_file_name_array
|
||||
IFS='.' read -r -a mca_file_name_array <<<"$mca_file_name"
|
||||
local x=${mca_file_name_array[1]}
|
||||
local z=${mca_file_name_array[2]}
|
||||
local x1=$((x * 512))
|
||||
local x2=$(((x + 1) * 512))
|
||||
local x3=$(((x + 1) * 512))
|
||||
local x4=$((x * 512))
|
||||
local z1=$((z * 512))
|
||||
local z2=$((z * 512))
|
||||
local z3=$(((z + 1) * 512))
|
||||
local z4=$(((z + 1) * 512))
|
||||
echo " area_100$i:" >>areas.yml
|
||||
echo " fillColor: 8421504 # 0x808080" >>areas.yml
|
||||
echo " world: $world_name" >>areas.yml
|
||||
echo " markup: false" >>areas.yml
|
||||
echo " ytop: 64.0" >>areas.yml
|
||||
echo " fillOpacity: 0.3" >>areas.yml
|
||||
echo " x:" >>areas.yml
|
||||
echo " - $x1.0" >>areas.yml
|
||||
echo " - $x2.0" >>areas.yml
|
||||
echo " - $x3.0" >>areas.yml
|
||||
echo " - $x4.0" >>areas.yml
|
||||
echo " strokeWeight: 1" >>areas.yml
|
||||
echo " z:" >>areas.yml
|
||||
echo " - $z1.0" >>areas.yml
|
||||
echo " - $z2.0" >>areas.yml
|
||||
echo " - $z3.0" >>areas.yml
|
||||
echo " - $z4.0" >>areas.yml
|
||||
echo " label: $mca_file_name" >>areas.yml
|
||||
echo " ybottom: 64.0" >>areas.yml
|
||||
echo " strokeColor: 8421504" >>areas.yml
|
||||
echo " strokeOpacity: 1.0" >>areas.yml
|
||||
done
|
||||
printf "共 %s 个mca 已生成 dynmap areas 到 areas.yml\n" "$mca_list_length"
|
||||
}
|
||||
|
||||
# Delete mca files not in mca_list
|
||||
function purge_mca_files() {
|
||||
local mca_list_array
|
||||
IFS=' ' read -r -a mca_list_array <<<"$mca_list"
|
||||
local mca_list_length=${#mca_list_array[@]}
|
||||
|
||||
local region_path=$world_save_path/region
|
||||
local entitits_path=$world_save_path/entities
|
||||
|
||||
local all_region_mca_files
|
||||
all_region_mca_files=$(ls "$region_path" | grep '\.mca$' | tr '\n' ' ')
|
||||
local all_entities_mca_files
|
||||
all_entities_mca_files=$(ls "$entitits_path" | grep '\.mca$' | tr '\n' ' ')
|
||||
|
||||
local all_region_mca_files_array
|
||||
IFS=' ' read -r -a all_region_mca_files_array <<<"$all_region_mca_files"
|
||||
local all_region_mca_files_length=${#all_region_mca_files_array[@]}
|
||||
printf "找到 %s 个 mca 文件\n" "$all_region_mca_files_length"
|
||||
for ((i = 0; i < all_region_mca_files_length; i++)); do
|
||||
if [[ ! " ${mca_list_array[*]} " =~ ${all_region_mca_files_array[i]} ]]; then
|
||||
printf "删除 mca 文件 %s\n" "${all_region_mca_files_array[i]}"
|
||||
rm "$region_path/${all_region_mca_files_array[i]}"
|
||||
fi
|
||||
done
|
||||
|
||||
local all_entities_mca_files_array
|
||||
IFS=' ' read -r -a all_entities_mca_files_array <<<"$all_entities_mca_files"
|
||||
local all_entities_mca_files_length=${#all_entities_mca_files_array[@]}
|
||||
printf "找到 %s 个 mca 文件\n" "$all_entities_mca_files_length"
|
||||
for ((i = 0; i < all_entities_mca_files_length; i++)); do
|
||||
if [[ ! " ${mca_list_array[*]} " =~ ${all_entities_mca_files_array[i]} ]]; then
|
||||
printf "删除 mca 文件 %s\n" "${all_entities_mca_files_array[i]}"
|
||||
rm "$entitits_path/${all_entities_mca_files_array[i]}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Select operate
|
||||
function select_operate() {
|
||||
local mca_list_array
|
||||
IFS=' ' read -r -a mca_list_array <<<"$mca_list"
|
||||
local mca_list_length=${#mca_list_array[@]}
|
||||
while true; do
|
||||
printf "请输入要操作的类型\n"
|
||||
printf "1. 导出 mca 文件列表到 csv\n"
|
||||
printf "2. 删除不在 mca 文件列表中的 mca 文件\n"
|
||||
printf "3. 导出dynmap areas 到 areas.yml\n"
|
||||
printf "> "
|
||||
read -r operate_type
|
||||
if [ "$operate_type" == "1" ]; then
|
||||
export_mca_list_to_csv
|
||||
break
|
||||
elif [ "$operate_type" == "2" ]; then
|
||||
printf "确认操作 y/n\n"
|
||||
printf "> "
|
||||
read -r confirm
|
||||
if [ "$confirm" == "y" ]; then
|
||||
get_world_save_path
|
||||
purge_mca_files
|
||||
break
|
||||
else
|
||||
printf "取消操作\n"
|
||||
break
|
||||
fi
|
||||
elif [ "$operate_type" == "3" ]; then
|
||||
generate_dynmap_areas
|
||||
break
|
||||
else
|
||||
printf "输入错误,请重新输入\n"
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
# Parse all 'main: 1575:-64:-2452:2045:319:-1872' in file to '1575 -64 -2452 2045 319 -1872'
|
||||
# to format 'x1 y1 z1 x2 y2 z2 x1 y1 z1 x2 y2 z2 ...''
|
||||
function parse_residence_list() {
|
||||
local world_save_file_path=$residence_save_path/res_$world_name.yml
|
||||
local residence_list
|
||||
residence_list=$(grep -oP "main: \K.*" "$world_save_file_path" | tr '\n' ' ')
|
||||
local residence_list_array
|
||||
IFS=' ' read -r -a residence_list_array <<<"$residence_list"
|
||||
local residence_list_length=${#residence_list_array[@]}
|
||||
for ((i = 0; i < residence_list_length; i++)); do
|
||||
local residence_cord
|
||||
residence_cord=$(echo "${residence_list_array[i]}" | tr ':' ' ')
|
||||
cord_list="$cord_list $residence_cord"
|
||||
done
|
||||
}
|
||||
|
||||
# Cast cordination to mca file name
|
||||
function cast_cord_to_mca() {
|
||||
local cord_list_array
|
||||
IFS=' ' read -r -a cord_list_array <<<"$cord_list"
|
||||
local cord_list_length=${#cord_list_array[@]}
|
||||
for ((i = 0; i < cord_list_length; i += 6)); do
|
||||
local x1=${cord_list_array[i]}
|
||||
local z1=${cord_list_array[i + 2]}
|
||||
local x2=${cord_list_array[i + 3]}
|
||||
local z2=${cord_list_array[i + 5]}
|
||||
local x1_mca=$((x1 / 512))
|
||||
local z1_mca=$((z1 / 512))
|
||||
local x2_mca=$((x2 / 512))
|
||||
local z2_mca=$((z2 / 512))
|
||||
# expand 1 field to each side
|
||||
for ((x = x1_mca - 2; x <= x2_mca + 2; x++)); do
|
||||
for ((z = z1_mca - 2; z <= z2_mca + 2; z++)); do
|
||||
file_name="r.$x.$z.mca"
|
||||
# if file not exist in mca_list_result then add it
|
||||
if [[ "$mca_list" != *"$file_name"* ]]; then
|
||||
mca_list="$mca_list $file_name"
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# Main function
|
||||
function main() {
|
||||
server_root_path=$1
|
||||
|
||||
# Check if server root path is empty
|
||||
if [ -z "$server_root_path" ]; then
|
||||
echo "Usage: PurgeMca.sh <server_root_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if server root path exists
|
||||
if [ ! -d "$server_root_path" ]; then
|
||||
echo "Server root path does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_residence_save_path
|
||||
while true; do
|
||||
select_world
|
||||
parse_residence_list
|
||||
cast_cord_to_mca
|
||||
select_operate
|
||||
printf "任务完成 继续或退出 c/q\n"
|
||||
printf "> "
|
||||
read -r continue_or_quit
|
||||
if [ "$continue_or_quit" == "c" ]; then
|
||||
clear
|
||||
continue
|
||||
elif [ "$continue_or_quit" == "q" ]; then
|
||||
break
|
||||
else
|
||||
printf "输入错误,退出\n"
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Call main function
|
||||
main "$1"
|
||||
|
Loading…
Reference in New Issue
Block a user