Chivalry 2 Listplayers Organizer

This program provides a user-friendly graphical interface for organizing player data from Chivalry 2. It streamlines the process of managing player information, tracking nickname changes, and prioritizing specific players for closer monitoring.

Key Features:

  • Graphical User Interface: The script operates within a GUI, making it more accessible and user-friendly. The interface includes buttons for processing data, loading pinned players, and saving changes, as well as text boxes for displaying and editing pinned players.
  • Updating the Player Database: Automatically updates or creates a new file named Chivalry2PlayersDatabase.log. It organizes players by their PlayFabPlayerIds and associated nicknames and last updated time in a clear and structured format.
  • Tracking Nickname Changes: Maintains a historical record of nicknames for each PlayFabPlayerId, enabling users to track changes in player nicknames over time.
  • Prioritizing Pinned Players: Players listed in Chivalry2PinnedPlayers.log are given priority and placed at the top of Chivalry2PlayersDatabase.log, marked with a “*Pinned Player” indicator. This is particularly useful for tracking key players.
  • Real-Time Clipboard Processing: The “Process ListPlayers” button enables users to process player data directly from the clipboard, eliminating the need for manual file management. This feature is designed for efficiency and ease of use, especially during active gaming sessions.

Usage Instructions:

Main GUI Window
1. In a Chivalry 2 Server, open Console by pressing tilde key, type “listplayers” and then press enter key
2. Click “Process ListPlayers” button on the window to get organized data
3. Put PlayFabPlayerIds to the right textbox(1 PlayFabPlayerId per a line) then click “Save Pinned Players”
4. With listplayers in your clipboard, click “Process ListPlayers” Button again and you will see Pinned Players on top
Players with multiple nickname records

Changes in version 1.35

  • Better handle of player nicknames.

PowerShell
# By vintertid from Discord

Add-Type -AssemblyName PresentationFramework

Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'

$consoleWindow = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consoleWindow, 0)

function Process-ListPlayers {
    $currentTime = Get-Date -Format "yyyy-MM-dd-HH:mm:ss UTCK"
    Add-Type -AssemblyName System.Windows.Forms
    $content = [System.Windows.Forms.Clipboard]::GetText()
	
    $listplayersDir = ".\listplayers"
    if (-not (Test-Path $listplayersDir)) {
        New-Item -Path $listplayersDir -ItemType Directory
    }
	
    $filename = "listplayers_" + (Get-Date -Format "yyyy-MM-dd-HH-mm-ss") + ".log"
    $filepath = Join-Path $listplayersDir $filename
	
    if ($content -match "^ServerName - .*\r?\nName -  PlayFabPlayerId - EOSPlayerId - Score - Kills - Deaths - Ping\r?\n(.+\r?\n)+") {
        Set-Content -Path $filepath -Value $content -Encoding UTF8
    } else {
        return
    }

    if (-not $content -match '\b[A-F0-9]{10,16}\b') { return }
    $players = $content -split "\r?\n" | Where-Object { $_ -match '^.+ - \b[A-F0-9]{10,16}\b - ' }
    if (-not $players) { return }
    $existingPlayers = @{}
    $updatedPlayerIds = @()
    $pinnedPlayers = @()

    if (Test-Path .\Chivalry2PinnedPlayers.log) {
        $pinnedPlayers = Get-Content -Path .\Chivalry2PinnedPlayers.log -Encoding UTF8
    }

    if (Test-Path .\Chivalry2PlayersDatabase.log) {
        $existingContent = Get-Content -Path .\Chivalry2PlayersDatabase.log -Encoding UTF8
        $currentId = $null
        foreach ($line in $existingContent) {
            if ($line -match '^\*Pinned Player$') {
                $isPinned = $true
                continue
            }
            if ($line -match '^[\w-]{13,16}$') {
                $currentId = $line
                $existingPlayers[$currentId] = @{ 'Nicknames' = @(); 'IsPinned' = $isPinned; 'TimeData' = 'no-time-data-old-version' }
                $isPinned = $false
            } elseif ($line -match 'listplayered (.+)$') {
                $existingPlayers[$currentId]['TimeData'] = $matches[1]
            } elseif ($line -match '^\s+-\s+(.*)') {
                if (-not $existingPlayers[$currentId]['Nicknames'].Contains($matches[1])) {
                    $existingPlayers[$currentId]['Nicknames'] += $matches[1]
                }
            }
        }
    }

    foreach ($player in $players) {
        if ($player -match '^(?<Nickname>.+?)\s+-\s+(?<PlayFabPlayerId>[A-F0-9]{10,16})\s+-') {
            $Nickname = $matches['Nickname'].Trim()
            $PlayFabPlayerId = $matches['PlayFabPlayerId'].Trim()

            if ($PlayFabPlayerId -and $existingPlayers.ContainsKey($PlayFabPlayerId)) {
                if (-not $existingPlayers[$PlayFabPlayerId]['Nicknames'].Contains($Nickname)) {
                    $existingPlayers[$PlayFabPlayerId]['Nicknames'] += $Nickname
                }
                $existingPlayers[$PlayFabPlayerId]['TimeData'] = $currentTime
            } elseif ($PlayFabPlayerId) {
                $existingPlayers[$PlayFabPlayerId] = @{ 'Nicknames' = @($Nickname); 'IsPinned' = $false; 'TimeData' = $currentTime }
            }
            $updatedPlayerIds += $PlayFabPlayerId
        }
    }

    foreach ($existingPlayer in $existingPlayers.Keys) {
        if ($existingPlayers[$existingPlayer]['IsPinned'] -and $pinnedPlayers -notcontains $existingPlayer) {
            $existingPlayers[$existingPlayer]['IsPinned'] = $false
        }
    }

    foreach ($id in $pinnedPlayers) {
        if ($id -and $existingPlayers.ContainsKey($id)) {
            $existingPlayers[$id]['IsPinned'] = $true
        }
    }

    $pinnedContent = @()
    $mostNicknamesContent = @()
    $mostRecentUpdatesContent = @()
    $restContent = @()

    foreach ($id in $existingPlayers.Keys) {
        $nicknames = $existingPlayers[$id]['Nicknames'] -join "`n    - "
        $timeData = $existingPlayers[$id]['TimeData']
        if ($updatedPlayerIds -contains $id -and $timeData -eq 'no-time-data-old-version') {
            $timeData = $currentTime
        }
        if ($existingPlayers[$id]['IsPinned']) {
            $entry = "-----------------------------------`n*Pinned Player`n$id`n    - $nicknames`nlistplayered $timeData"
            $pinnedContent += $entry
        } elseif ($existingPlayers[$id]['Nicknames'].Count -gt 1) {
            $entry = "-----------------------------------`n$id`n    - $nicknames`nlistplayered $timeData"
            $mostNicknamesContent += $entry
        } elseif ($timeData -eq $currentTime) {
            $entry = "-----------------------------------`n$id`n    - $nicknames`nlistplayered $timeData"
            $mostRecentUpdatesContent += $entry
        } else {
            $entry = "-----------------------------------`n$id`n    - $nicknames`nlistplayered $timeData"
            $restContent += $entry
        }
    }

    $mostNicknamesContent = $mostNicknamesContent | Sort-Object { ($_ -split "`n").Count } -Descending

    $newContent = $pinnedContent + $mostNicknamesContent + $mostRecentUpdatesContent + $restContent
    $newContent -join "`n" | Set-Content -Path .\Chivalry2PlayersDatabase.log -Encoding UTF8
}

$window = New-Object System.Windows.Window
$window.Title = "Chivalry 2 listplayers Organizer 1.35 by vintertid from Discord"
$window.Width = 1200
$window.Height = 800

$mainGrid = New-Object System.Windows.Controls.Grid
$column1 = New-Object System.Windows.Controls.ColumnDefinition
$column2 = New-Object System.Windows.Controls.ColumnDefinition
$mainGrid.ColumnDefinitions.Add($column1)
$mainGrid.ColumnDefinitions.Add($column2)

$stackPanel = New-Object System.Windows.Controls.StackPanel
$stackPanel2 = New-Object System.Windows.Controls.StackPanel

$processButton = New-Object System.Windows.Controls.Button
$processButton.Content = "Process ListPlayers"
$processButton.HorizontalAlignment = "Center"
$processButton.VerticalAlignment = "Top"
$processButton.Margin = New-Object System.Windows.Thickness(10)
$processButton.Add_Click({
    Process-ListPlayers
    $textBox.Text = Get-Content -Path .\Chivalry2PlayersDatabase.log -Encoding UTF8 -Raw
})

$timeTextBlock = New-Object System.Windows.Controls.TextBlock
$timeTextBlock.HorizontalAlignment = "Center"
$timeTextBlock.Margin = New-Object System.Windows.Thickness(10)

$timer = New-Object System.Windows.Threading.DispatcherTimer
$timer.Interval = [TimeSpan]::FromSeconds(1)
$timer.Add_Tick({
    $timeTextBlock.Text = "Current Time: " + (Get-Date -Format "yyyy-MM-dd-HH:mm:ss UTCK")
})
$timer.Start()

$textBox = New-Object System.Windows.Controls.TextBox
$textBox.VerticalScrollBarVisibility = "Visible"
$textBox.HorizontalAlignment = "Stretch"
$textBox.Height = 500
$textBox.Margin = New-Object System.Windows.Thickness(10)
$textBox.IsReadOnly = $true

$searchBox = New-Object System.Windows.Controls.TextBox
$searchBox.HorizontalAlignment = "Stretch"
$searchBox.Margin = New-Object System.Windows.Thickness(10)
$searchBox.Height = 20

$searchButton = New-Object System.Windows.Controls.Button
$searchButton.Content = "Search"
$searchButton.HorizontalAlignment = "Center"
$searchButton.Margin = New-Object System.Windows.Thickness(10)
$searchButton.Add_Click({
    $searchText = $searchBox.Text
    if ([string]::IsNullOrWhiteSpace($searchText)) { return }

    $startIndex = $textBox.Text.IndexOf($searchText, $textBox.SelectionStart + $textBox.SelectionLength, [System.StringComparison]::OrdinalIgnoreCase)
    if ($startIndex -eq -1) {
        $startIndex = $textBox.Text.IndexOf($searchText, [System.StringComparison]::OrdinalIgnoreCase)
        if ($startIndex -eq -1) { return }
    }

    $textBox.Select($startIndex, $searchText.Length)
    $textBox.Focus()
    $textBox.ScrollToLine($textBox.GetLineIndexFromCharacterIndex($startIndex))
})

$textBox2 = New-Object System.Windows.Controls.TextBox
$textBox2.VerticalScrollBarVisibility = "Visible"
$textBox2.HorizontalAlignment = "Stretch"
$textBox2.Height = 500
$textBox2.Margin = New-Object System.Windows.Thickness(10)
$textBox2.AcceptsReturn = $true

$loadButton = New-Object System.Windows.Controls.Button
$loadButton.Content = "Load Pinned Players"
$loadButton.HorizontalAlignment = "Center"
$loadButton.VerticalAlignment = "Top"
$loadButton.Margin = New-Object System.Windows.Thickness(10)
$loadButton.Add_Click({
    if (Test-Path .\Chivalry2PinnedPlayers.log) {
        $textBox2.Text = Get-Content -Path .\Chivalry2PinnedPlayers.log -Raw
    }
})

$saveButton = New-Object System.Windows.Controls.Button
$saveButton.Content = "Save Pinned Players"
$saveButton.HorizontalAlignment = "Center"
$saveButton.VerticalAlignment = "Top"
$saveButton.Margin = New-Object System.Windows.Thickness(10)
$saveButton.Add_Click({
    $textBox2.Text | Set-Content -Path .\Chivalry2PinnedPlayers.log -Encoding UTF8
})

$stackPanel.Children.Add($processButton)
$stackPanel.Children.Add($timeTextBlock)
$stackPanel.Children.Add($textBox)

if (Test-Path .\Chivalry2PlayersDatabase.log) {
    $textBox.Text = Get-Content -Path .\Chivalry2PlayersDatabase.log -Encoding UTF8 -Raw
}

$stackPanel.Children.Add($searchBox)
$stackPanel.Children.Add($searchButton)

$stackPanel.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 0)
$stackPanel2.Children.Add($textBox2)

if (Test-Path .\Chivalry2PinnedPlayers.log) {
    $textBox2.Text = Get-Content -Path .\Chivalry2PinnedPlayers.log -Raw
} else {
    New-Item -Path .\Chivalry2PinnedPlayers.log -ItemType File
}

$stackPanel2.Children.Add($loadButton)
$stackPanel2.Children.Add($saveButton)
$stackPanel2.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 1)

$mainGrid.Children.Add($stackPanel)
$mainGrid.Children.Add($stackPanel2)

$window.Content = $mainGrid

$window.ShowDialog()

↓ Old Version


Changes in version 1.34

  • Clicking Process ListPlayers button also saves original listplayers contents from the clipboard.
  • Better handle of PlayFabPlayerId.

Changes in version 1.32

  • Fixed players with double quotation marks in their nickname are not processed.

Changes in version 1.31

  • Searching is not case sensitive.
  • Displays current time below “Process ListPlayers” button.

Changes in version 1.3

  • It is GUI with buttons.

↓ Legacy Version


This PowerShell script is crafted to effectively organize player data from the game Chivalry 2, enabling users to track name changes and monitor specific players of interest.

  • Updating the Player Database: Just It updates or generates a new file named Chivalry2PlayersDatabase.log, organizing players by their PlayFabPlayerIds and associated nicknames in a structured format.
  • Tracking Nickname Changes: For each PlayFabPlayerId, the script maintains a history of nicknames, facilitating the tracking of player name changes over time.
  • Prioritizing Pinned Players: The script ensures that players listed in the Chivalry2PinnedPlayers.log are placed at the top of the Chivalry2PlayersDatabase.log file, marked with a special indicator to highlight their “Pinned” status. This feature is especially useful for users aiming to closely monitor certain players, whether for administrative reasons or to keep tabs on friends or notable individuals in the game.

It interacts with two primary log files:

Chivalry2ListPlayers.log: Contains the current list of players, player nicknames and their unique PlayFabPlayerIds.

ServerName - example-server--beginner-10p--chivalry-2-live--12345678-1234-1234-1234-1234567890ab 192.0.2.1:52760
Name - PlayFabPlayerId - EOSPlayerId - Score - Kills - Deaths - Ping
<Nickname1> - <PlayFabPlayerId1> - -2030777152 - 250 - 5 - 1 ms
<Nickname2> - <PlayFabPlayerId2> - -2030777152 - 300 - 6 - 2 ms
...

Chivalry2PinnedPlayers.log (optional): Lists the PlayFabPlayerIds of players the user wishes to track more closely, referred to as “pinned” players within the script’s context.

<PlayFabPlayerId1>
<PlayFabPlayerId2>
<PlayFabPlayerId3>
...

The script’s functionalities include:

  • Updating the Player Database: It updates or generates a new file named Chivalry2PlayersDatabase.log, organizing players by their PlayFabPlayerIds and associated nicknames in a structured format.
  • Tracking Nickname Changes: For each PlayFabPlayerId, the script maintains a history of nicknames, facilitating the tracking of player name changes over time.
  • Prioritizing Pinned Players: The script ensures that players listed in the Chivalry2PinnedPlayers.log are placed at the top of the Chivalry2PlayersDatabase.log file, marked with a special indicator to highlight their “Pinned” status. This feature is especially useful for users aiming to closely monitor certain players, whether for administrative reasons or to keep tabs on friends or notable individuals in the game.

Changes in version 1.2

  • PlayFabPlayerIds with the most recent update follow PlayFabPlayerIds with the most nicknames.
  • When updating the database with the listplayers output, the PlayFabPlayerId included in the listplayers output will have the current time recorded.

Changes in version 1.1

  • After Pinned Players, PlayFabPlayerIds with the most nicknames will be placed next.


Chivalry 2 Official Korea 64 Team Server Map Rotation

Seoul – 64-player Mixed Modes

GamemodeMap
TOGalencourtExplode ShipsDestroy RelicsDesecrate King’s Tomb
TORudhelm SiegePush Siege TowersArson the TentsKill Mason Heir
TDMCourtyardCourtyardBegin as Unarmed nobles
TODarkforestPush the ConvoyArson BarricadesKill Agatha Duke
TOBaudwyn (Bulwark)Destroy Siege WeaponsDestroy Thick Desert Wall using Cannons
TDMTournament GroundsTournament GroundsA Trap that Spins when Getting Hit
TOCoxwellArson the VillageSteal the GoldEliminate Agatha Soldiers
TOLionspirePush Battering RamsCapture the Town SquareDestroy the Trebuchets
TDMFrozen WreckBlizzardDestroyable Ice Floors
TOMontcruxDesert FortressExplode Thick Fortress Walls
TOBridgetownArson the FarmDestroy the MarketplaceThrow Nobles to Death
TDMDesertDesertNightBallistas
TOThayic (Stronghold)BlizzardDestroy Castle Wall using CatapultsEscort Agatha King Argon II
TOFalmireRescue HostagesCapture the BridgeEscort Agatha Champion
TDMWardengladeGrassFogThe Sound of Rain
TOAskandir (Library)Explode the LighthouseDestroy RelicsArson the Library
TOAberfell (Raid)Steal Pigs/PeasantsDestroy MonolithsKill Druids
TDMFighting PitArenaFire TrapsSpike Hole at the Center

Horde Plus Gamemode Mod (Discontinued)

I was writing this when the mod was still active.

Horde Plus Gamemode is based on Mordhau Vanilla Horde Gamemode but has Modified/New Elements. Previously, I used to make Sumerian Horde Gamemode. But the structure was very dirty because it was my early modding experiment. I wanted to start from scratch.

This mod is aiming for three things. Stability, Minimal Filesize and My Personal Appetite.

Stability. I’ve added features that just work as intended. (This means that some of my ideas were not able to be with the mod after the tests.) You may face some glitches like chest gambled items are being eaten by the earth, enemies stuck at certain points and more… They are all transplanted from Vanilla Horde. But I have tried to fix bugs like stuck points.

Minimal Filesize. My own server has somehow an extremely slow mod download speed when it is launched. It is quite an annoying task to manually download large mods with frequent updates. I therefore began to use only vanilla resources to have a very small file size. Downloading entine Horde Plus Gamemode Mod takes less than 512 KB.

My Personal Appetite. As a fellow normal Mordhau player, I wanted to modify some assets and add features to Vanilla Horde Gamemode. Also wanted to bring some features from my favorite games like ‘Classic Diablo II’ and ‘Elder Scrolls Series’.

Modified/New Systems

  • Players have some perks from the beginning.
    • Fireproof : Reduces incoming fire damage.
    • Flesh Wound : If you die to something other than a headshot or environmental damage, you stay alive for another 5 seconds.
  • Disabled kicking AFK players. You can check your boiling pot or empty your stomach without being kicked.
  • Every blunt Iron/Steel weapons deal chip damage on blocked when perform a swing attack.
  • Adjusted Wave clear reward gold amount
  • Adjusted Armor Costs, Random Chests Items
  • Shielded Enemies receive more damages.
  • Yeets and Ninjas will be killed with a single hit.
  • Modified Bosses
  • Added Custom Bosses, Minions
  • Some bosses will drop their Unique weapons(◎) on death.
  • Purchasable ranged weapons ammos are removed.
  • Ranged weapons ammo will be automatically replenished over time.
  • Added Ranged Mastery (Bows/Crossbows/ThrowingKnives/ThrowingAxes)
    • ‘Ranged Kills’ will be increased by killing enemies with ranged weapons.
    • Ranged weapons have {Its Original Damage + (0.3 * ‘Ranged Kills’)}.
    • Replenishment rate of ranged weapons ammo will be slightly faster depends on ‘Ranged Kills’.
    • Shooting/Throwing process will be slightly shortened depends on ‘Ranged Kills’.
    • Killing with ranged weapons will heal the players with above certain amount of ‘Ranged Kills’. (5HP with 50 >= ‘Ranged Kills’, 10HP with 100>= ‘Ranged Kills’)
    • Dealing damage with ranged weapons will heal the players with above certain amount of ‘Ranged Kills’. (5HP with 200 >= ‘Ranged Kills’)
  • New Small Maps (Melee Weapons from Random Chests Only)
    • Contraband
    • The Pit
    • Tourney
  • Purchasable Perks (Lesser Bloodlust, Rush, Fury, Dodge, Unflinchable, Tank)
    • Lesser Bloodlust : Increases heal amount upon killing an enemy with melee weapons.
    • Rush : Movement will be faster and Instantly begin sprinting upon killing an enemy.
    • Fury : Fully restores stamina on kill.
    • Dodge : Jumping while moving backwards or sideways will perform a quick dodging motion rather than a regular jump.
    • Unflinchable : Attacks won’t be canceled by getting hit.
    • Tank : Increases player’s size little bit, reduces damage taken from melee and ranged weapons.
  • Superior(○)/Rare(●) Weapons are added to random chests.
    • Superior(○) Weapons : Deals 30% more damage done. Additionally appends bonus damage depends on original weapon damage.
    • Rare(●) Weapons : Deals 80% more damage done. Added 30% chip damage on blocked is added on attack. Additionally appends bonus damage depends on original weapon damage.
  • Nightmare/Hell difficulties beyond 21th wave. (22-28/29-31)
    • Nightmare difficulty : Total 7 waves. Each wave is a summary of 3 waves from Normal difficulty. Minions carry Superior(○) weapons. All enemies will take less damage from players.
    • Hell difficulty : Total 3 waves. Each wave is a summary of 7 waves from Normal difficulty. Bosses & Minions carry Rare(●) weapons. All enemies will take much less damage from players.

Weapons

NormalSuperior(ㅇ)Rare(●)Unique(◎)
Rusty Arming SwordAncient Arming SwordDaedric Shortsword
Broken Arming SwordBroken Ancient Arming SwordSeven-Branched Sword Hilt
Rusty LongswordAncient LongswordDaedric Longsword
Broken LongswordBroken Ancient LongswordNarsil
Carving KnifeButter KnifeMihawk’s NecklaceSumerian Butter Knife
Frying PanChef’s PanHoradric Pan
Training SwordCoaching SwordDimensional SwordSumerian Sword
PitchforkEnt HandEarth Shaker
Wooden ShovelEnt SpoonValhalla Oar
Rusty ShovelBlade ShovelEfficiency V Shovel
Heavy BranchCudgelMoon Tenderizer
PickaxeCrowbillPompeii’s Wrath
ScytheGrim ScytheSoul Harvest
SickleHomiDaedric Crescent
HoeMattockSkull Splitter
Rusty ForkStygian PikeFork of Horripilation
RakeWooden SpikesEarth Shifter
Wooden MalletWoodenstoneImperial Legion Seal
SledgehammerBonesnapThe Cranium Basher
Short SwordRondelSpectral Shard
DaggerPoignardKeening
Arming SwordGladiusDjinn Falcata
Executioner’s SwordChamsu BladeSwordguardGuillotine Sword
PolehammerBec De CorbinHusoldal Evo
GreatswordEspandonSoul Flayer
ZweihanderFlambergeThe Grandfather
PartisanFuscinaRazortine
BillhookGlaiveBill
Bastard SwordGothic SwordUmbra
Pole AxeGreat Pole AxeTrulla Apocalypsi
Heavy HandaxeHand Pole AxeLegendary War Mallet
AxeHatchetTomahawk
EveningstarHeavy AspergillumCaduceusNoonstar
Blacksmith HammerIronstoneSunder
RapierKrisSpada da lato
BardicheLochaber AxeNerveshatter
LongswordRune SwordHonorblade of Chorrol
MesserMangnani BladeMagebane
MaulMartel de FerGavel of PainGreat Maul
MaceMorning StarMoonfall
War AxeNagaThe Chieftain
EstocOakeshott Types XVKoncerz
LuteOudGalápagos LyreAtavachron
SpearPikeMancatcher
WarhammerPineapple ClubSeraph Rod
FalxSicaRhomphaiaBloodthirst Falx
Short SpearSimbilanHarpoon
CleaverSmall CrescentGull
QuarterstaffStalagmiteOndal’s WisdomGandalf Staff
HalberdSteelgoadWoestave
Battle AxeTabarPierre Tombale CouantRhythm Axe
FalchionTulwarAli Baba BladeDwarf Galaxy
ClubWar ClubGnomestickOgre Club
CarrotRadishAncient Red GinsengSumerian Carrot
Beer JugKrügeDas Boot
StoolLoungeYggdrasil
LongbowSumerian Bow

How to install ZeroTier-One VPN on OpenBSD

※ In this article, I have used OpenBSD 7.2 and ZeroTier One 1.10.6.
The most current versions for the OS and software at the time of writing.

OS Information

$ uname -a

OpenBSD openbsd.ourdare.com 7.2 GENERIC.MP#758 amd64

Install Requirements

$ sudo pkg_add wget gmake

quirks-6.42 signed on 2023-03-21T19:29:38Z
wget-1.21.3:libunistring-0.9.7: ok
wget-1.21.3:libidn2-2.3.0p0: ok
wget-1.21.3:bzip2-1.0.8p0: ok
wget-1.21.3:pcre2-10.37: ok
wget-1.21.3:libpsl-0.21.1: ok
wget-1.21.3: ok
gmake-4.3: ok

Download and Extract ZeroTier-One Source

$ wget https://github.com/zerotier/ZeroTierOne/archive/refs/tags/1.10.6.tar.gz

--2023-03-29 14:05:54--  https://github.com/zerotier/ZeroTierOne/archive/refs/tags/1.10.6.tar.gz
github.com (github.com) 해석 중... 20.200.245.247
다음으로 연결 중: github.com (github.com)|20.200.245.247|:443... 연결했습니다.
HTTP 요청을 보냈습니다. 응답 기다리는 중... 302 Found
위치: https://codeload.github.com/zerotier/ZeroTierOne/tar.gz/refs/tags/1.10.6 [따라감]
--2023-03-29 14:05:55--  https://codeload.github.com/zerotier/ZeroTierOne/tar.gz/refs/tags/1.10.6
codeload.github.com (codeload.github.com) 해석 중... 20.200.245.246
다음으로 연결 중: codeload.github.com (codeload.github.com)|20.200.245.246|:443... 연결했습니다.
HTTP 요청을 보냈습니다. 응답 기다리는 중... 200 OK
길이: 15259391 (15M) [application/x-gzip]
저장 위치: `1.10.6.tar.gz'

1.10.6.tar.gz	100%[======================================================================>]  14.55M  6.90MB/s    /  2.1s

2023-03-29 14:05:57 (6.90 MB/s) - `1.10.6.tar.gz' 저장함 [15259391/15259391]



$ tar xzf 1.10.6.tar.gz

Build & Install

$ cd ZeroTierOne-1.10.6



$ gmake && sudo gmake install

Register a Service

Open a new file /etc/rc.d/zerotier with an editor and fill it with the contents below and then save.

#!/bin/ksh

daemon="/usr/local/sbin/zerotier-one -d"

. /etc/rc.d/rc.subr

rc_cmd $1
$ sudo chmod u+x /etc/rc.d/zerotier



$ sudo rcctl enable zerotier



$ sudo rcctl start zerotier

zerotier(ok)

Use Commands

$ sudo zerotier-cli info
200 info ㅁㅁㅁㅁㅁㅁㅁㅁㅁㅁ 1.10.6 ONLINE



$ sudo zerotier-cli join <networkid>

How to build an OpenTTD JGRPP Dedicated Server on OmniOS (Unix / Oracle Solaris / illumos)

※ In this article, I have used OmniOS r151038 and JGRPP v0.52.0.
At the moment, r151038 is the latest LTS OmniOS release and JGRPP v0.52.0 is the latest version release.

OS Information

~$ uname -a



SunOS omnioslts 5.11 omnios-r151038-7bb369b3b5 i86pc i386 i86pc



~$ cat /etc/os-release



NAME="OmniOS"
PRETTY_NAME="OmniOS Community Edition v11 r151038cs"
CPE_NAME="cpe:/o:omniosce:omnios:11:151038:97"
ID=omnios
VERSION=r151038cs
VERSION_ID=r151038cs
BUILD_ID=151038.97.2023.03.11
HOME_URL="https://omnios.org/"
SUPPORT_URL="https://omnios.org/"
BUG_REPORT_URL="https://github.com/omniosorg/omnios-build/issues/new"

Install Requirements

~$ sudo pkg install gcc10 cmake gnu-make



설치할 패키지:   2
변경할 서비스:   1
부트 환경 만들기: 아니오
백업 부트 환경 만들기: 아니오

다운로드		패키지	파일		XFER(MB)		속도
완료됨		2/2	3199/3199	25.5/25.5		471k/s

단계					항목
작업 설치				3358/3358
패키지 상태 데이터베이스 업데이트		완료
패키지 캐시 업데이트			0/0
이미지 상태 업데이트			완료
빠른 조회 데이터베이스 만들기		완료
검색 색인 읽기				완료
검색 색인 업데이트			2/2
패키지 캐시 업데이트			2/2



~$ gcc --version



gcc (OmniOS 151038/10.4.0-il-1) 10.4.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



~$ cmake --version



cmake version 3.25.3

CMake suite maintained and supported by Kitware (kitware.com/cmake).



~$ gmake --version



GNU Make 4.3
Built for x86_64-pc-solaris2.11
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Download and Extract JGRPP Source

~$ wget https://github.com/JGRennison/OpenTTD-patches/archive/refs/tags/jgrpp-0.52.0.tar.gz



--2023-03-24 15:02:55--  https://github.com/JGRennison/OpenTTD-patches/archive/refs/tags/jgrpp-0.52.0.tar.gz
Resolving github.com... 20.200.245.247
Connecting to github.com|20.200.245.247|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/JGRennison/OpenTTD-patches/tar.gz/refs/tags/jgrpp-0.52.0 [following]
--2023-03-24 15:02:56--  https://codeload.github.com/JGRennison/OpenTTD-patches/tar.gz/refs/tags/jgrpp-0.52.0
Resolving codeload.github.com... 20.200.245.246
Connecting to codeload.github.com|20.200.245.246|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/x-gzip]
Saving to: ‘jgrpp-0.52.0.tar.gz’

jgrpp-0.52.0.tar.gz                      [          <=>                                                         ]  11.64M  6.13MB/s    in 1.9s

2023-03-24 15:02:58 (6.13 MB/s) - ‘jgrpp-0.52.0.tar.gz’ saved [12207921]



~$ tar xzf jgrpp-0.52.0.tar.gz

Modify Source Files

Go to the source folder root.

~$ cd OpenTTD-patches-jgrpp-0.52.0

Open CMakeLists.txt with an editor and add 3 lines in target_link_libraries function located at line 313 and it should look like below.

${CMAKE_DL_LIBS}
-lsocket
-lnsl


add_dependencies(openttd
    find_version)

target_link_libraries(openttd
    openttd::languages
    openttd::settings
    openttd::media
    openttd::basesets
    openttd::script_api
    openttd::binfiles
    Threads::Threads
    ${CMAKE_DL_LIBS}
    -lsocket
    -lnsl
)

if(HAIKU)
    target_link_libraries(openttd "be" "network" "midi")
endif()

Open build-dedicated.sh with an editor and replace make at line 7 with gmake and it should look like below.


cd build
rm CMakeCache.txt
cmake .. -DOPTION_DEDICATED=true && gmake -j$(nproc 2>/dev/null || echo "1")

Open src/core/alloc_func.hpp with an editor and add 3 lines at the beginning and it should look like below.

#ifdef __sun
#include <alloca.h>
#endif
#ifdef __sun
#include <alloca.h>
#endif

/*
 * This file is part of OpenTTD.

Open src/string_func.h comment out the line at line 279 and it should look like below.



#       define DEFINE_STRCASESTR
// char *strcasestr(const char *haystack, const char *needle);
#endif /* strcasestr is available */

Open src/network/core/os_abstraction.cpp with an editor and replace SO_REUSEPORT at line 196 with SO_REUSEADDR and it should look like below.



#else
        int reuse_port = 1;
        return setsockopt(d, SOL_SOCKET, SO_REUSEADDR, &reuse_port, sizeof(reuse_port)) == 0;
#endif
}

Open src/3rdparty/randombytes/randombytes.h with an editor and replace a function randombytes line at line 19 and it should look like below.



/*
 * Write `n` bytes of high quality random bytes to `buf`
 */
int randombytes(unsigned char *buf, size_t n);

#ifdef __cplusplus
}
#endif

Open src/3rdparty/randombytes/randombytes.c with an editor and delete all contents and then fill with below.

#include "randombytes.h"
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

int randombytes(unsigned char *x, size_t xlen)
{
    int fd;
    ssize_t bytes_read;

    if (xlen == 0) return 0;
    assert(x != NULL);

    fd = open("/dev/urandom", O_RDONLY);
    if (fd == -1) {
        fd = open("/dev/random", O_RDONLY);
    }
    assert(fd != -1);

    bytes_read = read(fd, x, xlen);
    assert(bytes_read == xlen);

    close(fd);

    return 0;
}

Open src/os/unix/crashlog_unix.cpp with an editor and add a line #include <ucontext.h> right after #include <sys/mman.h> at line 25 and it should look like below.


#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <ucontext.h>

#if defined(WITH_DBG_GDB)
#include <sys/syscall.h>
#endif /* WITH_DBG_GDB */

And in the same file, replace two gregs[REG_EFL] at line 400, 418 with gregs[REG_RFL] and it should look like below.


                        gregs[REG_R14],
                        gregs[REG_R15],
                        gregs[REG_RIP],
                        gregs[REG_RFL]
                );
#elif defined(__i386)
                const gregset_t &gregs = ucontext->uc_mcontext.gregs;
                buffer += seprintf(buffer, last,

                        gregs[REG_EBP],
                        gregs[REG_ESP],
                        gregs[REG_EIP],
                        gregs[REG_RFL]
                );
#endif
#endif

Build

~$ ./build-dedicated.sh

Download and extract Base Graphics

~$ wget https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip



Resolving cdn.openttd.org... 54.230.167.118, 54.230.167.93, 54.230.167.82, ...
Connecting to cdn.openttd.org|54.230.167.118|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3547160 (3.4M) [application/zip]
Saving to: ‘opengfx-7.1-all.zip’

opengfx-7.1-all.zip                  100%[=====================================================================>]   3.38M  9.53MB/s    in 0.4s

2023-03-24 16:02:24 (9.53 MB/s) - ‘opengfx-7.1-all.zip’ saved [3547160/3547160]



~$ unzip opengfx-7.1-all.zip && mv opengfx-7.1.tar build/baseset/



Archive:  opengfx-7.1-all.zip
  inflating: opengfx-7.1.tar

Install

~$ cd build && sudo gmake install

Launch the dedicated server

~$ /usr/local/games/openttd -D

How to make a Minecraft Server on OmniOS (Paper Spigot 1.17 +) (Unix / Oracle Solaris / illumos)

OS Information

~$ uname -a

SunOS minecraft 5.11 omnios-master-72433da6283 i86pc i386 i86pc

~$ cat /etc/os-release

NAME="OmniOS"
PRETTY_NAME="OmniOS Community Edition v11 r151041"
CPE_NAME="cpe:/o:omniosce:omnios:11:151041:0"
ID=omnios
VERSION=r151041
VERSION_ID=r151041
BUILD_ID=151041.0.2021.11.19
HOME_URL="https://omnios.org/"
SUPPORT_URL="https://omnios.org/"
BUG_REPORT_URL="https://github.com/omniosorg/omnios-build/issues/new"

Java Installation Check & Install

~$ java

-bash: java: command not found

~$ pkg search jdk | awk '/17/'

basename    dir    usr/jdk                   pkg:/runtime/java/openjdk17@17.0.1.12-151041.0
basename    dir    usr/jdk                   pkg:/runtime/java/openjdk17@17.0.1.12-151041.0

~$ sudo pkg install openjdk17

     설치할 패키지:   2
     변경할 조정자:   1
     변경할 서비스:   1
   부트 환경 만들기: 아니오
백업 부트 환경 만들기: 아니오

다운로드                                     패키지            파일     XFER(MB)      속도
완료됨                                      2/2       250/250  139.1/139.1  1.4M/s

단계                                                항목
새 작업 설치                                      624/624
패키지 상태 데이터베이스 업데이트                                완료 
패키지 캐시 업데이트                                      0/0 
이미지 상태 업데이트                                       완료 
빠른 조회 데이터베이스 만들기                                  완료 
검색 색인 읽기                                          완료 
검색 색인 업데이트                                       2/2 
패키지 캐시 업데이트                                      2/2 

~$ java -version

openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-omnios-151041)
OpenJDK 64-Bit Server VM (build 17.0.1+12-omnios-151041, mixed mode, sharing)

Make a Directory for Minecraft Server, Download Paper Spigot & Execute the Server

~$ mkdir ~/minecraft && cd ~/minecraft

Get download link of the latest Paper Spigot from https://papermc.io/downloads and download with wget command.

~/minecraft$ wget https://papermc.io/api/v2/projects/paper/versions/1.17.1/builds/388/downloads/paper-1.17.1-388.jar

--2021-11-26 11:20:47--  https://papermc.io/api/v2/projects/paper/versions/1.17.1/builds/388/downloads/paper-1.17.1-388.jar
Resolving papermc.io... 172.67.72.198, 104.26.13.138, 104.26.12.138, ...
Connecting to papermc.io|172.67.72.198|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 61843877 (59M) [application/java-archive]
Saving to: ‘paper-1.17.1-388.jar’

paper-1.17.1-388.jar                                                                100%[================================================================================================================================================================================================================>]  58.98M  66.0MB/s    in 0.9s    

2021-11-26 11:20:48 (66.0 MB/s) - ‘paper-1.17.1-388.jar’ saved [61843877/61843877]

~/minecraft$ java -Xms14G -Xmx15G -jar paper-1.17.1-388.jar 

Downloading vanilla jar...
Patching vanilla jar...
System Info: Java 17 (OpenJDK 64-Bit Server VM 17.0.1+12-omnios-151041) Host: SunOS 5.11 (amd64)
Loading libraries, please wait...
[11:32:27 ERROR]: Failed to load properties from file: server.properties
[11:32:27 WARN]: Failed to load eula.txt
[11:32:27 INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

Open ‘~/minecraft/eula.txt’ and change line ‘eula=false’ to ‘eula=true’

~/minecraft$ java -Xms14G -Xmx15G -jar paper-1.17.1-388.jar

System Info: Java 17 (OpenJDK 64-Bit Server VM 17.0.1+12-omnios-151041) Host: SunOS 5.11 (amd64)
Loading libraries, please wait...
[11:33:17 INFO]: Environment: authHost='https://authserver.mojang.com', accountsHost='https://api.mojang.com', sessionHost='https://sessionserver.mojang.com', servicesHost='https://api.minecraftservices.com', name='PROD'
[11:33:17 INFO]: Found new data pack file/bukkit, loading it automatically
[11:33:18 INFO]: Reloading ResourceManager: Default, bukkit
[11:33:18 INFO]: Loaded 7 recipes
[11:33:19 INFO]: Starting minecraft server version 1.17.1
[11:33:19 INFO]: Loading properties
[11:33:19 INFO]: This server is running Paper version git-Paper-388 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT) (Git: 22aaf91)
[11:33:19 INFO]: Server Ping Player Sample Count: 12
[11:33:19 INFO]: Using 4 threads for Netty based IO
[11:33:19 INFO]: Default game type: SURVIVAL
[11:33:19 INFO]: Generating keypair
[11:33:19 INFO]: Starting Minecraft server on *:25565
[11:33:19 INFO]: Using default channel type
[11:33:19 INFO]: Paper: Using Java 11 compression from Velocity.
[11:33:19 INFO]: Paper: Using Java cipher from Velocity.
[11:33:20 INFO]: Preparing level "world"
[11:33:22 WARN]: Unable to find spawn biome
[11:33:23 WARN]: Unable to find spawn biome
[11:33:23 INFO]: Preparing start region for dimension minecraft:overworld
[11:33:23 INFO]: Preparing spawn area: 0%
[11:33:23 INFO]: Time elapsed: 289 ms
[11:33:23 INFO]: Preparing start region for dimension minecraft:the_nether
[11:33:23 INFO]: Time elapsed: 170 ms
[11:33:23 INFO]: Preparing start region for dimension minecraft:the_end
[11:33:23 INFO]: Time elapsed: 69 ms
[11:33:23 INFO]: Running delayed init tasks
[11:33:23 INFO]: Done (4.384s)! For help, type "help"
[11:33:23 INFO]: Timings Reset
> 

※ You can change parameter -Xms14G/-Xmx15G to your desired minimal/maximum allocation memory

HordePlusLite – Server Only Mod for Mordhau (Discontinued)

A simple Server only Mod that gives Casual Vanilla Horde experience.
This is designed for my Chinese friend Cabbageman3, his server and his group people.
Since mod.io is restricted from China to connect, Chinese cannot join servers with properly subscribed mods.
If you are also in the same condition, or just want to preserve your horde server as vanilla server, feel free to adopt this mod.
What the server owner needs to do is set up the mod manually and load the actor.
Thereby, clients do not have to download any but enjoy the mod features.

Installation

1. Manually download the zip compressed Mod.

2. Extract it and put HordePlusLite.pak to the server directory.

For Linux : Mordhau/Content/Paks
For Windows : Mordhau\Content\Paks

3. Open Game.ini

For Linux: Mordhau/Saved/Config/LinuxServer/Game.ini
For Windows: Mordhau\Saved\Config\WindowsServer\Game.ini

4. Add a line 

SpawnServerActorsOnMapLoad=/Game/Mordhau/Maps/HordePlusLite/BP_HordePlusLite.BP_HordePlusLite_C

under

[/Script/Mordhau.MordhauGameMode]

Supported Maps

  • HRD_Camp
  • HRD_Castello
  • HRD_Feitoria
  • HRD_Grad
  • HRD_MountainPeak
  • HRD_Taiga
  • HRD_Crossroads

Features

  • 50% more wave completion coin reward
  • Shield holding bots take 100% more damage
  • Ninja dies in a single hit
  • Removed firepot from Yeet
  • Players have some perks
    • Dodge
    • Flesh Wound
    • Cat
    • Half Bloodlust (Recover 50 HP on kill)
    • Half Fury (Recover 50 stamina on kill)
  • Added following weapons to the random chests
    • Lute
    • Jug
    • Stool
    • Carrot
    • Ancient Falx
    • Ogre Club
    • Seymour’s Longsword
    • Great War Axe
  • Removed turd from the random chests
  • Slash attack with brunt Iron/Steel weapons deal chip damage on blocked
    • Longsword Alt
    • Rusty Longsword Alt
    • Estoc Alt
    • Heavy Hand Axe Alt
    • Pole Axe Alt
    • Blacksmith Hammer
    • Frying Fan
    • Sledgehammer
  • Decreased respawn delay time of the random chests (5 secs -> 3 secs)
  • Added bonus depends on kills.
    • More than 50 kills, gets 5% walks peed bonus.
    • More than 100 kills, gets triple jump ability.
    • More than 150 kills, gets 10% walks peed bonus.
    • More than 200 kills, heals 5 stamina/sec healing.
    • More than 250 kills, gets 15% walks peed bonus.
    • More than 300 kills, heals 3 hp/sec.
    • More than 350 kills, gets 20% walks peed bonus.
    • More than 400 kills, becomes unflinchable.

How to make a Minecraft Server on OmniOS (Paper Spigot ~1.16.x) (Unix / Oracle Solaris / illumos)

※ For Minecraft 1.17+ versions, a more specific choice of java version is required. For that, please visit this article.

OS Information

~$ uname -a

SunOS omni 5.11 omnios-master-b7ba24aaa1 i86pc i386 i86pc

~$ cat /etc/os-release

NAME="OmniOS"
PRETTY_NAME="OmniOS Community Edition v11 r151035"
CPE_NAME="cpe:/o:omniosce:omnios:11:151035:0"
ID=omnios
VERSION=r151035
VERSION_ID=r151035
BUILD_ID=151035.0.2020.09.26

Java Installation Check & Install

~$ java -version

-bash: java: command not found

~$ sudo pkg install jdk

Packages to install: 2 Mediators to change: 1 Services to change: 1 Create boot environment: No
Create backup boot environment: No
DOWNLOAD PKGS FILES XFER (MB) SPEED
Completed 2/2 371/371 101.1/101.1 1.0M/s
PHASE ITEMS
Installing new actions 537/537
Updating package state database Done
Updating package cache 0/0
Updating image state Done
Creating fast lookup database Done
Reading search index Done
Updating search index 2/2
Updating package cache 2/2

~$ java -version

openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-omnios-151035-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)

Make a Directory for Minecraft Server & Execute the Server

~$ mkdir ~/minecraft && cd ~/minecraft

Put the downloaded server file from https://papermc.io/downloads to ‘~/minecraft’ and locate there.

~/minecraft$ java -Xmx1G -jar paper-209.jar

Downloading vanilla jar…
Failed to download vanilla jar
javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at sun.security.ssl.Alerts.getSSLException(Alerts.java:214)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1967)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1924)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1907)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1423)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
at java.net.URL.openStream(URL.java:1068)
at io.papermc.paperclip.Paperclip.checkVanillaJar(Paperclip.java:190)
at io.papermc.paperclip.Paperclip.checkPaperJar(Paperclip.java:121)
at io.papermc.paperclip.Paperclip.setupEnv(Paperclip.java:94)
at io.papermc.paperclip.Paperclip.main(Paperclip.java:48)
Caused by: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at sun.security.validator.PKIXValidator.(PKIXValidator.java:104)
at sun.security.validator.Validator.getInstance(Validator.java:181)
at sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:318)
at sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:179)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:193)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1670)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:226)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1082)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:1010)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1079)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
… 11 more
Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)
at java.security.cert.PKIXParameters.(PKIXParameters.java:120)
at java.security.cert.PKIXBuilderParameters.(PKIXBuilderParameters.java:104)
at sun.security.validator.PKIXValidator.(PKIXValidator.java:102)
… 23 more

Go https://www.oracle.com/kr/java/technologies/javase/javase-jdk8-downloads.html and download ‘jdk-8u261-solaris-x64.tar.gz’, then extract the file.

Move ‘/jdk-8u261-solaris-x64/jdk1.8.0_261/jre/lib/security/cacerts'(From jdk-8u261-solaris-x64.tar.gz) to Server ‘/etc/ssl/java/cacerts’ and overwrite it.

~/minecraft$ java -Xmx1G -jar paper-209.jar

Downloading vanilla jar…
Patching vanilla jar…
System Info: Java 1.8 (OpenJDK 64-Bit Server VM 25.265-b01) Host: SunOS 5.11 (amd64)
Loading libraries, please wait…
[16:23:35 ERROR]: Failed to load properties from file: server.properties
[16:23:35 WARN]: Failed to load eula.txt
[16:23:36 INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

Open ‘~/minecraft/eula.txt’ and change line ‘eula=false’ to ‘eula=true’

~/minecraft$ java -Xmx1G -jar paper-209.jar

※ You can change parameter -Xmx1G to your desired allocation memory
For 4GB, -Xmx4G
For 16GB, -Xmx16G