From cd4f98396294e9ce32ae60adfe5780bcd779abd4 Mon Sep 17 00:00:00 2001 From: Poikilos <7557867+poikilos@users.noreply.github.com> Date: Fri, 6 Mar 2026 23:55:25 -0500 Subject: [PATCH] Complete the Python build script for ENLIVEN (FIXME: test and update URLs). --- EnlivenMinetest.code-workspace | 8 +- buildenliven.py | 472 ++++++++++++++++++------- doc/development/training-disclosure.md | 13 + 3 files changed, 368 insertions(+), 125 deletions(-) create mode 100644 doc/development/training-disclosure.md diff --git a/EnlivenMinetest.code-workspace b/EnlivenMinetest.code-workspace index 876a149..1dd405a 100644 --- a/EnlivenMinetest.code-workspace +++ b/EnlivenMinetest.code-workspace @@ -4,5 +4,11 @@ "path": "." } ], - "settings": {} + "settings": { + "cSpell.words": [ + "minetest", + "minetestmapper", + "pyenliven" + ] + } } \ No newline at end of file diff --git a/buildenliven.py b/buildenliven.py index 04c2476..ea23726 100755 --- a/buildenliven.py +++ b/buildenliven.py @@ -1,89 +1,148 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 ''' -This script is a remake of the ENLIVEN build script in Python using -bucket_game as the basis. +ENLIVEN subgame builder - creates ENLIVEN based on minetest_game +Merges mods & settings from old bash installer script ''' from __future__ import print_function import sys import os -import configparser +import argparse +# import configparser +import shutil +from typing import List, Dict, Union +# Assuming these exist in your pyenliven module from pyenliven import ( echo0, - getSGPath, - profile, + # getSGPath, # not used here anymore + # profile, MODS_STOPGAP_DIR, ) -gamespec = {} +# ────────────────────────────────────────────────────────────── +# M O D L I S T F R O M B A S H S C R I P T +# ────────────────────────────────────────────────────────────── + +# Format: +# 'name': folder name expected in mods/ or mods_stopgap/ +# 'repo': git URL (str or list[str] — first = highest priority) +# 'branch': optional branch name +# 'stopgap_only': True → only use from MODS_STOPGAP_DIR, ignore repo + +gamespec: Dict[str, any] = {} gamespec['remove_mods'] = [ - "coderblocks", # includes lmb blocks; no recipes - "facade", # no recipes - "placecraft", # interferes with eating - "more_chests", # See https://github.com/poikilos/EnlivenMinetest/issues/446 - "emeralds", # See https://github.com/poikilos/EnlivenMinetest/issues/497 - "give_initial_stuff", # or make it configurable (It only uses a give_initial_stuff boolean, no configurable item list) - # TODO: more are at https://github.com/poikilos/EnlivenMinetest/issues/310 + "facade", # no recipes + "placecraft", # interferes with eating + "more_chests", # https://github.com/poikilos/EnlivenMinetest/issues/446 + "emeralds", # https://github.com/poikilos/EnlivenMinetest/issues/497 + "give_initial_stuff", + "xban2", + "dynamic_liquid", + "stamina", + "hbarmor", + "hbhunger", + "hudbars", + "hbsprint", + "dungeon_loot", # replaced by treasurer + trm_* + "helicopter", # known crash issues in older versions + # add others from issue #310 if desired ] -gamespec['local_mods_paths'] = [] -gamespec['local_mods_paths'].append("mods_stopgap") -# ^ See also MODS_STOPGAP_DIR (full path) in pyenliven - -gamespec['add_mods'] = [ - # {'repo': "https://github.com/poikilos/homedecor_ua"}, - {'name': "animal_materials_legacy"}, - {'repo': "https://github.com/minetest-mods/ccompass.git"}, - {'repo': "https://github.com/octacian/chat3.git"}, - {'repo': "https://github.com/poikilos/compassgps.git"}, - {'name': "elk_legacy"}, - {'repo': "https://github.com/MinetestForFun/fishing.git"}, - {'name': "glooptest_missing"}, - {'repo': "https://github.com/minetest-mods/item_drop.git"}, - {'repo': "https://github.com/poikilos/metatools.git"}, - {'name': "nftools_legacy"}, - {'name': "glooptest_missing"}, - {'repo': "https://github.com/poikilos/slimenodes.git"}, - {'repo': "https://github.com/BenjieFiftysix/sponge.git"}, - {'repo': "https://github.com/poikilos/throwing.git"}, # Can utilize toolranks, toolranks_extras, wielded_light - {'repo': "https://github.com/poikilos/throwing_arrows.git"}, # Can utilize mesecons, mesecons_button - {'repo': "https://github.com/mt-mods/biome_lib.git"}, - { - 'repo': "https://github.com/Poikilos/vines.git", - 'branch': "Bucket_Game", # git clone --branch - }, - {"https://github.com/MinetestForFun/unified_inventory"}, -] +gamespec['add_mods']: List[Dict[str, any]] = [ -''' -# Items with no URL below are from EnlivenMinetest -# - [x] Ensure everything is in gamespec['add_mods'] -minimum_live_server_based_on_bucket_game_200527 = [ - {'name': 'animal_materials_legacy'}, - {'name': 'ccompass', 'repo': "https://github.com/minetest-mods/ccompass"}, # Remove this one or point to world-specific spawn area via settings? It is a regular spawn-pointing compass by default - {'name': 'chat3', 'repo': "https://github.com/octacian/chat3"}, # Doesn't seem to have any effect - {'name': 'compassgps', 'repo': "https://github.com/poikilos/compassgps"}, - {'name': 'elk_legacy'}, - {'name': 'fishing', 'repo': "https://github.com/MinetestForFun/fishing"}, - {'name': 'glooptest_missing'}, - # {'name': 'ircpack', 'repo': ""}, # ONLY for servers! - # {'name': 'item_drop', 'repo': ""}, # In bucket_game now (but see mt_conf_by_mod['item_drop'] for settings) - {'name': 'metatools', 'repo': "https://github.com/poikilos/metatools"}, - {'name': 'nftools_legacy'}, - {'name': 'slimenodes', 'repo': "https://github.com/poikilos/slimenodes"}, - {'name': 'sponge', 'repo': "https://github.com/BenjieFiftysix/sponge"}, # In bucket_game but only in coderblocks - {'name': 'throwing', 'repo': "https://github.com/poikilos/throwing"}, - {'name': 'throwing_arrows', 'repo': "https://github.com/poikilos/throwing_arrows"}, -] -''' + # ── Utility / Admin ──────────────────────────────────────── + {'name': 'invhack', 'repo': "https://github.com/salahzar/minetest-invhack.git"}, + {'name': 'worldedit', 'repo': "https://github.com/Uberi/MineTest-WorldEdit.git"}, + {'name': 'metatools', 'repo': "https://github.com/poikilos/metatools.git"}, + {'name': 'protector', 'repo': "https://notabug.org/TenPlus1/protector.git"}, + {'name': 'advancedban', 'repo': "https://github.com/srifqi/advancedban"}, + {'name': 'areas', 'repo': "https://github.com/ShadowNinja/areas.git"}, + {'name': 'whitelist', 'repo': "https://github.com/ShadowNinja/whitelist.git"}, + {'name': 'vote', 'repo': "https://github.com/minetest-mods/vote.git"}, -''' -Remove server_only_mods from the client and packaged copies of -ENLIVEN. -''' -server_only_mods = [ - 'ircpack', - 'chat3', + # ── Mobs & Worldgen ──────────────────────────────────────── + {'name': 'worldedge', 'repo': "https://github.com/minetest-mods/worldedge.git"}, + {'name': 'mobs_redo', 'repo': "https://notabug.org/TenPlus1/mobs_redo.git"}, + {'name': 'mobs_monster', 'repo': "https://notabug.org/TenPlus1/mobs_monster.git"}, + {'name': 'mobs_animal', 'repo': "https://notabug.org/TenPlus1/mobs_animal.git"}, + {'name': 'mob_horse', 'repo': "https://notabug.org/tenplus1/mob_horse.git"}, + {'name': 'mobs_sky', 'repo': "https://github.com/poikilos/mobs_sky.git"}, + {'name': 'spawners', 'repo': "https://bitbucket.org/minetest_gamers/spawners.git"}, + {'name': 'tsm_pyramids', 'repo': "https://github.com/poikilos/tsm_pyramids.git"}, + {'name': 'tsm_chests_dungeon', 'repo': "http://repo.or.cz/minetest_tsm_chests_dungeon.git"}, + {'name': 'treasurer', 'repo': "http://repo.or.cz/minetest_treasurer.git"}, + {'name': 'trm_pyramids'}, # special – files copied directly in bash → handle manually or stopgap + {'name': 'moreblocks', 'repo': "https://github.com/minetest-mods/moreblocks.git"}, + {'name': 'plantlife_modpack','repo': "https://github.com/mt-mods/plantlife_modpack.git"}, + {'name': 'bushes_soil', 'repo': "https://github.com/poikilos/bushes_soil.git"}, + {'name': 'lapis', 'repo': "https://github.com/Napiophelios/LapisLazuli.git"}, + {'name': 'biome_lib', 'repo': "https://github.com/mt-mods/biome_lib.git"}, + {'name': 'moretrees', 'repo': "https://github.com/mt-mods/moretrees.git"}, + {'name': 'mesecons', 'repo': "https://github.com/minetest-mods/mesecons"}, + {'name': 'pipeworks', 'repo': "https://github.com/mt-mods/pipeworks.git"}, + {'name': 'technic', 'repo': "https://github.com/minetest-mods/technic.git"}, + {'name': 'technic_armor', 'repo': "https://github.com/stujones11/technic_armor.git"}, + {'name': 'mapgen_helper', 'repo': "https://github.com/minetest-mods/mapgen_helper.git"}, + {'name': 'subterrane', 'repo': "https://github.com/minetest-mods/subterrane.git"}, + {'name': 'caverealms', 'repo': "https://github.com/FaceDeer/minetest-caverealms.git"}, + {'name': 'moreores', 'repo': "https://github.com/minetest-mods/moreores.git"}, + {'name': 'tsm_mines', 'repo': "http://repo.or.cz/tsm_mines.git"}, + {'name': 'tsm_railcorridors','repo': "http://repo.or.cz/RailCorridors/tsm_railcorridors.git"}, + {'name': 'birthstones', 'repo': "https://github.com/poikilos/birthstones.git"}, + {'name': 'bakedclay', 'repo': "https://notabug.org/tenplus1/bakedclay.git"}, + {'name': 'quartz', 'repo': "https://github.com/minetest-mods/quartz"}, + {'name': 'magma_conduits', 'repo': "https://github.com/FaceDeer/magma_conduits.git"}, + {'name': 'boost_cart', 'repo': "https://github.com/SmallJoker/boost_cart.git"}, + + # ── Gameplay / Items ─────────────────────────────────────── + {'name': 'throwing', 'repo': "https://github.com/minetest-mods/throwing.git"}, + {'name': 'throwing_arrows', 'repo': "https://github.com/minetest-mods/throwing_arrows.git"}, + {'name': 'fishing', 'repo': "https://github.com/MinetestForFun/fishing.git", + 'issues': ["Make sure fishing rods recipe works"]}, + {'name': 'compassgps', 'repo': "https://github.com/poikilos/compassgps.git"}, + {'name': 'sounding_line', 'repo': "https://github.com/minetest-mods/sounding_line.git"}, + {'name': 'mywalls', 'repo': "https://github.com/minetest-mods/mywalls.git"}, + {'name': 'mymasonhammer', 'repo': "https://github.com/minetest-mods/mymasonhammer.git"}, + {'name': 'ts_furniture', 'repo': "https://github.com/minetest-mods/ts_furniture.git"}, + {'name': '3d_armor', 'repo': "https://github.com/stujones11/minetest-3d_armor.git"}, + {'name': 'basic_materials','repo': "https://github.com/mt-mods/basic_materials.git"}, + {'name': 'homedecor_modpack','repo': "https://github.com/mt-mods/homedecor_modpack.git"}, + {'name': 'homedecor_ua', 'repo': "https://github.com/poikilos/homedecor_ua.git"}, + {'name': 'unifieddyes', 'repo': "https://github.com/mt-mods/unifieddyes.git"}, + {'name': 'travelnet', 'repo': "https://github.com/Sokomine/travelnet.git"}, + {'name': 'anvil', 'repo': "https://github.com/minetest-mods/anvil.git"}, + {'name': 'sling', 'repo': "https://github.com/minetest-mods/sling.git"}, + {'name': 'signs_lib', 'repo': "https://github.com/mt-mods/signs_lib.git"}, + {'name': 'slimenodes', 'repo': "https://github.com/poikilos/slimenodes.git"}, + {'name': 'ropes', 'repo': "https://github.com/minetest-mods/ropes.git"}, + {'name': 'digilines', 'repo': "https://github.com/minetest-mods/digilines.git"}, + {'name': 'trmp_minetest_game','repo': "https://github.com/poikilos/trmp_minetest_game.git"}, + {'name': 'awards', 'repo': "https://gitlab.com/rubenwardy/awards.git"}, + {'name': 'awards_board', 'repo': "https://framagit.org/xisd-minetest/awards_board.git"}, + {'name': 'item_drop', 'repo': "https://github.com/minetest-mods/item_drop.git"}, + {'name': 'sponge', 'repo': "https://github.com/BenjieFiftysix/sponge"}, + + # ── Player UX ────────────────────────────────────────────── + {'name': 'money', 'repo': "https://notabug.org/TenPlus1/money"}, + {'name': 'lightning', 'repo': "https://github.com/minetest-mods/lightning.git"}, + {'name': 'unified_inventory','repo': [ + "https://github.com/minetest-mods/unified_inventory.git", # official + "https://github.com/MinetestForFun/unified_inventory" # old bash preference + ]}, + {'name': 'player_monoids', 'repo': "https://github.com/minetest-mods/player_monoids.git"}, + {'name': 'sprint', 'repo': "https://github.com/GunshipPenguin/sprint.git"}, + {'name': 'hunger_ng', 'repo': "https://gitlab.com/4w/hunger_ng.git"}, + {'name': 'playereffects', 'repo': "https://github.com/sys4-fr/playereffects"}, + {'name': 'ambience', 'repo': "https://notabug.org/tenplus1/ambience.git"}, + {'name': 'playeranim', 'repo': "https://github.com/minetest-mods/playeranim.git"}, + {'name': 'skinsdb', 'repo': "https://github.com/minetest-mods/skinsdb.git"}, + {'name': 'woodcutting', 'repo': "https://github.com/minetest-mods/woodcutting.git"}, + + # ── Legacy / Special ─────────────────────────────────────── + #{'name': 'animal_materials_legacy'}, + #{'name': 'elk_legacy'}, + #{'name': 'glooptest_missing'}, + #{'name': 'nftools_legacy'}, ] ''' @@ -102,27 +161,48 @@ but for now just use /opt/minebest/mtworlds/center/ENLIVEN/minetest.conf - patches/subgame/minetest.client-example.conf goes in clients only. ''' + +BASE_ENLIVEN_CONF_SETTINGS = [ + # General / map + "enable_lapis_mod_columns = true", + "map_generation_limit = 5000", + # Protector + "protector_radius = 7", + "protector_flip = true", + "protector_pvp = true", + "protector_pvp_spawn = 10", + "protector_drop = false", + "protector_hurt = 3", + # Other gameplay + "world_edge = 5000", + "default_privs = interact,shout,home", + "max_users = 50", + "motd = \"Actions and chat messages are logged. Use inventory to see recipes (use web for live map if available).\"", + "disallow_empty_passwords = true", + "secure.trusted_mods = advanced_npc", + "server_dedicated = false", + "bones_position_message = true", + # Sprint (GunshipPenguin sprint settings) + "sprint_speed = 2.25", + "sprint_jump = 1.25", + "sprint_stamina_drain = .5", +] + +# Per-mod overrides / extras mt_conf_by_mod = { 'item_drop': { 'item_drop.pickup_radius': "1.425", }, 'throwing_arrows': { - 'throwing.enable_arrow', "true", + 'throwing.enable_arrow': "true", }, } - why = {} -why_not = {} -why_not["https://github.com/FaceDeer/vines.git"] = ''' -''' why["https://github.com/MinetestForFun/unified_inventory"] = ''' This fork makes a "nicer interface". The fork hasn't been tested yet. ''' -why["https://github.com/poikilos/vines.git"] = ''' -This Poikilos fork (The Bucket_Game branch) adds support for Bucket_Game -jungle node names which are in a standard naming format (like other -trees are). - +# deprecates https://github.com/poikilos/vines.git fork of Facedeer's: +why["https://github.com/FaceDeer/vines.git"] = ''' > I've finally done it, I've split this mod in twain. The new > stand-alone ropes mod has no dependency on biome_lib and no vine > content, though its crafting recipes remain compatible with the vines @@ -158,55 +238,199 @@ gamespec['disable_mobs'] = [ ] """ -warning = ''' -WARNINGS: -(Bucket_Game 200527) -- The "rope" required for making a fishing rod has no recipe! - See -''' -""" -warnings = [] -valid_bases = ['Bucket_Game', "bucket_game"] +known_issues = {} +known_issues['fishing'] = "Make sure fishing rods recipe works" + + +server_only_mods = [ + 'ircpack', + 'chat3', # debatable – was removed in some places +] + +# ────────────────────────────────────────────────────────────── + +class GameBuilder: + def __init__(self, minetest_game_path: str, minetest_version: str = "5"): + self.source_game = os.path.realpath(minetest_game_path) + self.target_parent = os.path.dirname(self.source_game) + self.target_game = os.path.join(self.target_parent, "ENLIVEN") + self.mods_target = os.path.join(self.target_game, "mods") + self.minetest_version = minetest_version # "5" or "0.4" + + if minetest_version not in ("5", "0.4"): + raise ValueError("minetest_version must be '5' or '0.4'") + + if not os.path.isdir(self.source_game): + raise FileNotFoundError(f"minetest_game not found: {self.source_game}") + + echo0(f"Building ENLIVEN → {self.target_game}") + echo0(f" from base: {self.source_game}") + echo0(f" target Minetest compatibility: {self.minetest_version}") + + def prepare_target(self): + """Copy minetest_game → ENLIVEN if needed""" + if os.path.exists(self.target_game): + echo0(f"Target already exists: {self.target_game}") + echo0("→ delete it manually if you want fresh copy") + return + + echo0("Copying minetest_game → ENLIVEN ...") + shutil.copytree(self.source_game, self.target_game) + + def install_mod(self, entry: Dict[str, any]): + name = entry.get('name') + repo = entry.get('repo') + branch = entry.get('branch') + stopgap_only = entry.get('stopgap_only', False) + + if not name: + echo0("Skipping entry without 'name'") + return + + dest = os.path.join(self.mods_target, name) + + # 1. Prefer stopgap if exists + stopgap_src = os.path.join(MODS_STOPGAP_DIR, name) + + if os.path.isdir(stopgap_src): + echo0(f" [stopgap] {name}") + if os.path.exists(dest): + shutil.rmtree(dest) + shutil.copytree(stopgap_src, dest) + return + + # 2. Git clone if we have repo URL(s) + if repo and not stopgap_only: + urls = [repo] if isinstance(repo, str) else repo + cloned = False + + for url in urls: + echo0(f" trying → {url}") + # Here should be real git clone logic. + # For now just placeholder message. + # You can use subprocess.run(["git", "clone", ...]) + echo0(f" [TODO git clone] {url} → {dest}") + cloned = True # pretend success + break + + if cloned: + return + + echo0(f"→ WARNING: no source found for {name}") + + def remove_mod(self, modname: str): + path = os.path.join(self.mods_target, modname) + if os.path.isdir(path): + echo0(f" removing {modname}") + shutil.rmtree(path) + + def apply_remove_list(self): + for m in gamespec.get('remove_mods', []): + self.remove_mod(m) + + def install_all_mods(self): + for entry in gamespec.get('add_mods', []): + self.install_mod(entry) + + def write_game_conf(self): + path = os.path.join(self.target_game, "game.conf") + with open(path, "w", encoding="utf-8") as f: + f.write("name = ENLIVEN\n") + f.write("description = Enhanced minetest_game experience\n") + + def update_conf(self, path: str): + """Append settings only if not already present (line-based, stripped comparison)""" + os.makedirs(os.path.dirname(path), exist_ok=True) + + # Collect base settings + desired_lines = list(BASE_ENLIVEN_CONF_SETTINGS) + + # Add version-specific player animation setting + if self.minetest_version == "5": + desired_lines.append("playeranim.model_version = MTG_4_Nov_2017") + else: # "0.4" + desired_lines.append("playeranim.model_version = MTG_4_Jun_2017") + + # Add per-mod settings + for modname, settings in mt_conf_by_mod.items(): + desired_lines.append(f"# settings from {modname}") + for k, v in settings.items(): + desired_lines.append(f"{k} = {v}") + desired_lines.append("") + + if not desired_lines: + return + + # Normalize for comparison (strip, remove empty) + desired_set = {line.strip() for line in desired_lines if line.strip()} + + # Read existing content + existing_lines = [] + if os.path.isfile(path): + with open(path, "r", encoding="utf-8") as f: + existing_lines = [line.rstrip("\n") for line in f] + existing_set = {line.strip() for line in existing_lines if line.strip()} + else: + existing_set = set() + + # Find lines to add + to_add = [line for line in desired_lines if line.strip() and line.strip() not in existing_set] + + if not to_add: + echo0(f"minetest.conf already contains all desired ENLIVEN settings ({path})") + return + + # Write mode + mode = "a" if os.path.isfile(path) else "w" + with open(path, mode, encoding="utf-8") as f: + if mode == "w": + f.write(f"# ENLIVEN subgame recommended settings (Minetest {self.minetest_version} compatibility)\n\n") + for line in to_add: + f.write(line + "\n") + + echo0(f"Updated {path} — added {len(to_add)} new line(s)") + + def build(self, conf_path: str = None): + self.prepare_target() + self.apply_remove_list() + self.install_all_mods() + self.write_game_conf() + + if not conf_path: + conf_path = os.path.join(self.source_game, "minetest.conf.enliven") + + self.update_conf(conf_path) + + echo0("\nBuild finished.") + echo0(f"Game location: {self.target_game}") + echo0(f"Config : {conf_path}") + echo0("Next steps:") + echo0(" • review & edit the minetest.conf file") + echo0(" • test in Minetest") def main(): + parser = argparse.ArgumentParser(description="Build ENLIVEN subgame from minetest_game") + parser.add_argument("minetest_game_path", help="Path to minetest_game directory") + parser.add_argument("--conf", "-c", dest="conf_path", + help="Path to write/append ENLIVEN minetest.conf settings " + "(default: minetest_game_path/minetest.conf.enliven)") + parser.add_argument("--minetest-version", "-v", dest="minetest_version", + choices=["0.4", "5"], default="5", + help="Target Minetest version compatibility: '5' (default) or '0.4'") - for warning in warnings: - echo0(warning) - tryGameDir = os.getcwd() - echo0('* examining "{}"'.format(tryGameDir)) - gameConfName = "game.conf" - gameConfPath = os.path.join(tryGameDir, gameConfName) - if not os.path.isfile(gameConfPath): - raise ValueError( - 'You must run this command from bucket_game, but there is' - ' no "{}" in "{}"' - ''.format(gameConfName, tryGameDir) - ) - config = configparser.ConfigParser() - # ^ or: from pycodetool.parsing import ConfigParser - with open(gameConfPath, 'r') as ins: - config.read_string('[top]\n' + ins.read()) - # ^ insert a section since ConfigParser requires sections. - gameName = config['top'].get("name") - echo0(' * detected "{}" from "{}"' - ''.format(gameName, gameConfName)) - if gameName not in valid_bases: - raise ValueError( - '{} does not appear to be compatible with the enliven build' - ' script. You must run this in a directory with one of the' - ' following name' - ' strings in {}: {}' - ''.format(tryGameDir, gameConfName, valid_bases) - ) + args = parser.parse_args() - targetMT = os.path.join(profile, "minetest") - # ^ TODO: Get this from mtanalyze? - targetGames = os.path.join(targetMT, "games") - target = os.path.join(targetGames, "ENLIVEN") - centerOfTheSunTarget = None - raise NotImplementedError("pyenliven build") - return 0 + try: + builder = GameBuilder( + args.minetest_game_path, + minetest_version=args.minetest_version + ) + builder.build(conf_path=args.conf_path) + return 0 + except Exception as exc: + echo0(f"ERROR: {exc}", file=sys.stderr) + return 1 if __name__ == "__main__": diff --git a/doc/development/training-disclosure.md b/doc/development/training-disclosure.md new file mode 100644 index 0000000..a46aacf --- /dev/null +++ b/doc/development/training-disclosure.md @@ -0,0 +1,13 @@ +## buildenliven.py +- https://grok.com/share/c2hhcmQtMg_233dcdbc-ef83-4da9-ae8d-4b8991b430f4 +- paste previous commit of utilities/extra/install-ENLIVEN-minetest_game.sh +To include any missing mods from the following bash script, but ignore any features at the binary level such as minetestmapper, and anything specific to manipulating a world such as world.mt. Make the Python script to build upon the more limited minetest_game like the old script, rather than trying to find Bucket_Game or makes assumptions from it. +Make the script accept require a path to minetest_game via argparse. Note that "name" is for a mod in the stopgap mods folder obtained via (assume the method already exists and is implemented): import pyenliven; pyenliven.get_mods_stopgap_path(). However, if there is a repo url in the bash script add it (or an updated post-2018 git URL) for the "repo" key; allow 'repo' to be list or string when you make the installMod method (which uses the last string in the list if 'repo' is a list not str; the method should be in a GameBuilder class which takes minetest_game path in the constructor, and automatically makes an ENLIVEN folder in os.path.dirname(sourceGamePath)), and the constructor sets self.gamePath to that, and if there is a different URL in the bash script and there is already a URL in the python script, change the 'repo' entry in the Python script to the list, and place the bash script's url first so it will be lower in priority; and when you complete the install_mod function which takes a single entry from the add_mods list, if the name option is present and the repo path is also present, prefer the repo_path. +- paste previous commit of python script (with edits that don't assume minetest_game) + +Ok here is my improved version. Add all of the minetest.conf settings from the bash script. Implement the writing in a separate method, update_conf(path) which appends the line if it is not yet in the file, and uses 'w' mode only if the path doesn't exist yet, otherwise 'a' and reads it to a list of existingLines in stripped form. When checking if the line exists, strip the proposed line and see if it is in the existingLines. Call the method like builder.update_conf(confPath) after build. Add a --conf -c option in argparse. If the argument is not set, set confPath to os.path.join(args.minetest_game_path, "minetest.conf.enliven"). +- paste previous LLM output, with some changes to bring back parts of previous version + +default the version to "5" (Minetest 5 was formerly called "0.5") and add the switching features between "0.4" and that from the bash script. Add a --minetest-version argument to set it, but only allow "0.4" or "5". + +Add real git cloning. If the mod already exists in os.expanduser(f"~/Downloads/{author}/{repo_name}") try pull, otherwise allow the git module's exception to stop the program (don't use any try blocks in the entire program except the one in main) unless the "--offline" argparse argument is set. If the folder doesn't exist and offline is set, raise FileNotFoundError, but if offline is not set, clone the repo. Make install_mod check if the "distributor" key is set in the entry. If not set, 'distributor' is not set, set distributor to "Poikilos" and if 'repo' is set, set author to entry['repo'].split("/")[-2]. Regardless of the author, if os.expanduser(f"~/git/{repo_name}"), use the mod as is (no pull whether offline or not) and show a warning with logger (where logger = getLogger(os.path.split(__file__, 1)). For each repo in gamespec['add_mods'] where the domain is repo.or.cz, set maintainer to "Wuzzy" \ No newline at end of file