From 51b95240f2ed463de3c035c946e67991874fe3d7 Mon Sep 17 00:00:00 2001 From: Alexander Zielonka Date: Mon, 12 Jan 2026 03:07:23 +0100 Subject: [PATCH] =?UTF-8?q?Logging=20f=C3=BCr=20REST=20Abfragen=20aus=20de?= =?UTF-8?q?m=20Palworld=20Server=20etnfernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 5 ++++- docs/PalWorldSettings.ini | 5 +++++ gsm-backend/services/rcon.js | 37 +++++++++++++++++++++++------------- gsm-backend/services/ssh.js | 7 ++++++- 4 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 docs/PalWorldSettings.ini diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 66a4c30..3764803 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -9,7 +9,10 @@ "Bash(cat:*)", "Bash(git add:*)", "Bash(dir:*)", - "Bash(ssh-keygen:*)" + "Bash(ssh-keygen:*)", + "WebSearch", + "WebFetch(domain:tech.palworldgame.com)", + "WebFetch(domain:docs.palworldgame.com)" ] } } diff --git a/docs/PalWorldSettings.ini b/docs/PalWorldSettings.ini new file mode 100644 index 0000000..b64e26e --- /dev/null +++ b/docs/PalWorldSettings.ini @@ -0,0 +1,5 @@ +; This configuration file is a sample of the default server settings. +; Changes to this file will NOT be reflected on the server. +; To change the server settings, modify Pal/Saved/Config/LinuxServer/PalWorldSettings.ini. +[/Script/Pal.PalGameWorldSettings] +OptionSettings=(Difficulty=None,RandomizerType=None,RandomizerSeed="",bIsRandomizerPalLevelRandom=False,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.000000,PalCaptureRate=1.000000,PalSpawnNumRate=1.000000,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,BuildObjectHpRate=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=1.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=All,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=True,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=False,DropItemMaxNum=3000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=128,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=20,BaseCampMaxNumInGuild=4,PalEggDefaultHatchingTime=72.000000,WorkSpeedRate=1.000000,AutoSaveSpan=30.000000,bIsMultiplay=False,bIsPvP=False,bHardcore=False,bPalLost=False,bCharacterRecreateInHardcore=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bEnableFastTravelOnlyBaseCamp=False,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,bInvisibleOtherGuildBaseCampAreaFX=False,bBuildAreaLimit=False,ItemWeightRate=1.000000,CoopPlayerMaxNum=4,ServerPlayerMaxNum=32,ServerName="Default Palworld Server",ServerDescription="",AdminPassword="gsm-pal-admin-2026",ServerPassword="",bAllowClientMod=True,PublicPort=8211,PublicIP="",RCONEnabled=True,RCONPort=25575,Region="",bUseAuth=False,BanListURL="https://api.palworldgame.com/api/banlist.txt",RESTAPIEnabled=True,RESTAPIPort=8212,bShowPlayerList=False,ChatPostLimitPerMinute=30,CrossplayPlatforms=(Steam,Xbox,PS5,Mac),bIsUseBackupSaveData=True,LogFormatType=Text,bIsShowJoinLeftMessage=True,SupplyDropSpan=180,EnablePredatorBossPal=True,MaxBuildingLimitNum=0,ServerReplicatePawnCullDistance=15000.000000,bAllowGlobalPalboxExport=True,bAllowGlobalPalboxImport=False,EquipmentDurabilityDamageRate=1.000000,ItemContainerForceMarkDirtyInterval=1.000000,ItemCorruptionMultiplier=1.000000,DenyTechnologyList=,GuildRejoinCooldownMinutes=0,BlockRespawnTime=5.000000,RespawnPenaltyDurationThreshold=0.000000,RespawnPenaltyTimeScale=2.000000,bDisplayPvPItemNumOnWorldMap_BaseCamp=False,bDisplayPvPItemNumOnWorldMap_Player=False,AdditionalDropItemWhenPlayerKillingInPvPMode="PlayerDropItem",AdditionalDropItemNumWhenPlayerKillingInPvPMode=1,bAdditionalDropItemWhenPlayerKillingInPvPMode=False,bAllowEnhanceStat_Health=True,bAllowEnhanceStat_Attack=True,bAllowEnhanceStat_Stamina=True,bAllowEnhanceStat_Weight=True,bAllowEnhanceStat_WorkSpeed=True) diff --git a/gsm-backend/services/rcon.js b/gsm-backend/services/rcon.js index 9099b12..1553640 100644 --- a/gsm-backend/services/rcon.js +++ b/gsm-backend/services/rcon.js @@ -4,6 +4,24 @@ const rconConnections = new Map(); const playerCache = new Map(); const CACHE_TTL = 30000; // 30 seconds +// Palworld REST API helper +async function getPalworldPlayers(server) { + const port = server.restApiPort || 8212; + const url = `http://${server.host}:${port}/v1/api/players`; + const auth = Buffer.from(`admin:${server.rconPassword}`).toString('base64'); + + const response = await fetch(url, { + headers: { 'Authorization': `Basic ${auth}` }, + signal: AbortSignal.timeout(5000) + }); + + if (!response.ok) { + throw new Error(`REST API error: ${response.status}`); + } + + return await response.json(); +} + async function getConnection(server) { const key = `${server.host}:${server.rconPort}`; @@ -88,10 +106,9 @@ export async function getPlayers(server) { const lines = response.split('\n').filter(l => l.trim() && !l.includes('listusers')); result = { online: lines.length, max: null }; } else if (server.type === 'palworld') { - const response = await sendRconCommand(server, 'ShowPlayers'); - // Format: "name,playeruid,steamid\nPlayer1,123,765...\nPlayer2,456,765..." - const lines = response.split('\n').filter(l => l.trim() && !l.toLowerCase().startsWith('name,')); - result = { online: lines.length, max: null }; + // Use REST API instead of RCON for Palworld + const data = await getPalworldPlayers(server); + result = { online: data.players?.length || 0, max: null }; } playerCache.set(cacheKey, { data: result, time: Date.now() }); @@ -151,15 +168,9 @@ export async function getPlayerList(server) { const lines = response.split('\n').filter(l => l.trim() && !l.includes('listusers')); players = lines.map(l => l.trim()).filter(p => p); } else if (server.type === 'palworld') { - const response = await sendRconCommand(server, 'ShowPlayers'); - // Format: "name,playeruid,steamid\nPlayer1,123,765...\nPlayer2,456,765..." - const lines = response.split('\n').filter(l => l.trim() && !l.toLowerCase().startsWith('name,')); - for (const line of lines) { - const parts = line.split(','); - if (parts.length >= 1 && parts[0].trim()) { - players.push(parts[0].trim()); - } - } + // Use REST API instead of RCON for Palworld + const data = await getPalworldPlayers(server); + players = (data.players || []).map(p => p.name); } const result = { players }; diff --git a/gsm-backend/services/ssh.js b/gsm-backend/services/ssh.js index 1b37828..a693473 100644 --- a/gsm-backend/services/ssh.js +++ b/gsm-backend/services/ssh.js @@ -192,7 +192,12 @@ export async function getConsoleLog(server, lines = 50) { const result = await ssh.execCommand(`/usr/local/bin/docker-logs-tz ${server.containerName} ${lines}`); return result.stdout || result.stderr; } else if (server.runtime === 'systemd') { - const result = await ssh.execCommand(`tail -n ${lines} ${server.workDir}/logs/VRisingServer.log 2>/dev/null || journalctl -u ${server.serviceName} -n ${lines} --no-pager`); + let cmd = `tail -n ${lines} ${server.workDir}/logs/VRisingServer.log 2>/dev/null || journalctl -u ${server.serviceName} -n ${lines} --no-pager`; + // Filter out REST API spam for Palworld + if (server.type === 'palworld') { + cmd = `journalctl -u ${server.serviceName} -n ${lines * 2} --no-pager | grep -v "REST accessed endpoint" | tail -n ${lines}`; + } + const result = await ssh.execCommand(cmd); return result.stdout || result.stderr; } else if (server.runtime === 'pm2') { const nvmPrefix = "source ~/.nvm/nvm.sh && ";