GCPでパルワールドのサーバーを作成するTips

## 想定読者
- ある程度クラウドが分かる人orエンジニア
- マイクラサーバーを建てたことがある人

## サーバーの規模感など
- 最大同時接続ユーザーが8人程度
- サーバーにはパルワールドやりこみ勢ばっかり
- パルワールドのバージョンは`Ver0.1.5.1`


## TL;DR
GCEの4c8tのcpuに32GBのRAM, 100GB程度のストレージを選ぶと良い。
palworldsettings.iniはこんな感じ
```
[/Script/Pal.PalGameWorldSettings]
OptionSettings=(Difficulty=None,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.500000,PalCaptureRate=1.200000,PalSpawnNumRate=0.650000,PalDamageRateAttack=1.000000,PalDamageRateDefense=1.000000,PlayerDamageRateAttack=1.000000,PlayerDamageRateDefense=1.000000,PlayerStomachDecreaceRate=1.000000,PlayerStaminaDecreaceRate=1.000000,PlayerAutoHPRegeneRate=1.000000,PlayerAutoHpRegeneRateInSleep=1.000000,PalStomachDecreaceRate=1.000000,PalStaminaDecreaceRate=1.000000,PalAutoHPRegeneRate=1.000000,PalAutoHpRegeneRateInSleep=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=0.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=All,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=False,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=False,DropItemMaxNum=1000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=30,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=10,PalEggDefaultHatchingTime=4.300000,WorkSpeedRate=1.000000,bIsMultiplay=False,bIsPvP=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,CoopPlayerMaxNum=4,ServerPlayerMaxNum=10,ServerName="Default Palworld Server",ServerDescription="",AdminPassword="hoge",ServerPassword="huga",PublicPort=8211,PublicIP="",RCONEnabled=False,RCONPort=25575,Region="",bUseAuth=True,BanListURL="https://api.palworldgame.com/api/banlist.txt")
```

`PalSpawnNumRate`と`BaseCampMaxNum`はかなりパフォーマンスに影響が出るので、値に注意してください

## やることの流れ（あくまでTipsなので本記事で全ては説明しません。）
- GCEでスペック構成を選ぶ
- SSHでサーバーに接続しsteamCMDをインスコする
- パルワールド用のライブラリなどなどを入れる
- パルワールドのsettingファイルを弄る

手順については以下の記事がとても丁寧で詳しいのでそちらを見ていただくと良いと思います。
- [【GCP/Linux】GCEに話題のパルワールド（Palworld）の専用サーバー（Dedicated Server）を構築してみた](https://zenn.dev/kazumax4395/articles/49fe4d15dbc625)
- [最大32人 パルワールド Linux 専用サーバの立て方
](https://qiita.com/naoya-i/items/e907a6b949e5da36d532#%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97%E7%B6%9A%E3%81%91%E3%82%8B%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%90%E3%81%8C%E8%90%BD%E3%81%A1%E3%82%8B)

## GCE
![スクリーンショット 2024-04-03 18.29.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648231/68257924-792a-c3f5-084a-bdf3834b341c.png)
(参照：https://cloud.google.com/compute/docs/machine-resource?hl=ja#n2d_machine_types)
この`コスト最適化`に特化した、`E2`ワークロードの4C8Tくらいで大体各使用率が誰もサーバーを使っていないときで30%前後、使ってるときで6,70%前後になります。

少し余裕が欲しい人は8C16Tとかにしておくと良いと思います。

メモリはパルワールドのサーバーが起動している間、ずっとリークし続けているので、
> There are a few events which occur in the game, which are believed to cause memory leaks.

(参考：https://gist.github.com/Toakan/3c78a577c21a21fcc5fa917f3021d70e#memory-leak)
予算が許す限り32GBより大きいものを選ぶとsystemd再起動の頻度が少なくなります。

ストレージはsteamCMDに加えて、パルワールドのサーバーに必要なライブラリ、バックアップ等を入れることを想定すると50GBくらいあれば十分ですが、前述のようにメモリリークの影響からスワップ領域を作成しておくことが望ましいので、私は100GBくらいのストレージを用意してそのうちの20GBくらいをスワップに割り当てました。

## systemd設定諸々
### crontab
```
0 5,17 * * * /home/palworld/backup-palworld.sh
// 32GBなので、12時間に一回は再起動するようにしている。
30 5,17 * * * /home/palworld/restart-palworld.sh
0 * * * * /home/palworld/update-palworld.sh
```
- backup-palworld.sh
```bash
#!/bin/bash

# Define source directory and backup directory
SOURCE_DIR="/home/palworld/.steam/SteamApps/common/PalServer/Pal/Saved"
BACKUP_DIR="/home/palworld/backup"
DATE=$(date +%Y%m%d_%H%M%S)

# Create a gzip compressed tarball
tar -czf "${BACKUP_DIR}/backup_${DATE}.tar.gz" -C "${SOURCE_DIR}" .

echo "Backup of ${SOURCE_DIR} completed at ${BACKUP_DIR}/backup_${DATE}.tar.gz"
```

- restart-palworld.sh
```bash
#!/bin/bash
echo "Restart ."

sudo systemctl stop palworld-dedicated.service
sleep 5
sudo systemctl start palworld-dedicated.service
systemctl status palworld-dedicated.service
```

- update-palworld.sh
```bash
#!/bin/bash

# Paths
Steamcmd="/home/palworld/.steam/steamcmd/steamcmd.sh"
install_dir="/home/palworld/.steam/SteamApps/common/PalServer"
service_name="palworld-dedicated.service"

echo "# Environment Check"
date

# Retrieve the current Build ID
OLD_Build=`$Steamcmd +force_install_dir $install_dir +login anonymous +app_status 2394010 +quit | grep -e "BuildID" | awk '{print $8}'`
echo "Current BuildID: $OLD_Build"

# Attempt to fetch the New Build ID using curl
NEW_Build=$(curl -s https://api.steamcmd.net/v1/info/2394010 | jq -r '.data["2394010"].depots.branches.public.buildid')

# Fallback to SteamCMD method if curl fails to retrieve data
if [ -z "$NEW_Build" ] || [ "$NEW_Build" = "null" ]; then
            echo "Failed to fetch New BuildID with curl. Resorting to SteamCMD."
            $Steamcmd +force_install_dir $install_dir +login anonymous +app_update 2394010 validate +quit > /dev/null
            NEW_Build=`$Steamcmd +force_install_dir $install_dir +login anonymous +app_status 2394010 +quit | grep -e "BuildID" | awk '{print $8}'`
fi

echo "Fetched New BuildID: $NEW_Build"

# Update the server if the Build IDs do not match
if [ "$OLD_Build" = "$NEW_Build" ]; then
            echo "No update required. Build numbers are identical."
    else
            echo "# Updating the game server..."
            $Steamcmd +force_install_dir $install_dir +login anonymous +app_update 2394010 validate +quit > /dev/null
            echo "Game server updated successfully to BuildID: $NEW_Build"
            echo "Restart ${service_name}."

            sudo systemctl stop $service_name
            sleep 5
            sudo systemctl start $service_name
            systemctl status $service_name
fi
```

## PalworldSettings.ini
```ini
[/Script/Pal.PalGameWorldSettings]
OptionSettings=(Difficulty=None,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.500000,PalCaptureRate=1.200000,PalSpawnNumRate=0.650000,PalDamageRateAttack=1.000000,PalDamageRateDefense=1.000000,PlayerDamageRateAttack=1.000000,PlayerDamageRateDefense=1.000000,PlayerStomachDecreaceRate=1.000000,PlayerStaminaDecreaceRate=1.000000,PlayerAutoHPRegeneRate=1.000000,PlayerAutoHpRegeneRateInSleep=1.000000,PalStomachDecreaceRate=1.000000,PalStaminaDecreaceRate=1.000000,PalAutoHPRegeneRate=1.000000,PalAutoHpRegeneRateInSleep=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=0.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=All,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=False,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=False,DropItemMaxNum=1000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=30,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=10,PalEggDefaultHatchingTime=4.300000,WorkSpeedRate=1.000000,bIsMultiplay=False,bIsPvP=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,CoopPlayerMaxNum=4,ServerPlayerMaxNum=10,ServerName="Default Palworld Server",ServerDescription="",AdminPassword="hoge",ServerPassword="huga",PublicPort=8211,PublicIP="",RCONEnabled=False,RCONPort=25575,Region="",bUseAuth=True,BanListURL="https://api.palworldgame.com/api/banlist.txt")
```
`PalSpawnNumRate`と`BaseCampMaxNum`はかなりパフォーマンスに影響が出るので、値に注意してください。

また、`ServerName`と`ServerPassword`, `AdminPassword`の値は適宜変更することを強くおすすめします。

## ラグ関連の対策
一応下記リンクを参考に設定してみましたが、効果は体感できませんでした。

```ini
# PalworldSettings.ini
[/Script/OnlineSubsystemUtils.IpNetDriver]
LanServerMaxTickRate=60

NetServerMaxTickRate=60

[/script/engine.player]

ConfiguredInternetSpeed=6250000

ConfiguredLanSpeed=6250000

[/script/socketsubsystemepic.epicnetdriver]

MaxClientRate=6250000

MaxInternetClientRate=6250000

[/script/engine.engine]

bSmoothFrameRate=false

bUseFixedFrameRate=true

SmoothedFrameRateRange=(LowerBound=(Type=Inclusive,Value=60.000000),UpperBound=(Type=Exclusive,Value=60.000000))

MinDesiredFrameRate=60.000000

FixedFrameRate=60.000000
```

## 参考
- [【GCP/Linux】GCEに話題のパルワールド（Palworld）の専用サーバー（Dedicated Server）を構築してみた](https://zenn.dev/kazumax4395/articles/49fe4d15dbc625)
- [最大32人 パルワールド Linux 専用サーバの立て方
](https://qiita.com/naoya-i/items/e907a6b949e5da36d532#%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97%E7%B6%9A%E3%81%91%E3%82%8B%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%90%E3%81%8C%E8%90%BD%E3%81%A1%E3%82%8B)
- [Palworld Server Community FAQ](https://gist.github.com/Toakan/3c78a577c21a21fcc5fa917f3021d70e)
- [Optimizing PalWorld Dedicated Server: Engine.ini Settings to Reduce Lag and Rubberbanding](https://www.reddit.com/r/Palworld/comments/19f6i19/optimizing_palworld_dedicated_server_engineini/)