You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
18 KiB
354 lines
18 KiB
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 <https://forum.minetest.net/viewtopic.php?f=11&t=13659>"},
|
|
{'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")
|
|
|