import shutil import os from collections import OrderedDict from decimal import Decimal from typing import Dict, List gamespec: OrderedDict[str, any] = OrderedDict() gamespec['remove_mods'] = [ "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", # or treasurer + trm_* "helicopter", # known crash issues in older versions # add others from issue #310 if desired ] gamespec['add_mods']: List[Dict[str, any]] = [ # ── Utility / Admin ──────────────────────────────────────── # ^ See also inventory_admin mod which is purely command-based {'name': "advancedban", 'repo': "https://github.com/srifqi/advancedban"}, {'name': "areas", 'repo': "https://github.com/ShadowNinja/areas.git"}, {'name': "invhack", 'repo': "https://github.com/salahzar/minetest-invhack.git", 'privs': {'moderator': ['invhack']}, 'items': {'moderator': ['invhack:tool']}}, {'name': "metatools", 'repo': "https://github.com/poikilos/metatools.git"}, {'name': "modlist", 'repo': "https://github.com/SkyBuilder1717/modlist.git"}, # {'name': "protector", 'repo': ["https://notabug.org/TenPlus1/protector.git", # "https://codeberg.org/tenplus1/protector.git"]}, {'name': "protect_block_area", 'repo': "https://github.com/C-C-Minetest-Server/protect_block_area.git"}, {'name': "vote", 'repo': "https://github.com/minetest-mods/vote.git"}, {'name': "whitelist", 'repo': "https://github.com/ShadowNinja/whitelist.git"}, {'name': "worldedit", 'repo': "https://github.com/Uberi/MineTest-WorldEdit.git"}, # Mobs #{'name': "mobs_redo", 'repo': ["https://notabug.org/TenPlus1/mobs_redo.git", # "https://codeberg.org/tenplus1/mobs_redo.git"]}, #{'name': "mobs_monster", 'repo': ["https://notabug.org/TenPlus1/mobs_monster.git", # "https://codeberg.org/tenplus1/mobs_monster.git"]}, #{'name': "mobs_animal", 'repo': ["https://notabug.org/TenPlus1/mobs_animal.git", # "https://codeberg.org/tenplus1/mobs_animal.git"]}, #{'name': "mob_horse", 'repo': ["https://notabug.org/tenplus1/mob_horse.git", # "https://codeberg.org/tenplus1/mob_horse.git"]}, #{'name': "mobs_sky", 'repo': "https://github.com/poikilos/mobs_sky.git"}, #{'name': "mobs_water", 'repo': "https://github.com/blert2112/mobs_water.git"}, #{'name': "dmobs", 'repo': ["https://github.com/minetest-mobs-mods/dmobs.git", # "https://codeberg.org/tenplus1/dmobs"]}, # TODO: ^ Make open_ai mobs api bridge for these {'name': "open_ai", 'repo': "https://github.com/Poikilos/open_ai.git"}, {'name': "spawners", 'repo': "https://bitbucket.org/minetest_gamers/spawners.git"}, # Worldgen {'name': "bakedclay", 'repo': ["https://notabug.org/tenplus1/bakedclay.git", "https://codeberg.org/tenplus1/bakedclay.git"]}, {'name': "biome_lib", 'repo': "https://github.com/mt-mods/biome_lib.git"}, # {'name': "birthstones", 'repo': "https://github.com/poikilos/birthstones.git"}, # commented to reduce inventory overload {'name': "bushes_soil", 'repo': "https://github.com/poikilos/bushes_soil.git"}, {'name': "caverealms", 'repo': "https://github.com/FaceDeer/minetest-caverealms.git"}, {'name': "lapis", 'repo': "https://github.com/Napiophelios/LapisLazuli.git", 'settings': OrderedDict(enable_lapis_mod_columns=True), 'why': "Unlike, minetest-mods/lapis, LapisLazuli has more things you can make."}, {'name': "mapgen_helper", 'repo': "https://github.com/minetest-mods/mapgen_helper.git"}, {'name': "mesecons", 'repo': "https://github.com/minetest-mods/mesecons"}, {'name': "moreblocks", 'repo': "https://github.com/minetest-mods/moreblocks.git"}, {'name': "moreores", 'repo': "https://github.com/minetest-mods/moreores.git"}, {'name': "moretrees", 'repo': "https://github.com/mt-mods/moretrees.git"}, {'name': "plantlife_modpack", 'repo': "https://github.com/mt-mods/plantlife_modpack.git"}, {'name': "pipeworks", 'repo': "https://github.com/mt-mods/pipeworks.git"}, {'name': "subterrane", 'repo': "https://github.com/minetest-mods/subterrane.git"}, {'name': "technic", 'repo': "https://github.com/minetest-mods/technic.git"}, {'name': "technic_armor", 'repo': "https://github.com/stujones11/technic_armor.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"}, # see "loot" mod instead # {'name': "treasurer", 'repo': "http://repo.or.cz/minetest_treasurer.git"}, # {'name': "trm_pyramids"}, # special – files copied directly in bash → handle manually or stopgap # {'name': "tsm_mines", 'repo': "http://repo.or.cz/tsm_mines.git"}, fork of BlockMen’s [Mines](https://forum.minetest.net/viewtopic.php?f=11&t=6307) replaced by tsm_railcorridors # {'name': "tsm_railcorridors", 'repo': ["http://repo.or.cz/RailCorridors/tsm_railcorridors.git", # "https://codeberg.org/Wuzzy/minetest_tsm_railcorridors.git"]}, # TODO: ^ Make loot version of these {'name': "loot", 'repo': "https://github.com/minetest-mods/loot.git", 'why': "Defines loot API and adds loot to dungeons", 'settings': OrderedDict(loot_dungeons=True)}, # {'name': 'quartz', 'repo': "https://github.com/minetest-mods/quartz"}, # commented to reduce inventory overload {'name': "magma_conduits", 'repo': "https://github.com/FaceDeer/magma_conduits.git"}, {'name': "worldedge", 'repo': "https://github.com/minetest-mods/worldedge.git"}, # ── Gameplay / Items ─────────────────────────────────────── {'name': "3d_armor", 'repo': "https://github.com/stujones11/minetest-3d_armor.git"}, {'name': "anvil", 'repo': "https://github.com/minetest-mods/anvil.git"}, {'name': "awards", 'repo': "https://gitlab.com/rubenwardy/awards.git"}, {'name': "awards_board", 'repo': "https://framagit.org/xisd-minetest/awards_board.git"}, {'name': "basic_materials",'repo': "https://github.com/mt-mods/basic_materials.git"}, {'name': "boost_cart", 'repo': "https://github.com/SmallJoker/boost_cart.git"}, {'name': "compassgps", 'repo': "https://github.com/poikilos/compassgps.git"}, {'name': "digilines", 'repo': "https://github.com/minetest-mods/digilines.git"}, {'name': "fishing", 'repo': "https://github.com/MinetestForFun/fishing.git", 'issues': ["Make sure fishing rods recipe works"], 'version-note': "Minetestforfun's (NOT wulfsdad's) fishing "}, {'name': "homedecor_modpack", 'repo': "https://github.com/mt-mods/homedecor_modpack.git"}, {'name': "homedecor_ua", 'repo': "https://github.com/poikilos/homedecor_ua.git"}, {'name': "item_drop", 'repo': "https://github.com/minetest-mods/item_drop.git", 'settings': {'item_drop.pickup_radius': "1.425"}}, # {'name': 'mymasonhammer', 'repo': "https://github.com/minetest-mods/mymasonhammer.git", # 'what': "A hammer that cuts stairs and ladders in blocks"}, {'name': "mywalls", 'repo': "https://github.com/minetest-mods/mywalls.git", 'what': "Adds more wall types for walls mod from minetest_game."}, {'name': "ropes", 'repo': "https://github.com/minetest-mods/ropes.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': "sounding_line", 'repo': "https://github.com/minetest-mods/sounding_line.git"}, {'name': "stamina", 'repo': "https://codeberg.org/tenplus1/stamina.git", 'comment': "Patches item_eat to affect saturation instead of health.", 'help-dev': "Changes ItemStack before register_on_item_eat callbacks, but they can use 6th param for original ItemStack", 'privs': {'invincible':['no_hunger']}}, {'name': "sponge", 'repo': "https://github.com/BenjieFiftysix/sponge"}, # TODO: ^ Test, make sure is in mapgen. Add underwater/sealife mod & integrate {'name': "throwing", 'repo': "https://github.com/minetest-mods/throwing.git"}, {'name': "throwing_arrows", 'repo': "https://github.com/minetest-mods/throwing_arrows.git", 'settings': {'throwing.enable_arrow': "true"}}, {'name': "travelnet", 'repo': "https://github.com/Sokomine/travelnet.git"}, {'name': "ts_furniture", 'repo': "https://github.com/minetest-mods/ts_furniture.git"}, # {'name': 'trmp_minetest_game','repo': "https://github.com/poikilos/trmp_minetest_game.git"}, # TODO: ^ Make a version for loot # {'name': 'unifieddyes', 'repo': "https://github.com/mt-mods/unifieddyes.git"}, # TODO: ^ add Poikilos/dyed mod # ── Player UX ────────────────────────────────────────────── {'name': "ambience", 'repo': ["https://notabug.org/tenplus1/ambience.git", "https://codeberg.org/tenplus1/ambience.git"]}, {'name': "hunger_ng", 'repo': "https://gitlab.com/4w/hunger_ng.git"}, {'name': "lightning", 'repo': "https://github.com/minetest-mods/lightning.git"}, # {'name': "money", 'repo': ["https://notabug.org/TenPlus1/money", # "https://codeberg.org/tenplus1/money.git"], # 'why-not': "This fork removes everything except barter stations"}, {'name': "player_monoids", 'repo': "https://github.com/minetest-mods/player_monoids.git"}, {'name': "playeranim", 'repo': "https://github.com/minetest-mods/playeranim.git", 'what': "Makes the head, and the right arm when you're mining, face the way you're facing"}, {'name': "playereffects", 'repo': "https://github.com/sys4-fr/playereffects"}, # {'name': 'skinsdb', 'repo': "https://github.com/minetest-mods/skinsdb.git"}, # {'name': "sprint", 'repo': "https://github.com/GunshipPenguin/sprint.git"}, # TODO: ^ Make sure stamina mod fully implements sprint # {'name': 'unified_inventory','repo': [ # "https://github.com/minetest-mods/unified_inventory.git", # "https://github.com/MinetestForFun/unified_inventory" # fork with "nicer interface" # ]}, {'name': "sfinv", 'repo': "https://github.com/rubenwardy/sfinv.git", 'why': "Unified inventory is ugly and has a bloated API."}, # {'name': "bags", 'repo': "https://github.com/cornernote/minetest-bags.git"}, {'name': "prestibags", 'repo': "https://github.com/Poikilos/prestibags.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"}, ] # Preprocess add_mods for repo.or.cz for entry in gamespec['add_mods']: repos = entry.get('repo') if isinstance(repos, str): repos = [repos] for repo in repos: if repo and "repo.or.cz" in repo: entry['distributor'] = "Wuzzy" break # Per-mod overrides / extras why = {} why["https://github.com/MinetestForFun/unified_inventory"] = ''' This fork makes a "nicer interface". The fork hasn't been tested yet. ''' # 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 > produced by this mod. > > My fork of this vines mod has had the rope-related content removed > from it, leaving it as just a vines mod. Note that I haven't tested > it extensively - I have to admit, I've mainly been in this for the > ropes. :) I'll do what I can to maintain it, though, if anyone has > bug reports or requests. > > I've added a node upgrade function to the new ropes mod that will > convert the ropes from both my fork of the vines mod and the original > version of the vines mod by bas080 to the new ropes mod's ropes. So > if you wish to upgrade an existing world it should work. - FaceDeer on [[Mod] Vines and Rope [2.3] [vines]] (https://forums.minetest.org/viewtopic.php?f=11&t=2344&start=50 &sid=bf15c996963e891cd3f2460c2525044a) Note that vines requires: default biome_lib moretrees? doc? intllib? mobs? creatures? ''' gamespec['disable_mobs'] = [ "old_lady", ] server_only_mods = [ 'ircpack', 'chat3', ] # ────────────────────────────────────────────────────────────── # ────────────────────────────────────────────────────────────── # Collected minetest.conf settings from the bash script # ────────────────────────────────────────────────────────────── BASE_ENLIVEN_CONF_SETTINGS = OrderedDict( # General / map map_generation_limit=5000, # HUD / Controls # "stamina_disable_aux1 = true", # require double tap for run (Prevent stamina from taking up aux1 key) # "stamina_hud_x =", # "stamina_hud_y =", # "stamina_double_tap_time =", # 0 to disable # 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, server_dedicated=False, bones_position_message=True, # Sprint (GunshipPenguin sprint settings) sprint_speed=2.25, sprint_jump=1.25, sprint_stamina_drain=.5, ) BASE_ENLIVEN_CONF_SETTINGS['secure.trusted_mods'] = "advanced_npc" def encode_cv(v): """Encode the value to minetest.conf syntax""" if v is None: return "" # results in "name =" which is valid syntax if isinstance(v, bool): return "true" if v else "false" if isinstance(v, (int, float, Decimal)): return str(v) if isinstance(v, str): return f'"{v}"' raise TypeError( "{} type is not implemented in pyenliven Luanti conf encoder" .format(type(v).__name__)) def update_conf(path, new_settings): # 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() tmp_path = path + ".tmp" if os.path.isfile(tmp_path): os.remove(tmp_path) changed = 0 added = 0 same = 0 if os.path.isfile(path): lineN = 0 with open(path, 'r', encoding="utf-8") as src: with open(tmp_path, 'w', encoding="utf-8") as dst: for rawL in src: lineN += 1 line = rawL.strip() if line.startswith("#"): dst.write(rawL) continue if not line: dst.write(rawL) continue if "=" not in line: logger.warning( f"{path}, line {lineN}:" f" No '=' in {rawL.rstrip()}") dst.write(rawL) continue parts = line.split(line, 1) parts[0] = parts[0].strip() if not parts[0]: logger.warning( f"{path}, line {lineN}:" f" No name before '=' in {rawL.rstrip()}") dst.write(rawL) continue if len(parts) > 1: parts[1] = parts[1].strip() else: # f"{name} =" is null value syntax for conf parts[1] = None if parts[0] in new_settings: encoded = encode_cv(new_settings[parts[0]]) if parts[1] == encoded: # no change same += 1 dst.write(rawL) continue changed += 1 if new_settings[parts[0]] is not None: dst.write(f"{parts[0]} = {encoded}\n") else: dst.write(f"{parts[0]} =\n") del new_settings[parts[0]] if new_settings: mode = "a" if os.path.isfile(tmp_path) else "w" with open(tmp_path, mode, encoding="utf-8") as dst: for k, v in new_settings.items(): if v is not None: dst.write(f"{k} = {encode_cv(v)}\n") else: dst.write(f"{k} =\n") # "{k} = " is null value syntax if os.path.isfile(path): os.remove(path) shutil.move(tmp_path, path) echo0(f"Updated {path}: added {added} new line(s), changed {changed}, {same} value(s) already matched")