diff --git a/community/palworld/1.0.0/Chart.lock b/community/palworld/1.0.0/Chart.lock new file mode 100644 index 0000000000..89fca8d37d --- /dev/null +++ b/community/palworld/1.0.0/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.2.9 +digest: sha256:af1a9a1f87e3e48453c9f25f909f5ebcd7fa6e25162b7b425448ba752bcdbc5c +generated: "2024-01-22T14:15:27.684929848+02:00" diff --git a/community/palworld/1.0.0/Chart.yaml b/community/palworld/1.0.0/Chart.yaml new file mode 100644 index 0000000000..3eac6242b7 --- /dev/null +++ b/community/palworld/1.0.0/Chart.yaml @@ -0,0 +1,26 @@ +name: palworld +description: Palworld is a multiplayer, open-world survival crafting game where you befriend and collect mysterious creatures called "Pals". +annotations: + title: Palworld +type: application +version: 1.0.0 +apiVersion: v2 +appVersion: palworld +kubeVersion: '>=1.16.0-0' +maintainers: + - name: truenas + url: https://www.truenas.com/ + email: dev@ixsystems.com +dependencies: + - name: common + repository: file://../../../common + version: 1.2.9 +home: https://www.pocketpair.jp/palworld +icon: https://media.sys.truenas.net/apps/palworld/icons/icon.webp +sources: + - https://www.pocketpair.jp/palworld + - https://github.com/truenas/charts/tree/master/library/ix-dev/community/palworld + - https://github.com/ich777/docker-steamcmd-server/tree/palworld +keywords: + - game + - palworld diff --git a/community/palworld/1.0.0/README.md b/community/palworld/1.0.0/README.md new file mode 100644 index 0000000000..8738d28e48 --- /dev/null +++ b/community/palworld/1.0.0/README.md @@ -0,0 +1,3 @@ +# Palworld + +[Palworld](https://www.pocketpair.jp/palworld) is a multiplayer, open-world survival crafting game where you befriend and collect mysterious creatures called "Pals". diff --git a/community/palworld/1.0.0/app-readme.md b/community/palworld/1.0.0/app-readme.md new file mode 100644 index 0000000000..8738d28e48 --- /dev/null +++ b/community/palworld/1.0.0/app-readme.md @@ -0,0 +1,3 @@ +# Palworld + +[Palworld](https://www.pocketpair.jp/palworld) is a multiplayer, open-world survival crafting game where you befriend and collect mysterious creatures called "Pals". diff --git a/community/palworld/1.0.0/charts/common-1.2.9.tgz b/community/palworld/1.0.0/charts/common-1.2.9.tgz new file mode 100644 index 0000000000..a6f1cd325b Binary files /dev/null and b/community/palworld/1.0.0/charts/common-1.2.9.tgz differ diff --git a/community/palworld/1.0.0/ci/basic-values.yaml b/community/palworld/1.0.0/ci/basic-values.yaml new file mode 100644 index 0000000000..0dbdbf2250 --- /dev/null +++ b/community/palworld/1.0.0/ci/basic-values.yaml @@ -0,0 +1,13 @@ +palworldNetwork: + serverPort: 32211 + rconPort: 32212 + +palworldID: + user: 1000 + group: 1000 + +palworldStorage: + steamcmd: + type: pvc + server: + type: pvc diff --git a/community/palworld/1.0.0/ix_values.yaml b/community/palworld/1.0.0/ix_values.yaml new file mode 100644 index 0000000000..878b14933d --- /dev/null +++ b/community/palworld/1.0.0/ix_values.yaml @@ -0,0 +1,43 @@ +image: + repository: ich777/steamcmd + pullPolicy: IfNotPresent + tag: palworld + +resources: + limits: + cpu: 4000m + memory: 8Gi + +palworldConfig: + adminPassword: '' + gameParams: + - EpicApp=PalServer + gameParamsExtra: + - -No-useperfthreads + - -NoAsyncLoadingThread + - -UseMultithreadForDS + updatePublicIP: false + validate: false + username: '' + password: '' + additionalEnvs: [] + +palworldID: + user: 568 + group: 568 + +palworldNetwork: + serverPort: 38211 + rconPort: 38212 + hostNetwork: false + +palworldStorage: + steamcmd: + type: ixVolume + ixVolumeConfig: + datasetName: config + server: + type: ixVolume + ixVolumeConfig: + datasetName: storage + additionalStorages: [] diff --git a/community/palworld/1.0.0/metadata.yaml b/community/palworld/1.0.0/metadata.yaml new file mode 100644 index 0000000000..10262703e1 --- /dev/null +++ b/community/palworld/1.0.0/metadata.yaml @@ -0,0 +1,20 @@ +runAsContext: + - userName: root + groupName: root + gid: 0 + uid: 0 + description: Palworld runs as root user. +capabilities: + - name: CHOWN + description: Palworld is able to change file ownership. + - name: DAC_OVERRIDE + description: Palworld is able to bypass file read, write, and execute permission checks. + - name: FOWNER + description: Palworld is able to bypass permission checks on operations that normally require the file system UID of the process to match the UID of the file. + - name: SETUID + description: Palworld is able to set the setuid attribute on a file. + - name: SETGID + description: Palworld is able to set the setgid attribute on a file. + - name: KILL + description: Palworld is able to send signals to processes owned by others. +hostMounts: [] diff --git a/community/palworld/1.0.0/questions.yaml b/community/palworld/1.0.0/questions.yaml new file mode 100644 index 0000000000..700ebda6dc --- /dev/null +++ b/community/palworld/1.0.0/questions.yaml @@ -0,0 +1,518 @@ +groups: + - name: Palworld Configuration + description: Configure Palworld + - name: User and Group Configuration + description: Configure User and Group for Palworld + - name: Network Configuration + description: Configure Network for Palworld + - name: Storage Configuration + description: Configure Storage for Palworld + - name: Resources Configuration + description: Configure Resources for Palworld + +questions: + - variable: palworldConfig + label: "" + group: Palworld Configuration + schema: + type: dict + attrs: + - variable: adminPassword + label: Admin Password + description: Your server admin password + schema: + type: string + private: true + default: "" + - variable: gameParams + label: Game Parameters + description: | + Enter your game parameters
+ Format: EpicApp=PalServer + schema: + type: list + default: + - EpicApp=PalServer + items: + - variable: gameParam + label: Game Parameter + schema: + type: string + required: true + - variable: gameParamsExtra + label: Extra Game Parameters + description: | + Enter your extra game parameters
+ Format: -NoAsyncLoadingThread + schema: + type: list + default: + - -No-useperfthreads + - -NoAsyncLoadingThread + - -UseMultithreadForDS + items: + - variable: gameParamExtra + label: Extra Game Parameter + schema: + type: string + required: true + - variable: updatePublicIP + label: Update Public IP + description: | + If enabled the container will check on each container + start if the Public IP is still valid. + schema: + type: boolean + default: false + - variable: validate + label: Validate + description: If enabled the container validates the game data + schema: + type: boolean + default: false + - variable: username + label: Username + description: Leave blank for anonymous login + schema: + type: string + default: "" + - variable: password + label: Password + description: Leave blank for anonymous login + schema: + type: string + default: "" + show_if: [["username", "!=", ""]] + private: true + - variable: additionalEnvs + label: Additional Environment Variables + description: Configure additional environment variables for Palworld. + schema: + type: list + default: [] + items: + - variable: env + label: Environment Variable + schema: + type: dict + attrs: + - variable: name + label: Name + schema: + type: string + required: true + - variable: value + label: Value + schema: + type: string + required: true + + - variable: palworldID + label: "" + group: User and Group Configuration + schema: + type: dict + attrs: + - variable: user + label: User ID + description: The user id that Palworld files will be owned by. + schema: + type: int + min: 568 + default: 568 + required: true + - variable: group + label: Group ID + description: The group id that Palworld files will be owned by. + schema: + type: int + min: 568 + default: 568 + required: true + + - variable: palworldNetwork + label: "" + group: Network Configuration + schema: + type: dict + attrs: + - variable: serverPort + label: Server Port + description: The UDP port for the Palworld Server. + schema: + type: int + default: 38211 + min: 9000 + max: 65535 + required: true + - variable: rconPort + label: RCON Port + description: The TCP port for the Palworld RCON. + schema: + type: int + default: 38212 + min: 9000 + max: 65535 + required: true + - variable: hostNetwork + label: Host Network + description: | + Bind to the host network. It might be needed for the UDP server port to work. + schema: + type: boolean + default: false + + - variable: palworldStorage + label: "" + group: Storage Configuration + schema: + type: dict + attrs: + - variable: steamcmd + label: Palworld SteamCMD Storage + description: The path to store Palworld SteamCMD. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + immutable: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + hidden: true + default: "steamcmd" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + + - variable: server + label: Palworld Server Storage + description: The path to store Palworld Server. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + immutable: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: readOnly + label: Read Only + description: Mount the volume as read only. + schema: + type: boolean + default: false + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + hidden: true + default: "server" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + + - variable: additionalStorages + label: Additional Storage + description: Additional storage for Palworld. + schema: + type: list + default: [] + items: + - variable: storageEntry + label: Storage Entry + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system.
+ SMB Share: Is a SMB share that is mounted to a persistent volume claim. + schema: + type: string + required: true + default: "ixVolume" + immutable: true + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - value: "smb-pv-pvc" + description: SMB Share (Mounts a persistent volume claim to a SMB share) + - variable: readOnly + label: Read Only + description: Mount the volume as read only. + schema: + type: boolean + default: false + - variable: mountPath + label: Mount Path + description: The path inside the container to mount the storage. + schema: + type: path + required: true + - variable: hostPathConfig + label: Host Path Configuration + schema: + type: dict + show_if: [["type", "=", "hostPath"]] + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: acl + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + $ref: + - "normalize/acl" + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["aclEnable", "=", false]] + required: true + - variable: ixVolumeConfig + label: ixVolume Configuration + description: The configuration for the ixVolume dataset. + schema: + type: dict + show_if: [["type", "=", "ixVolume"]] + $ref: + - "normalize/ixVolume" + attrs: + - variable: aclEnable + label: Enable ACL + description: Enable ACL for the dataset. + schema: + type: boolean + default: false + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + required: true + immutable: true + default: "storage_entry" + - variable: aclEntries + label: ACL Configuration + schema: + type: dict + show_if: [["aclEnable", "=", true]] + attrs: [] + - variable: smbConfig + label: SMB Share Configuration + description: The configuration for the SMB Share. + schema: + type: dict + show_if: [["type", "=", "smb-pv-pvc"]] + attrs: + - variable: server + label: Server + description: The server for the SMB share. + schema: + type: string + required: true + - variable: share + label: Share + description: The share name for the SMB share. + schema: + type: string + required: true + - variable: domain + label: Domain (Optional) + description: The domain for the SMB share. + schema: + type: string + - variable: username + label: Username + description: The username for the SMB share. + schema: + type: string + required: true + - variable: password + label: Password + description: The password for the SMB share. + schema: + type: string + required: true + private: true + - variable: size + label: Size (in Gi) + description: The size of the volume quota. + schema: + type: int + required: true + min: 1 + default: 1 + + - variable: resources + group: Resources Configuration + label: "" + schema: + type: dict + attrs: + - variable: limits + label: Limits + schema: + type: dict + attrs: + - variable: cpu + label: CPU + description: CPU limit for Palworld. + schema: + type: string + max_length: 6 + valid_chars: '^(0\.[1-9]|[1-9][0-9]*)(\.[0-9]|m?)$' + valid_chars_error: | + Valid CPU limit formats are
+ - Plain Integer - eg. 1
+ - Float - eg. 0.5
+ - Milicpu - eg. 500m + default: "4000m" + required: true + - variable: memory + label: Memory + description: Memory limit for Palworld. + schema: + type: string + max_length: 12 + valid_chars: '^[1-9][0-9]*([EPTGMK]i?|e[0-9]+)?$' + valid_chars_error: | + Valid Memory limit formats are
+ - Suffixed with E/P/T/G/M/K - eg. 1G
+ - Suffixed with Ei/Pi/Ti/Gi/Mi/Ki - eg. 1Gi
+ - Plain Integer in bytes - eg. 1024
+ - Exponent - eg. 134e6 + default: "8Gi" + required: true diff --git a/community/palworld/1.0.0/templates/NOTES.txt b/community/palworld/1.0.0/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/community/palworld/1.0.0/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/community/palworld/1.0.0/templates/_palworld.tpl b/community/palworld/1.0.0/templates/_palworld.tpl new file mode 100644 index 0000000000..b27cbcd8b2 --- /dev/null +++ b/community/palworld/1.0.0/templates/_palworld.tpl @@ -0,0 +1,99 @@ +{{- define "palworld.workload" -}} +workload: + palworld: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: {{ .Values.palworldNetwork.hostNetwork }} + securityContext: + fsGroup: {{ .Values.palworldID.group }} + containers: + palworld: + enabled: true + primary: true + imageSelector: image + securityContext: + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + readOnlyRootFilesystem: false + capabilities: + add: + - CHOWN + - DAC_OVERRIDE + - FOWNER + - SETGID + - SETUID + - KILL + env: + STEAMCMD_DIR: /serverdata/steamcmd + {{- $srvDir := "/serverdata/serverfiles" }} + SERVER_DIR: {{ $srvDir }} + SRV_ADMIN_PWD: {{ .Values.palworldConfig.adminPassword }} + GAME_PARAMS: {{ join " " .Values.palworldNetwork.serverPort }} + GAME_PARAMS_EXTRA: {{ join " " .Values.palworldConfig.gameParamsExtra }} + UPDATE_PUBLIC_IP: {{ .Values.palworldConfig.updatePublicIP }} + VALIDATE: {{ .Values.palworldConfig.validate }} + USERNAME: {{ .Values.palworldConfig.username }} + PASSWORD: {{ .Values.palworldConfig.password }} + fixedEnv: + PUID: {{ .Values.palworldID.user }} + {{ with .Values.palworldConfig.additionalEnvs }} + envList: + {{ range $env := . }} + - name: {{ $env.name }} + value: {{ $env.value }} + {{ end }} + {{ end }} + probes: + liveness: + enabled: true + type: tcp + port: {{ .Values.palworldNetwork.rconPort }} + readiness: + enabled: true + type: tcp + port: {{ .Values.palworldNetwork.rconPort }} + startup: + enabled: true + type: tcp + port: {{ .Values.palworldNetwork.rconPort }} + initContainers: + 01-config: + enabled: true + type: init + imageSelector: image + securityContext: + runAsUser: 0 + runAsGroup: 0 + runAsNonRoot: false + readOnlyRootFilesystem: false + capabilities: + add: + - CHOWN + - DAC_OVERRIDE + - FOWNER + command: /bin/bash + args: + - -c + - | + config={{ $srvDir }}/Pal/Saved/Config/LinuxServer + cfgFile=${config}/PalWorldSettings.ini + mkdir -p ${config} + if [ ! -f ${cfgFile} ]; then + echo "Config file not found, fetching..." + # Fetch the config file if it doesn't exist, just like the container does + wget -qO ${cfgFile} https://github.com/ich777/docker-steamcmd-server/raw/palworld/config/PalWorldSettings.ini + fi + echo "Setting RCON status..." + sed -i 's/\(RCONEnabled=\)[^,]*/\1True/g' ${cfgFile} + echo "Set to [$(grep -Po 'RCONEnabled=[^,]*' ${cfgFile})]" + echo "Setting RCON Port..." + sed -i 's/\(RCONPort=\)[^,]*/\1{{ .Values.palworldNetwork.rconPort }}/g' ${cfgFile} + echo "Set to [$(grep -Po 'RCONPort=[^,]*' ${cfgFile})]" + echo "Setting Game Port..." + sed -i 's/\(PublicPort=\)[^,]*/\1{{ .Values.palworldNetwork.serverPort }}/g' ${cfgFile} + echo "Set to [$(grep -Po 'PublicPort=[^,]*' ${cfgFile})]" + echo "Done!" +{{- end -}} diff --git a/community/palworld/1.0.0/templates/_persistence.tpl b/community/palworld/1.0.0/templates/_persistence.tpl new file mode 100644 index 0000000000..ef7428479b --- /dev/null +++ b/community/palworld/1.0.0/templates/_persistence.tpl @@ -0,0 +1,35 @@ +{{- define "palworld.persistence" -}} +persistence: + steamcmd: + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" .Values.palworldStorage.steamcmd) | nindent 4 }} + targetSelector: + palworld: + palworld: + mountPath: /serverdata/steamcmd + server: + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" .Values.palworldStorage.server) | nindent 4 }} + targetSelector: + palworld: + palworld: + mountPath: /serverdata/serverfiles + 01-config: + mountPath: /serverdata/serverfiles + tmp: + enabled: true + type: emptyDir + targetSelector: + palworld: + palworld: + mountPath: /tmp + {{- range $idx, $storage := .Values.palworldStorage.additionalStorages }} + {{ printf "palworld-%v:" (int $idx) }} + enabled: true + {{- include "ix.v1.common.app.storageOptions" (dict "storage" $storage) | nindent 4 }} + targetSelector: + palworld: + palworld: + mountPath: {{ $storage.mountPath }} + {{- end }} +{{- end -}} diff --git a/community/palworld/1.0.0/templates/_service.tpl b/community/palworld/1.0.0/templates/_service.tpl new file mode 100644 index 0000000000..ac1d184bfc --- /dev/null +++ b/community/palworld/1.0.0/templates/_service.tpl @@ -0,0 +1,21 @@ +{{- define "palworld.service" -}} +service: + palworld: + enabled: true + primary: true + type: NodePort + targetSelector: palworld + ports: + server: + enabled: true + primary: true + port: {{ .Values.palworldNetwork.serverPort }} + nodePort: {{ .Values.palworldNetwork.serverPort }} + protocol: udp + targetSelector: palworld + rcon: + enabled: true + port: {{ .Values.palworldNetwork.rconPort }} + nodePort: {{ .Values.palworldNetwork.rconPort }} + targetSelector: palworld +{{- end -}} diff --git a/community/palworld/1.0.0/templates/_validation.tpl b/community/palworld/1.0.0/templates/_validation.tpl new file mode 100644 index 0000000000..b0bab79a7a --- /dev/null +++ b/community/palworld/1.0.0/templates/_validation.tpl @@ -0,0 +1,7 @@ +{{- define "palworld.validation" -}} + {{- range $param := .Values.palworldConfig.gameParams -}} + {{- if hasPrefix "port=" $param -}} + {{- fail "PalWorld - [port=] param is automatically adjusted from the Server Port field" -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/community/palworld/1.0.0/templates/common.yaml b/community/palworld/1.0.0/templates/common.yaml new file mode 100644 index 0000000000..faabd7f405 --- /dev/null +++ b/community/palworld/1.0.0/templates/common.yaml @@ -0,0 +1,10 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{- include "palworld.validation" $ -}} + +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "palworld.workload" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "palworld.service" $ | fromYaml) -}} +{{- $_ := mustMergeOverwrite .Values (include "palworld.persistence" $ | fromYaml) -}} + +{{- include "ix.v1.common.loader.apply" . -}} diff --git a/community/palworld/1.0.0/upgrade_strategy_disabled b/community/palworld/1.0.0/upgrade_strategy_disabled new file mode 100755 index 0000000000..924794842c --- /dev/null +++ b/community/palworld/1.0.0/upgrade_strategy_disabled @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +import json +import re +import sys + +from catalog_update.upgrade_strategy import semantic_versioning + + +RE_STABLE_VERSION = re.compile(r'v\d+\.\d+\.\d+') + + +def newer_mapping(image_tags): + key = list(image_tags.keys())[0] + temp_tags = {t.strip('v'): t for t in image_tags[key] if RE_STABLE_VERSION.fullmatch(t)} + + # Strip leading zeros + tags = {} + for tag in temp_tags: + tag = tag.split('.') + for i in range(len(tag)): + # Remove leading zeros + tag[i] = tag[i].lstrip('0') + tags[tag] = '.'.join(tag) + + version = semantic_versioning(list(tags)) + if not version: + return {} + + return { + 'tags': {key: tags[version]}, + 'app_version': version, + } + + +if __name__ == '__main__': + try: + versions_json = json.loads(sys.stdin.read()) + except ValueError: + raise ValueError('Invalid json specified') + + print(json.dumps(newer_mapping(versions_json))) diff --git a/community/palworld/item.yaml b/community/palworld/item.yaml new file mode 100644 index 0000000000..cd5c6ceb5c --- /dev/null +++ b/community/palworld/item.yaml @@ -0,0 +1,6 @@ +icon_url: https://media.sys.truenas.net/apps/palworld/icons/icon.webp +categories: + - games +screenshots: [] +tags: + - palworld