First, here’s the core of my manifest showing everything the flatpak should have access to:
id: io.github.evilsupahfly.amulet_flatpak
runtime: org.freedesktop.Platform
runtime-version: '24.08'
sdk: org.freedesktop.Sdk
command: amulet_map_editor
finish-args:
- --device=all
- --device=dri
- --allow=devel
- --allow=per-app-dev-shm
- --share=network
- --share=ipc
- --socket=fallback-x11
- --socket=wayland
- --filesystem=host
- --filesystem=host-os
- --filesystem=home
- --filesystem=/tmp
- --filesystem=xdg-config/AmuletMapEditor:create
- --filesystem=xdg-cache/AmuletMapEditor:create
- --filesystem=xdg-run/gvfs
- --filesystem=xdg-run/gvfsd
- --talk-name=org.freedesktop.Notifications
- --env=LIBGL_ALWAYS_SOFTWARE="0"
- --env=OPENGL_VERSION=3.3
- --env=OPENGL_LIB=/usr/lib/x86_64-linux-gnu/libGL.so
- --env=PS1=[ AMULET_FLATPAK > \w ] >
- --env=PYTHONPATH=/app/lib/python3.12
# Uncomment the following options to increase debug output verbosity in the terminal
# - --env=PYTHONDEBUG=3
# - --env=PYTHONVERBOSE=3
# - --env=PYTHONTRACEMALLOC=10
# - --env=G_MESSAGES_DEBUG=all
modules:
- shared-modules/libjpeg8/libjpeg8.json
- shared-modules/glew/glew.json
- shared-modules/glu/glu-9.json
- pip-gen.yaml
- flatpak-debug-build.yaml
- name: metainfo-xml
buildsystem: simple
build-commands:
- install -Dm644 io.github.evilsupahfly.amulet_flatpak.metainfo.xml -t ${FLATPAK_DEST}/share/metainfo/
sources:
- type: file
path: io.github.evilsupahfly.amulet_flatpak.metainfo.xml
- name: metainfo-desktop
buildsystem: simple
build-commands:
- install -Dm755 io.github.evilsupahfly.amulet_flatpak.desktop -t ${FLATPAK_DEST}/share/applications/
sources:
- type: file
path: io.github.evilsupahfly.amulet_flatpak.desktop
- name: metainfo-ico
buildsystem: simple
build-commands:
- install -Dm644 io.github.evilsupahfly.amulet_flatpak.png -t ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/
sources:
- type: file
path: io.github.evilsupahfly.amulet_flatpak.png
- name: amulet-debug
buildsystem: simple
build-commands:
- install -Dm555 debug.sh -t ${FLATPAK_DEST}/bin/
sources:
- type: file
path: debug.sh
In theory, this should give me unfettered (or as close as possible) access to HOME and the XDG folders. Now, here’s the background. I am (still) attempting to turn the Python-built Amulet Map Editor into a Flatpak app, but I’m encountering issues with bundled files. When I install Amulet into a Python VENV, it works fine. But when I run the flatpak, I get errors:
2025-09-01 19:11:37.261 | DEBUG | resource_pack_manager.py:247 | get_texture_path() | [PROBE:TEXTURE] Called with ns=minecraft, rel=block/water
2025-09-01 19:11:37.261 | DEBUG | resource_pack_manager.py:258 | get_texture_path() | [TEXTURE FOUND - PRIMARY] ns=minecraft, rel=block/water, abs=/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png
2025-09-01 19:11:37.262 | ERROR | resource_pack_manager.py:303 | _get_model() | Failed to load block model {'model': 'minecraft:block/water'}
'/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png'
Call stack:
File "/usr/lib/python3.12/threading.py", line 1012, in run
self._target(*self._args, **self._kwargs)
File "/app/lib/python3.12/site-packages/amulet_map_editor/programs/edit/api/chunk_generator.py", line 32, in _generate_chunks
self.thread_action()
File "/app/lib/python3.12/site-packages/amulet_map_editor/api/opengl/thread_generator.py", line 48, in thread_action
self._objects[self._obj_index].thread_action()
File "/app/lib/python3.12/site-packages/amulet_map_editor/api/opengl/mesh/level/level.py", line 168, in thread_action
chunk.create_geometry()
File "/app/lib/python3.12/site-packages/amulet_map_editor/api/opengl/mesh/level/chunk/chunk.py", line 185, in create_geometry
chunk_verts, chunk_verts_translucent = self._create_lod0_multi(
File "/app/lib/python3.12/site-packages/amulet_map_editor/api/opengl/mesh/level/chunk/chunk_builder.py", line 73, in _create_lod0_multi
return create_lod0_chunk(
File "/app/lib/python3.12/site-packages/amulet_map_editor/api/opengl/resource_pack/resource_pack.py", line 203, in get_block_model
self._block_models[universal_block] = self._resource_pack.get_block_model(version_block)
File "/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/base/resource_pack_manager.py", line 74, in get_block_model
+ tuple(self._get_model(block_) for block_ in block.extra_blocks)
File "/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/base/resource_pack_manager.py", line 74, in <genexpr>
+ tuple(self._get_model(block_) for block_ in block.extra_blocks)
File "/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/resource_pack_manager.py", line 303, in _get_model
log.error(f"Failed to load block model {model}\n{e}\nCall stack:\n" + "".join(traceback.format_stack(limit=10)))
The files are all there. I can run a shell prompt inside my flatpak, and list the files right where it says they’re missing. All these .png and .json files, and all the subfolders they reside in under the folder java_vanilla_fix
are ALL bundled with the “minecraft_resource_pack” package and they’re all present in the source wheel used in the flatpak construction. The DEBUG
output proves this:
2025-09-01 19:11:33.385 | DEBUG | resource_pack_manager.py:235 | _load_iter() | [SANITY:PRIMARY] {('minecraft', 'block/water_still'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water_still.png', True), ('minecraft', 'block/lava_flow'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava_flow.png', True), ('minecraft', 'block/lava_still'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava_still.png', True), ('minecraft', 'block/water_flow'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water_flow.png', True), ('minecraft', 'block/water_overlay'): ('/home/seann/.var/app/io.github.evilsupahfly.amulet_flatpak/cache/AmuletMapEditor/resource_packs/java/vanilla/assets/minecraft/textures/block/water_overlay.png', True), ('minecraft', 'block/lava'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png', True), ('minecraft', 'block/water'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png', True)}
2025-09-01 19:11:33.385 | DEBUG | resource_pack_manager.py:236 | _load_iter() | [SANITY:BACKUP ] {('minecraft', 'block/water_still'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water_still.png', True), ('minecraft', 'block/lava_flow'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava_flow.png', True), ('minecraft', 'block/lava_still'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava_still.png', True), ('minecraft', 'block/water_flow'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water_flow.png', True), ('minecraft', 'block/water_overlay'): ('/home/seann/.var/app/io.github.evilsupahfly.amulet_flatpak/cache/AmuletMapEditor/resource_packs/java/vanilla/assets/minecraft/textures/block/water_overlay.png', True), ('minecraft', 'block/lava'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/lava.png', True), ('minecraft', 'block/water'): ('/app/lib/python3.12/site-packages/minecraft_model_reader/api/resource_pack/java/java_vanilla_fix/assets/minecraft/textures/block/water.png', True)}
Also, Amulet is able to download the minecraft version-secific textures from the Minecraft launcher website after loading a Minecraft save from the user’s $HOME/.minecraft/saves
folder, and save them to the XDG-defined cache, but it fails to read the files bundled with its own component, minecraft_model_reader
.
To get around this, I figured I would simply have the bundled texture folder copied to cache, and use them from that location instead, so I modified the minecraft_model_reader
module to do just this, and it still failed. Inside Amulet, the paths are defined as follows:
data_dir = platformdirs.user_data_dir("AmuletMapEditor", "AmuletTeam")
os.environ.setdefault("DATA_DIR", data_dir)
config_dir = platformdirs.user_config_dir("AmuletMapEditor", "AmuletTeam")
if config_dir == data_dir:
config_dir = os.path.join(data_dir, "Config")
os.environ.setdefault("CONFIG_DIR", config_dir)
os.environ.setdefault("CACHE_DIR", platformdirs.user_cache_dir("AmuletMapEditor", "AmuletTeam"))
os.environ.setdefault("LOG_DIR", platformdirs.user_log_dir("AmuletMapEditor", "AmuletTeam"))
So… Can somebody please explain to me why this works fine when I install it into a VENV with PIP but fails when the exact same code is built into a flatpak?
The java_vanilla_fix
folder bundled with minecraft_model_reader
contains about 400 files, while the primary cache contains about 9,900 - am I up against a ulimit
cap or limit, and if so, can I extend that ceiling within the flatpak or am I bound by the ulimit
defined by the host system? If it’s not ulimit
, what other reason is there for the app to successfully locate the files, then suddenly say it can’t find them?
The Python code itself is sound, because there are no issues at all when installed inside a VENV. And while I suppose everybody could just do that, I figured making it into a flatpak would be easier for novice users who might not understand the complexities of creating and maintaining a Python virtual environment.
If you need anything clarified or want to see anything, the entire flatpak project is located in my GIT repo. The sum total of this project is all there: all the YAML/JSON manifest files, all the packages I modified for debug logging, even the shell scripts I run locally to automate everything so I don’t have to keep entering commands each step of the way. Literally EVERYTHING.
Amulet is a fantastic tool, but it’s not very effective with missing textures so I would love to get to the bottom of this!