Set up ability to run commands from the terminal

This commit is contained in:
Andrew Miner
2025-10-06 20:57:46 -06:00
parent a8b6e6b15e
commit 4637137152
18 changed files with 231 additions and 49 deletions
Executable
+1
View File
@@ -0,0 +1 @@
python -m tungston.modpack.mysteriousisland.runner $*
+3
View File
@@ -1,8 +1,11 @@
exceptiongroup==1.3.0 exceptiongroup==1.3.0
iniconfig==2.1.0 iniconfig==2.1.0
jedi==0.19.2
packaging==25.0 packaging==25.0
parso==0.8.4
pluggy==1.6.0 pluggy==1.6.0
Pygments==2.19.2 Pygments==2.19.2
pytest==8.4.2 pytest==8.4.2
toml==0.10.2
tomli==2.2.1 tomli==2.2.1
typing_extensions==4.15.0 typing_extensions==4.15.0
+2 -2
View File
@@ -59,8 +59,8 @@ class Biome(object):
"}" "}"
]]) ]])
def traits(self) -> set[BiomeTrait]: def traits(self) -> list[BiomeTrait]:
return set([ return list([
self.flora, self.flora,
self.geology, self.geology,
self.heat, self.heat,
+1 -1
View File
@@ -17,7 +17,7 @@ class BiomeTrait:
return hash((type(self).__name__, self.name)) return hash((type(self).__name__, self.name))
def __str__(self): def __str__(self):
return self.name return f"{type(self).__name__}: {self.name}"
def __repr__(self) -> str: def __repr__(self) -> str:
return f"{type(self).__name__}<{self.name}>" return f"{type(self).__name__}<{self.name}>"
+1 -1
View File
@@ -52,7 +52,7 @@ def test_repr(green):
assert repr(green) == "BiomeTrait<green>" assert repr(green) == "BiomeTrait<green>"
def test_str(green): def test_str(green):
assert str(green) == "green" assert str(green) == "BiomeTrait: green"
def test_within(traitList, green, yellow, orange): def test_within(traitList, green, yellow, orange):
assert biomeTrait.within(traitList, green, orange) == [green, yellow, orange] assert biomeTrait.within(traitList, green, orange) == [green, yellow, orange]
@@ -0,0 +1,22 @@
from tungston.core.world import World
from tungston.generator.markdown.report import Report
# Class ############################################################################################
class BiomeReport(Report):
def __init__(self, world:World):
super().__init__("biomes.md", world)
def build(self):
for biome in self.world.biomes.all():
self.line(f"# Biome: {biome.city} <{biome.gameId}>")
self.line()
self.indent()
for trait in biome.traits():
self.text("* ").line(trait)
self.outdent()
self.line()
@@ -0,0 +1,61 @@
from pytest import fixture
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomecatalog import BiomeCatalog
from tungston.core.world import World
from tungston.generator.markdown.biomereport import BiomeReport
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
import textwrap
# Fixtures #########################################################################################
@fixture(name="biomes")
def createCatalog():
yield BiomeCatalog([
Biome("dallas", "minecraft:savanna",
F.FIELD, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("kansascity", "minecraft:plains",
F.FIELD, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
])
@fixture(name="world")
def createWorld(biomes):
yield World(biomes, None, None, None)
@fixture(name="report")
def createReport(world):
report = BiomeReport(world)
report.build()
yield report
# Tests ############################################################################################
def test_report(report):
assert str(report) == textwrap.dedent("""
# Biome: dallas <minecraft:savanna>
* Flora: field
* Geology: sedimentary
* Heat: subtropical
* Humidity: dry
* Soil: sandy
* Water: inland
# Biome: kansascity <minecraft:plains>
* Flora: field
* Geology: sedimentary
* Heat: temperate
* Humidity: damp
* Soil: loamy
* Water: inland
""").strip()
+4 -1
View File
@@ -6,6 +6,9 @@ from tungston.generator.markdown.report import Report
class MineralReport(Report): class MineralReport(Report):
def __init__(self, world:World):
super().__init__("minerals.md", world)
def build(self): def build(self):
for mineral in self.world.minerals.all(): for mineral in self.world.minerals.all():
self.line(f"# Mineral: {mineral.name}") self.line(f"# Mineral: {mineral.name}")
@@ -13,7 +16,7 @@ class MineralReport(Report):
self.indent() self.indent()
for replacement in mineral.replacements: for replacement in mineral.replacements:
self.line(str(replacement)) self.text("* ").line(str(replacement))
self.outdent() self.outdent()
self.line() self.line()
@@ -45,11 +45,11 @@ def test_report(report):
assert str(report) == textwrap.dedent(""" assert str(report) == textwrap.dedent("""
# Mineral: copper # Mineral: copper
#minecraft:stone_replaceables => minecraft:copper_ore * #minecraft:stone_replaceables => minecraft:copper_ore
#minecraft:deepslate_replaceables => minecraft:deepslate_copper_ore * #minecraft:deepslate_replaceables => minecraft:deepslate_copper_ore
# Mineral: iron # Mineral: iron
#minecraft:stone_replaceables => minecraft:iron_ore * #minecraft:stone_replaceables => minecraft:iron_ore
#minecraft:deepslate_replaceables => minecraft:deepslate_iron_ore * #minecraft:deepslate_replaceables => minecraft:deepslate_iron_ore
""").strip() """).strip()
+2 -1
View File
@@ -10,7 +10,8 @@ INDENT = " "
class Report: class Report:
def __init__(self, world:World): def __init__(self, name:str, world:World):
self.name = name
self.world = world self.world = world
self.reset() self.reset()
+1 -5
View File
@@ -4,14 +4,10 @@ from tungston.generator.markdown.report import Report
# Fixtures ######################################################################################### # Fixtures #########################################################################################
@fixture(name="emptyReport")
def createEmptyReport():
return Report()
@fixture(name="report") @fixture(name="report")
def createReport(): def createReport():
return ( return (
Report(None) Report("test", None)
.text("alpha") .text("alpha")
.line("bravo") .line("bravo")
.indent() .indent()
@@ -0,0 +1,24 @@
from tungston.generator.markdown.report import Report
import shutil
import os
# Class ############################################################################################
class ReportWriter:
def __init__(self, reports:list[Report]):
self._reports = reports
def write(self, reportDirPath:str):
if os.path.exists(reportDirPath):
shutil.rmtree(reportDirPath)
os.makedirs(reportDirPath, exist_ok=True)
for report in self._reports:
report.build()
path = os.path.join(reportDirPath, report.name)
with open(path, "w") as file:
file.write(str(report))
+28
View File
@@ -0,0 +1,28 @@
from tungston.core.world import World
import inspect
import sys
# Class ############################################################################################
class Runner:
def __init__(self, world:World):
self.world = world
def abort(self, message:str, status:int=-1):
print(message)
sys.exit(status)
def run(self, argv:list[str]):
if len(sys.argv) < 2:
abort("Please provide a command name")
commandName = "_command_" + argv[1]
for name, doCommand in inspect.getmembers(self):
if name == commandName:
doCommand(*argv[2:])
sys.exit(0)
abort("No command named: " + argv[1])
+7
View File
@@ -0,0 +1,7 @@
from tungston.interface.runner import Runner
# Tests ############################################################################################
def test_syntax():
pass
@@ -1,7 +1,7 @@
from tungston.core.ecology.biomefilter import BiomeFilter as BF from tungston.core.ecology.biomefilter import BiomeFilter as BF
from tungston.core.geology.depositcatalog import DepositCatalog
from tungston.core.geology.deposit.inclusion import Inclusion as I
from tungston.core.geology.deposit.metaldeposit import MetalDeposit from tungston.core.geology.deposit.metaldeposit import MetalDeposit
from tungston.core.geology.depositcatalog import DepositCatalog
from tungston.core.geology.inclusion import Inclusion as I
from tungston.modpack.mysteriousisland.mineralcatalog import CATALOG as M from tungston.modpack.mysteriousisland.mineralcatalog import CATALOG as M
import tungston.core.altitude as AL import tungston.core.altitude as AL
@@ -16,13 +16,13 @@ import tungston.core.scarcity as SC
# Catalog ########################################################################################## # Catalog ##########################################################################################
CATALOG = C = DepositCatalog(minerals) CATALOG = C = DepositCatalog()
C.add(MetalDeposit( C.add(MetalDeposit(
name = "bif_iron", name = "bif_iron",
biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]),
scarcity = SC.COMMON, scarcity = SC.COMMON,
minerals = [I(M.get("iron"), 50), I(M.get("quartz"), 45), I(M.get("uranium"), 5)], biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]),
inclusions = [I(M.get("iron"), 50), I(M.get("quartz"), 45), I(M.get("uranium"), 5)],
bulk = BU.LARGE, bulk = BU.LARGE,
proportion = 0.2, proportion = 0.2,
)) ))
@@ -16,27 +16,27 @@ def makeMineral(name:str, blockId:str, deepslateBlockId:None|str=None) -> Minera
deepslateBlockId = deepslateBlockId if deepslateBlockId else blockId deepslateBlockId = deepslateBlockId if deepslateBlockId else blockId
return Mineral(name, [ return Mineral(name, [
R.inStone(blockId), Replacement.inStone(blockId),
R.inDeepslate(blockId) Replacement.inDeepslate(blockId)
]) ])
def makeOreMineral(name:str) -> Mineral: def makeOreMineral(name:str) -> Mineral:
return Mineral(name, [ return Mineral(name, [
R.inStone(f"{name}_ore"), Replacement.inStone(f"{name}_ore"),
R.inDeepslate(f"deepslate_{name}_ore") Replacement.inDeepslate(f"deepslate_{name}_ore")
]) ])
def makeImmersiveEngineeringOreMineral(name:str) -> Mineral: def makeImmersiveEngineeringOreMineral(name:str) -> Mineral:
return Mineral(name, [ return Mineral(name, [
R.inStone(f"{IE}:ore_{name}"), Replacement.inStone(f"{IE}:ore_{name}"),
R.inDeepslate("{IE}:deepslate_ore_{name}") Replacement.inDeepslate("{IE}:deepslate_ore_{name}")
]), ])
def makeRailcraftOreMineral(name:str) -> Mineral: def makeRailcraftOreMineral(name:str) -> Mineral:
return Mineral(name, [ return Mineral(name, [
R.inStone(f"{RC}:{name}_ore"), Replacement.inStone(f"{RC}:{name}_ore"),
R.inDeepslate("{RC}:deepslate_{name}_ore") Replacement.inDeepslate("{RC}:deepslate_{name}_ore")
]), ])
# Catalog ########################################################################################## # Catalog ##########################################################################################
@@ -56,7 +56,7 @@ C.add(makeOreMineral("redstone"))
# Crystals # Crystals
C.add(makeMineral("amethyst", "amethyst_block")) C.add(makeMineral("amethyst", "amethyst_block"))
C.add(makeMineral("glowstone", "glowstone")) C.add(makeMineral("glowstone", "glowstone"))
C.add(makeMineral("quartz", f"{OQ}:quartz_ore") f"{OQ}:deepslate_quartz_ore") C.add(makeMineral("quartz", f"{OQ}:quartz_ore", f"{OQ}:deepslate_quartz_ore"))
C.add(makeMineral("salt", "butcher:saltblock")) C.add(makeMineral("salt", "butcher:saltblock"))
# Earth, gravel, etc. # Earth, gravel, etc.
+17 -16
View File
@@ -1,9 +1,9 @@
from tungston.core.ecology.biomefilter import BiomeFilter as BF from tungston.core.ecology.biomefilter import BiomeFilter as BF
from tungston.core.habitat import Habitat
from tungston.core.fauna.mob import Mob from tungston.core.fauna.mob import Mob
from tungston.core.fauna.mobplacement import MobPlacement
from tungston.core.fauna.mobcatalog import MobCatalog from tungston.core.fauna.mobcatalog import MobCatalog
from tungston.core.fauna.mobplacement import MobPlacement
import tungston.core.active as AC
import tungston.core.altitude as AL import tungston.core.altitude as AL
import tungston.core.ecology.flora as FL import tungston.core.ecology.flora as FL
import tungston.core.ecology.geology as GE import tungston.core.ecology.geology as GE
@@ -11,6 +11,7 @@ import tungston.core.ecology.heat as HE
import tungston.core.ecology.humidity as HU import tungston.core.ecology.humidity as HU
import tungston.core.ecology.soil as SO import tungston.core.ecology.soil as SO
import tungston.core.ecology.water as WA import tungston.core.ecology.water as WA
import tungston.core.fauna.active as AC
import tungston.core.fauna.group as GR import tungston.core.fauna.group as GR
import tungston.core.fauna.location as LO import tungston.core.fauna.location as LO
import tungston.core.scarcity as SC import tungston.core.scarcity as SC
@@ -22,17 +23,17 @@ import tungston.core.season as SE
CATALOG = MobCatalog([ CATALOG = MobCatalog([
MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL), MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL),
Habitat( Habitat(
altitude = AL.LOWLANDS, altitudes = AL.LOWLANDS,
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]), biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]),
seasons = SE.SUMMER, seasons = SE.SUMMER,
group = GR.merge(GR.SOLO, GR.PAIR), group = GR.merge(GR.SOLO, GR.PAIR),
scarcity = SC.COMMON scarcity = SC.COMMON
).derive( ).derive(
altitude = AL.UPLANDS, scarcity = SC.SPARSE, altitudes = AL.UPLANDS, scarcity = SC.SPARSE,
).derive( ).derive(
altitude = AL.LOWLANDS, SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON, altitudes = AL.LOWLANDS, seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON,
).derive( ).derive(
altitude = AL.UPLANDS, scarcity = SC.UNUSUAL, altitudes = AL.UPLANDS, scarcity = SC.UNUSUAL,
) )
), ),
MobPlacement(Mob("black_bear", "bearminimum:black_bear"), MobPlacement(Mob("black_bear", "bearminimum:black_bear"),
@@ -47,7 +48,7 @@ CATALOG = MobCatalog([
).derive( ).derive(
seasons = SE.WINTER, scarcity = SC.UNUSUAL seasons = SE.WINTER, scarcity = SC.UNUSUAL
).derive( ).derive(
biomeFilter = BF([HE.BOREAL, (HE.CANOPY, HE.FOREST)]), biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]),
seasons = SE.AUTUMN, seasons = SE.AUTUMN,
scarcity = SC.SPARSE scarcity = SC.SPARSE
).derive( ).derive(
@@ -65,7 +66,7 @@ CATALOG = MobCatalog([
) )
), ),
MobPlacement(Mob("bogged", "minecraft:bogged")), MobPlacement(Mob("bogged", "minecraft:bogged")),
MobPlacement(Mob("brown_bear", "bearminimum:brown_bear") MobPlacement(Mob("brown_bear", "bearminimum:brown_bear"),
Habitat( Habitat(
altitudes = AL.span(AL.LOWLANDS, AL.ALPINE), altitudes = AL.span(AL.LOWLANDS, AL.ALPINE),
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]),
@@ -93,7 +94,7 @@ CATALOG = MobCatalog([
MobPlacement(Mob("cat", "minecraft:cat")), MobPlacement(Mob("cat", "minecraft:cat")),
MobPlacement(Mob("cave_spider", "minecraft:cave_spider"), MobPlacement(Mob("cave_spider", "minecraft:cave_spider"),
Habitat( Habitat(
altitudes = AL.SPAN(AL.OVERBURDEN, AL.HILLS), altitudes = AL.span(AL.OVERBURDEN, AL.HILLS),
location = LO.CAVE, location = LO.CAVE,
group = GR.SOLO, group = GR.SOLO,
scarcity = SC.UNCOMMON scarcity = SC.UNCOMMON
@@ -102,27 +103,27 @@ CATALOG = MobCatalog([
MobPlacement(Mob("chameleon", "cold_sweat:chameleon"), MobPlacement(Mob("chameleon", "cold_sweat:chameleon"),
Habitat( Habitat(
altitudes = AL.span(AL.DUNES, AL.UPLANDS), altitudes = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilters = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]), biomeFilter = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]),
seasons = SE.WET, seasons = SE.WET,
groups = GR.merge(GR.SOLO, GR.FAMILY), group = GR.merge(GR.SOLO, GR.FAMILY),
scarcity = SC.COMMON, scarcity = SC.COMMON,
).derive( ).derive(
seasons = SE.DRY, scarcity = SC.UNCOMMON, seasons = SE.DRY, scarcity = SC.UNCOMMON,
).derive( ).derive(
biomeFilters = BF([HE.TROPICAL, HU.WET, FL.CLEARING]), biomeFilter = BF([HE.TROPICAL, HU.WET, FL.CLEARING]),
seasons = SE.WET, seasons = SE.WET,
scarcity = SC.UNCOMMON scarcity = SC.UNCOMMON
).derive( ).derive(
seasons = SE.DRY, scarcity = SC.SPARSE, seasons = SE.DRY, scarcity = SC.SPARSE,
) )
), ),
MobPlacement(Mob("chicken", "minecraft:chicken") MobPlacement(Mob("chicken", "minecraft:chicken"),
Habitat( Habitat(
altitudes = AL.span(AL.LOWLANDS, AL.UPLANDS), altitudes = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]), biomeFilter = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]),
seasons = SE.SUMMER, seasons = SE.SUMMER,
groups = GR.TROUP, group = GR.TROUP,
scarcity.COMMON, scarcity = SC.COMMON,
).derive( ).derive(
seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON
) )
@@ -0,0 +1,35 @@
from tungston.interface.runner import Runner as BaseRunner
from tungston.core.world import World
from tungston.modpack.mysteriousisland.biomecatalog import CATALOG as biomes
from tungston.modpack.mysteriousisland.depositcatalog import CATALOG as deposits
from tungston.modpack.mysteriousisland.mineralcatalog import CATALOG as minerals
from tungston.modpack.mysteriousisland.mobcatalog import CATALOG as mobs
from tungston.generator.markdown.reportwriter import ReportWriter
from tungston.generator.markdown.biomereport import BiomeReport
from tungston.generator.markdown.mineralreport import MineralReport
import sys
# Constants ########################################################################################
REPORT_PATH = "./output/markdown/mysteriousisland"
# Class ############################################################################################
class Runner(BaseRunner):
def _command_writeReports(self):
writer = ReportWriter([
BiomeReport(self.world),
MineralReport(self.world)
])
writer.write(REPORT_PATH)
# Script ###########################################################################################
if __name__ == "__main__":
Runner(World(biomes, deposits, minerals, mobs)).run(sys.argv)