From 5a63d52088545b2ead63d3f9d8e58e21d151abd0 Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Wed, 8 Oct 2025 12:35:18 -0600 Subject: [PATCH] Checkpoint continued progress --- .vimrc | 1 + code.zip | Bin 0 -> 92209 bytes mcpacker/emit/markdown/biomereport.py | 10 +- mcpacker/emit/markdown/biomereport_test.py | 74 +-- mcpacker/emit/markdown/mineralreport.py | 8 +- mcpacker/emit/markdown/mineralreport_test.py | 48 +- mcpacker/emit/markdown/mobreport.py | 10 +- mcpacker/emit/markdown/report.py | 9 +- mcpacker/emit/markdown/reportwriter.py | 1 + mcpacker/emit/markdown/reportwriter_test.py | 7 + mcpacker/emit/modpack/__init__.py | 0 mcpacker/emit/modpack/__init___.py | 1 + mcpacker/emit/resourcepack/__init__.py | 0 mcpacker/model/core/ecology/biomecatalog.py | 27 +- mcpacker/model/core/fauna/mobcatalog.py | 8 +- .../model/core/geology/mineralcatalog_test.py | 6 +- mcpacker/model/core/material/__init__.py | 0 mcpacker/model/core/material/block.py | 27 + mcpacker/model/core/material/block_test.py | 6 + mcpacker/model/core/material/blockcatalog.py | 30 ++ .../model/core/material/blockcatalog_test.py | 7 + mcpacker/model/core/material/item.py | 12 + mcpacker/model/core/material/item_test.py | 7 + mcpacker/model/core/material/itemcatalog.py | 27 + .../model/core/material/itemcatalog_test.py | 7 + mcpacker/model/core/material/loot.py | 24 + mcpacker/model/core/material/loot_test.py | 7 + mcpacker/model/core/material/loottable.py | 9 + .../model/core/material/loottable_test.py | 7 + mcpacker/model/core/material/soundtype.py | 35 ++ .../model/core/material/soundtype_test.py | 7 + mcpacker/model/core/season.py | 2 +- mcpacker/model/core/season_test.py | 4 +- mcpacker/model/core/world.py | 26 +- mcpacker/model/datapack/__init__.py | 13 +- mcpacker/model/datapack/mod.py | 2 + mcpacker/model/mod.py | 6 + mcpacker/model/mod_test.py | 7 + mcpacker/model/modpack.py | 31 ++ mcpacker/model/modpack_test.py | 7 + mcpacker/model/resourcepack/__init__.py | 40 ++ mcpacker/model/resourcepack/kind.py | 23 + mcpacker/model/resourcepack/kind_test.py | 7 + mcpacker/model/resourcepack/mod.py | 8 + mcpacker/model/resourcepack/mod_test.py | 8 + mcpacker/model/resourcepack/texture.py | 10 + mcpacker/model/resourcepack/texture_test.py | 7 + .../{textures/block => images}/peat_block.png | Bin .../{textures/item => images}/peat_chunk.png | Bin .../deposit_bed_loam_marker.nbt | Bin .../deposit_bif_iron_marker.nbt | Bin .../deposit_epithermal_silver_marker.nbt | Bin .../deposit_evaporite_nitrate_marker.nbt | Bin .../deposit_evaporite_salt_marker.nbt | Bin .../deposit_fulmarole_sulfur_marker.nbt | Bin .../deposit_geode_amethyst_marker.nbt | Bin .../deposit_greisen_tin_marker.nbt | Bin .../deposit_hydrothermal_emerald_marker.nbt | Bin .../deposit_laterite_aluminum_marker.nbt | Bin .../deposit_lavatube_diamond_marker.nbt | Bin .../deposit_mvt_lead_marker.nbt | Bin .../deposit_porphyry_copper_marker.nbt | Bin .../deposit_seam_bituminouscoal_marker.nbt | Bin .../deposit_seam_peatcoal_marker.nbt | Bin .../deposit_sedimentary_iron_marker.nbt | Bin .../deposit_skarnlapis_marker.nbt | Bin .../pack/mysteriousisland/biomecatalog.py | 459 ++++++++++------ .../pack/mysteriousisland/blockcatalog.py | 23 + .../mysteriousisland/blockcatalog_test.py | 7 + mcpacker/pack/mysteriousisland/datapack.py | 8 + .../pack/mysteriousisland/datapack_test.py | 7 + .../pack/mysteriousisland/depositcatalog.py | 31 +- mcpacker/pack/mysteriousisland/itemcatalog.py | 8 + .../pack/mysteriousisland/itemcatalog_test.py | 7 + .../pack/mysteriousisland/mineralcatalog.py | 126 ++--- mcpacker/pack/mysteriousisland/mobcatalog.py | 509 ++++++++++++------ mcpacker/pack/mysteriousisland/modpack.py | 27 + .../pack/mysteriousisland/modpack_test.py | 7 + .../pack/mysteriousisland/resourcepack.py | 8 + .../mysteriousisland/resourcepack_test.py | 7 + mcpacker/pack/mysteriousisland/runner.py | 29 +- mcpacker/pack/mysteriousisland/runner_test.py | 7 + mcpacker/pack/mysteriousisland/world.py | 10 - mcpacker/ui/runner.py | 26 +- mcpacker/ui/runner_test.py | 2 +- 85 files changed, 1390 insertions(+), 541 deletions(-) create mode 100644 .vimrc create mode 100644 code.zip create mode 100644 mcpacker/emit/markdown/reportwriter_test.py create mode 100644 mcpacker/emit/modpack/__init__.py create mode 100644 mcpacker/emit/modpack/__init___.py create mode 100644 mcpacker/emit/resourcepack/__init__.py create mode 100644 mcpacker/model/core/material/__init__.py create mode 100644 mcpacker/model/core/material/block.py create mode 100644 mcpacker/model/core/material/block_test.py create mode 100644 mcpacker/model/core/material/blockcatalog.py create mode 100644 mcpacker/model/core/material/blockcatalog_test.py create mode 100644 mcpacker/model/core/material/item.py create mode 100644 mcpacker/model/core/material/item_test.py create mode 100644 mcpacker/model/core/material/itemcatalog.py create mode 100644 mcpacker/model/core/material/itemcatalog_test.py create mode 100644 mcpacker/model/core/material/loot.py create mode 100644 mcpacker/model/core/material/loot_test.py create mode 100644 mcpacker/model/core/material/loottable.py create mode 100644 mcpacker/model/core/material/loottable_test.py create mode 100644 mcpacker/model/core/material/soundtype.py create mode 100644 mcpacker/model/core/material/soundtype_test.py create mode 100644 mcpacker/model/mod.py create mode 100644 mcpacker/model/mod_test.py create mode 100644 mcpacker/model/modpack.py create mode 100644 mcpacker/model/modpack_test.py create mode 100644 mcpacker/model/resourcepack/__init__.py create mode 100644 mcpacker/model/resourcepack/kind.py create mode 100644 mcpacker/model/resourcepack/kind_test.py create mode 100644 mcpacker/model/resourcepack/mod.py create mode 100644 mcpacker/model/resourcepack/mod_test.py create mode 100644 mcpacker/model/resourcepack/texture.py create mode 100644 mcpacker/model/resourcepack/texture_test.py rename mcpacker/pack/mysteriousisland/assets/{textures/block => images}/peat_block.png (100%) rename mcpacker/pack/mysteriousisland/assets/{textures/item => images}/peat_chunk.png (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_bed_loam_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_bif_iron_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_epithermal_silver_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_evaporite_nitrate_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_evaporite_salt_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_fulmarole_sulfur_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_geode_amethyst_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_greisen_tin_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_hydrothermal_emerald_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_laterite_aluminum_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_lavatube_diamond_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_mvt_lead_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_porphyry_copper_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_seam_bituminouscoal_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_seam_peatcoal_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_sedimentary_iron_marker.nbt (100%) rename mcpacker/pack/mysteriousisland/assets/{structure => nbts}/deposit_skarnlapis_marker.nbt (100%) create mode 100644 mcpacker/pack/mysteriousisland/blockcatalog.py create mode 100644 mcpacker/pack/mysteriousisland/blockcatalog_test.py create mode 100644 mcpacker/pack/mysteriousisland/datapack.py create mode 100644 mcpacker/pack/mysteriousisland/datapack_test.py create mode 100644 mcpacker/pack/mysteriousisland/itemcatalog.py create mode 100644 mcpacker/pack/mysteriousisland/itemcatalog_test.py create mode 100644 mcpacker/pack/mysteriousisland/modpack.py create mode 100644 mcpacker/pack/mysteriousisland/modpack_test.py create mode 100644 mcpacker/pack/mysteriousisland/resourcepack.py create mode 100644 mcpacker/pack/mysteriousisland/resourcepack_test.py create mode 100644 mcpacker/pack/mysteriousisland/runner_test.py delete mode 100644 mcpacker/pack/mysteriousisland/world.py diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..2688578 --- /dev/null +++ b/.vimrc @@ -0,0 +1 @@ +let g:jedi#environment_path = expand('.venv') diff --git a/code.zip b/code.zip new file mode 100644 index 0000000000000000000000000000000000000000..3f69b098aff932281b94574f63327d7bf6b44b81 GIT binary patch literal 92209 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

JEZ#3!}m`I@%L&gPkqDq`TQ-` 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 literal 0 HcmV?d00001 diff --git a/mcpacker/emit/markdown/biomereport.py b/mcpacker/emit/markdown/biomereport.py index bcdab5e..8715f7b 100644 --- a/mcpacker/emit/markdown/biomereport.py +++ b/mcpacker/emit/markdown/biomereport.py @@ -1,17 +1,17 @@ from mcpacker.emit.markdown.report import Report -from mcpacker.model.core.world import World +from mcpacker.model.modpack import ModPack # Class ############################################################################################ class BiomeReport(Report): - def __init__(self, world:World): - super().__init__("biomes.md", world) + def __init__(self, pack:ModPack): + super().__init__("biomes.md", pack) def build(self): - for biome in self.world.biomes.all(): - self.line(f"# Biome: {biome.city} <{biome.gameId}>") + for biome in self.pack.world.biomes.all(): + self.line(f"# Biome: {biome.gameId} ({biome.city})") self.line() self.indent() diff --git a/mcpacker/emit/markdown/biomereport_test.py b/mcpacker/emit/markdown/biomereport_test.py index 0a0fb81..80a7bb1 100644 --- a/mcpacker/emit/markdown/biomereport_test.py +++ b/mcpacker/emit/markdown/biomereport_test.py @@ -1,39 +1,45 @@ from mcpacker.emit.markdown.biomereport import BiomeReport -from mcpacker.model.core.ecology.biome import Biome -from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog -from mcpacker.model.core.world import World -from pytest import fixture +from mcpacker.model.core.ecology.biome import Biome +from mcpacker.model.modpack import ModPack +from pytest import fixture -import mcpacker.model.core.ecology.flora as F -import mcpacker.model.core.ecology.geology as G -import mcpacker.model.core.ecology.heat as E +import mcpacker.model.core.ecology.flora as F +import mcpacker.model.core.ecology.geology as G +import mcpacker.model.core.ecology.heat as E import mcpacker.model.core.ecology.humidity as U -import mcpacker.model.core.ecology.soil as S -import mcpacker.model.core.ecology.water as W +import mcpacker.model.core.ecology.soil as S +import mcpacker.model.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="addBiomes") +def defineAddBiomes(): + def addBiomes(pack:ModPack): + pack.world.biomes.add( + Biome("dallas", "minecraft:savanna", + F.FIELD, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND + ) + ) + pack.world.biomes.add( + 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) + return addBiomes + +@fixture(name="pack") +def createPack(addBiomes): + pack = ModPack("test") + pack.augment(addBiomes) + yield pack @fixture(name="report") -def createReport(world): - report = BiomeReport(world) +def createReport(pack): + report = BiomeReport(pack) report.build() yield report @@ -41,16 +47,7 @@ def createReport(world): def test_report(report): assert str(report) == textwrap.dedent(""" - # Biome: dallas - - * Flora: field - * Geology: sedimentary - * Heat: subtropical - * Humidity: dry - * Soil: sandy - * Water: inland - - # Biome: kansascity + # Biome: minecraft:plains (kansascity) * Flora: field * Geology: sedimentary @@ -58,4 +55,13 @@ def test_report(report): * Humidity: damp * Soil: loamy * Water: inland + + # Biome: minecraft:savanna (dallas) + + * Flora: field + * Geology: sedimentary + * Heat: subtropical + * Humidity: dry + * Soil: sandy + * Water: inland """).strip() diff --git a/mcpacker/emit/markdown/mineralreport.py b/mcpacker/emit/markdown/mineralreport.py index 2c262ef..0dd0ca5 100644 --- a/mcpacker/emit/markdown/mineralreport.py +++ b/mcpacker/emit/markdown/mineralreport.py @@ -1,16 +1,16 @@ from mcpacker.emit.markdown.report import Report -from mcpacker.model.core.world import World +from mcpacker.model.modpack import ModPack # Class ############################################################################################ class MineralReport(Report): - def __init__(self, world:World): - super().__init__("minerals.md", world) + def __init__(self, pack:ModPack): + super().__init__("minerals.md", pack) def build(self): - for mineral in self.world.minerals.all(): + for mineral in self.pack.world.minerals.all(): self.line(f"# Mineral: {mineral.name}") self.line() diff --git a/mcpacker/emit/markdown/mineralreport_test.py b/mcpacker/emit/markdown/mineralreport_test.py index aa0d348..ad1bdfa 100644 --- a/mcpacker/emit/markdown/mineralreport_test.py +++ b/mcpacker/emit/markdown/mineralreport_test.py @@ -1,40 +1,38 @@ -from mcpacker.emit.markdown.mineralreport import MineralReport -from mcpacker.model.core.geology.mineral import Mineral -from mcpacker.model.core.geology.mineralcatalog import MineralCatalog +from mcpacker.emit.markdown.mineralreport import MineralReport +from mcpacker.model.core.geology.mineral import Mineral from mcpacker.model.core.geology.replacement import Replacement -from mcpacker.model.core.world import World -from pytest import fixture +from mcpacker.model.modpack import ModPack +from pytest import fixture import textwrap # Fixtures ######################################################################################### -@fixture(name="copper") -def createCopper(): - yield Mineral("copper", [ - Replacement("#minecraft:stone_replaceables", "minecraft:copper_ore"), - Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_copper_ore") - ]) +@fixture(name="addMinerals") +def defineAddMinerals(): + def addMinerals(pack:ModPack): + pack.world.minerals.add(Mineral("copper", [ + Replacement("#minecraft:stone_replaceables", "minecraft:copper_ore"), + Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_copper_ore") + ])) -@fixture(name="iron") -def createIron(): - yield Mineral("iron", [ - Replacement("#minecraft:stone_replaceables", "minecraft:iron_ore"), - Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_iron_ore") - ]) + pack.world.minerals.add(Mineral("iron", [ + Replacement("#minecraft:stone_replaceables", "minecraft:iron_ore"), + Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_iron_ore") + ])) -@fixture(name="minerals") -def createMineralCatalog(copper, iron): - yield MineralCatalog([copper, iron]) + return addMinerals -@fixture(name="world") -def createWorld(minerals): - yield World(None, None, minerals, None) +@fixture(name="pack") +def createPack(addMinerals): + pack = ModPack("test") + pack.augment(addMinerals) + yield pack @fixture(name="report") -def createReport(world): - report = MineralReport(world) +def createReport(pack): + report = MineralReport(pack) report.build() yield report diff --git a/mcpacker/emit/markdown/mobreport.py b/mcpacker/emit/markdown/mobreport.py index 1beb34a..c56fecf 100644 --- a/mcpacker/emit/markdown/mobreport.py +++ b/mcpacker/emit/markdown/mobreport.py @@ -1,17 +1,17 @@ -from mcpacker.emit.markdown.report import Report +from mcpacker.emit.markdown.report import Report from mcpacker.model.core.ecology.biometrait import BiomeTrait -from mcpacker.model.core.world import World +from mcpacker.model.modpack import ModPack # Class ############################################################################################ class MobReport(Report): - def __init__(self, world:World): - super().__init__("mobs.md", world) + def __init__(self, pack:ModPack): + super().__init__("mobs.md", pack) def build(self): - for placement in self.world.mobs.all(): + for placement in self.pack.world.mobs.all(): self.line(f"# Mob: {placement.mob.name} <{placement.mob.gameId}>") self.line() diff --git a/mcpacker/emit/markdown/report.py b/mcpacker/emit/markdown/report.py index db3f3f4..ce0a4b8 100644 --- a/mcpacker/emit/markdown/report.py +++ b/mcpacker/emit/markdown/report.py @@ -1,18 +1,19 @@ -from collections.abc import Iterator -from mcpacker.model.core.world import World +from collections.abc import Iterator +from mcpacker.model.modpack import ModPack # Constants ######################################################################################## INDENT = " " + # Class ############################################################################################ class Report: - def __init__(self, name:str, world:World): + def __init__(self, name:str, pack:ModPack): self.name = name - self.world = world + self.pack = pack self.reset() def __str__(self) -> str: diff --git a/mcpacker/emit/markdown/reportwriter.py b/mcpacker/emit/markdown/reportwriter.py index 6a17735..205ce39 100644 --- a/mcpacker/emit/markdown/reportwriter.py +++ b/mcpacker/emit/markdown/reportwriter.py @@ -3,6 +3,7 @@ from mcpacker.emit.markdown.report import Report import os import shutil + # Class ############################################################################################ class ReportWriter: diff --git a/mcpacker/emit/markdown/reportwriter_test.py b/mcpacker/emit/markdown/reportwriter_test.py new file mode 100644 index 0000000..8ce6e94 --- /dev/null +++ b/mcpacker/emit/markdown/reportwriter_test.py @@ -0,0 +1,7 @@ +import mcpacker.emit.markdown.reportwriter + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/emit/modpack/__init__.py b/mcpacker/emit/modpack/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mcpacker/emit/modpack/__init___.py b/mcpacker/emit/modpack/__init___.py new file mode 100644 index 0000000..31cf705 --- /dev/null +++ b/mcpacker/emit/modpack/__init___.py @@ -0,0 +1 @@ +from mcpacker.model.core.modpack diff --git a/mcpacker/emit/resourcepack/__init__.py b/mcpacker/emit/resourcepack/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mcpacker/model/core/ecology/biomecatalog.py b/mcpacker/model/core/ecology/biomecatalog.py index 2f981fc..d5e9c97 100644 --- a/mcpacker/model/core/ecology/biomecatalog.py +++ b/mcpacker/model/core/ecology/biomecatalog.py @@ -1,3 +1,4 @@ +from collections.abc import Iterable from mcpacker.model.core.ecology.biome import Biome from mcpacker.model.core.ecology.biomefilter import BiomeFilter @@ -9,17 +10,23 @@ class BiomeCatalog: A comprehensive list of all available biomes in the modpack. """ - def __init__(self, biomes): - self.biomes = sorted(biomes, key=lambda b: b.city) + def __init__(self, biomes:Iterable[Biome]|None=None): + self._biomes = {} - def all(self) -> list[Biome]: - return list(self.biomes) + for biome in (biomes or []): + self.add(biome) - def matching(self, biomeFilter:BiomeFilter) -> list[Biome]: - result = [] + def add(self, biome:Biome) -> "BiomeCatalog": + if biome.gameId in self._biomes: + raise Exception(f"Catalog already contains {biome.gameId}") - for biome in self.biomes: + self._biomes[biome.gameId] = biome + + def all(self) -> Iterable[Biome]: + for gameId in sorted([b.gameId for b in self._biomes.values()]): + yield self._biomes[gameId] + + def matching(self, biomeFilter:BiomeFilter) -> Iterable[Biome]: + for biome in self.all(): if biomeFilter.accepts(biome): - result.append(biome) - - return result + yield biome diff --git a/mcpacker/model/core/fauna/mobcatalog.py b/mcpacker/model/core/fauna/mobcatalog.py index b1928f0..c49488d 100644 --- a/mcpacker/model/core/fauna/mobcatalog.py +++ b/mcpacker/model/core/fauna/mobcatalog.py @@ -1,4 +1,4 @@ -from collections.abc import Iterator +from collections.abc import Iterable from mcpacker.model.core.fauna.mobplacement import MobPlacement @@ -6,10 +6,10 @@ from mcpacker.model.core.fauna.mobplacement import MobPlacement class MobCatalog: - def __init__(self, mobs:tuple[MobPlacement]): + def __init__(self, mobs:Iterable[MobPlacement]|None=None): self._mobs = {} - for mob in mobs: + for mob in (mobs or []): self.add(mob) def add(self, placement:MobPlacement) -> "MobCatalog": @@ -18,7 +18,7 @@ class MobCatalog: self._mobs[placement.mob.name] = placement - def all(self) -> Iterator[MobPlacement]: + def all(self) -> Iterable[MobPlacement]: for placement in self._mobs.values(): yield placement diff --git a/mcpacker/model/core/geology/mineralcatalog_test.py b/mcpacker/model/core/geology/mineralcatalog_test.py index 0d9f537..c554b43 100644 --- a/mcpacker/model/core/geology/mineralcatalog_test.py +++ b/mcpacker/model/core/geology/mineralcatalog_test.py @@ -1,7 +1,7 @@ -from mcpacker.model.core.geology.mineral import Mineral +from mcpacker.model.core.geology.mineral import Mineral from mcpacker.model.core.geology.mineralcatalog import MineralCatalog -from mcpacker.model.core.geology.replacement import Replacement -from pytest import fixture +from mcpacker.model.core.geology.replacement import Replacement +from pytest import fixture # Fixtures ######################################################################################### diff --git a/mcpacker/model/core/material/__init__.py b/mcpacker/model/core/material/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mcpacker/model/core/material/block.py b/mcpacker/model/core/material/block.py new file mode 100644 index 0000000..8af8023 --- /dev/null +++ b/mcpacker/model/core/material/block.py @@ -0,0 +1,27 @@ +from mcpacker.model.core.material.loottable import LootTable +from mcpacker.model.core.material.soundtype import SoundType +from mcpacker.model.core.resourceid import ResourceId + +import mcpacker.model.core.material.soundtype as ST + + +# Class ############################################################################################ + +class Block: + + def __init__( + self, + name:str, + gameId:ResourceId, + loot:LootTable, + requiresTool:bool=False, + soundType:SoundType=ST.STONE, + tags:list[str]=None, + ): + self.gameId = gameId + self.loot = loot + self.name = name + self.requiresTool = requiresTool + self.silkTouchLoot = loot + self.soundType = soundType + self.tags = tags or [] diff --git a/mcpacker/model/core/material/block_test.py b/mcpacker/model/core/material/block_test.py new file mode 100644 index 0000000..e701d58 --- /dev/null +++ b/mcpacker/model/core/material/block_test.py @@ -0,0 +1,6 @@ +import mcpacker.model.core.material.block + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/blockcatalog.py b/mcpacker/model/core/material/blockcatalog.py new file mode 100644 index 0000000..4c99781 --- /dev/null +++ b/mcpacker/model/core/material/blockcatalog.py @@ -0,0 +1,30 @@ +from mcpacker.model.core.material.block import Block +from typing import Iterator + + +# Class ############################################################################################ + +class BlockCatalog: + + def __init__(self, blocks:tuple[Block]=None): + self._blocks = {} + + for block in (blocks or []): + self.add(block) + + def __len__(self) -> int: + return len(self._blocks) + + def add(self, block:Block) -> "BlockCatalog": + if block.name in self._blocks: + raise Exception(f"Catalog already contains an entry for {block.name}") + + self._blocks[block.name] = block + + def all(self) -> Iterator[Block]: + for block in self._blocks.values(): + yield block + + def get(self, name:str) -> Block|None: + return self._blocks.get(name, None) + diff --git a/mcpacker/model/core/material/blockcatalog_test.py b/mcpacker/model/core/material/blockcatalog_test.py new file mode 100644 index 0000000..01b7782 --- /dev/null +++ b/mcpacker/model/core/material/blockcatalog_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.blockcatalog + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/item.py b/mcpacker/model/core/material/item.py new file mode 100644 index 0000000..8e30ff9 --- /dev/null +++ b/mcpacker/model/core/material/item.py @@ -0,0 +1,12 @@ +from mcpacker.model.core.resourceid import ResourceId + + +# Class ############################################################################################ + +class Item: + + def __init__(self, gameId:ResourceId): + self.gameId = gameId + + if not isinstance(self.gameId, ResourceId): + self.gameId = ResourceId.parse(str(self.gameId)) diff --git a/mcpacker/model/core/material/item_test.py b/mcpacker/model/core/material/item_test.py new file mode 100644 index 0000000..6416a91 --- /dev/null +++ b/mcpacker/model/core/material/item_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.item + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/itemcatalog.py b/mcpacker/model/core/material/itemcatalog.py new file mode 100644 index 0000000..8ca6b96 --- /dev/null +++ b/mcpacker/model/core/material/itemcatalog.py @@ -0,0 +1,27 @@ +from mcpacker.model.core.material.item import Item +from typing import Iterator + + +# Class ############################################################################################ + +class ItemCatalog: + + def __init__(self, items:tuple[Item]=None): + self._items = {} + + for item in (items or []): + self.add(item) + + def add(self, item:Item) -> "ItemCatalog": + if item.gameId in self._items: + raise Exception(f"Catalog already contains an entry for {item.gameId}") + + self._items[item.gameId] = item + + def all(self) -> Iterator[Item]: + for item in self._items.values(): + yield item + + def get(self, gameId:str) -> Item|None: + return self._items.get(gameId, None) + diff --git a/mcpacker/model/core/material/itemcatalog_test.py b/mcpacker/model/core/material/itemcatalog_test.py new file mode 100644 index 0000000..4995903 --- /dev/null +++ b/mcpacker/model/core/material/itemcatalog_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.itemcatalog + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/loot.py b/mcpacker/model/core/material/loot.py new file mode 100644 index 0000000..682bec1 --- /dev/null +++ b/mcpacker/model/core/material/loot.py @@ -0,0 +1,24 @@ +from mcpacker.model.core.material.item import Item + + +# Class ############################################################################################ + +class Loot: + + def __init__(self, item:Item, maxCount:int=1, minCount:int=1, weight:int=1): + self.item = item + self.maxCount = maxCount + self.minCount = minCount + self.weight = weight + + def __repr__(self) -> str: + return "".join([repr(p) for p in [ + "Loot{", + "item: ", self.item, ", ", + "minCount: ", self.minCount, ", ", + "weight: ", self.weight, + "}" + ]]) + + def __str__(self) -> str: + return f"{str(item)} ({self.minCount}..{self.maxCount} @ {self.weight})" diff --git a/mcpacker/model/core/material/loot_test.py b/mcpacker/model/core/material/loot_test.py new file mode 100644 index 0000000..7bee294 --- /dev/null +++ b/mcpacker/model/core/material/loot_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.loot + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/loottable.py b/mcpacker/model/core/material/loottable.py new file mode 100644 index 0000000..ae9d664 --- /dev/null +++ b/mcpacker/model/core/material/loottable.py @@ -0,0 +1,9 @@ +from mcpacker.model.core.material.loot import Loot + + +# Class ############################################################################################ + +class LootTable: + + def __init__(self, items:list[Loot]): + self.items = items diff --git a/mcpacker/model/core/material/loottable_test.py b/mcpacker/model/core/material/loottable_test.py new file mode 100644 index 0000000..190ee3a --- /dev/null +++ b/mcpacker/model/core/material/loottable_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.loottable + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/material/soundtype.py b/mcpacker/model/core/material/soundtype.py new file mode 100644 index 0000000..4951251 --- /dev/null +++ b/mcpacker/model/core/material/soundtype.py @@ -0,0 +1,35 @@ +# Class ############################################################################################ + +class SoundType: + + def __init__(self, name:str): + self.name = name + + def __eq__(self, other) -> bool: + if type(self) != type(other): return False + if self.name != other.name: return False + return True + + def __hash__(self) -> int: + return hash(self.name) + + def __repr__(self) -> str: + return f"SoundType<{self.name}>" + + def __str__(self) -> str: + return self.name + +# Constants ######################################################################################## + +CRYSTAL = SoundType("crystal") +DIRT = SoundType("dirt") +FOLIAGE = SoundType("foliage") +GLASS = SoundType("glass") +GRAVEL = SoundType("gravel") +HONEY = SoundType("honey") +METAL = SoundType("metal") +SCULK = SoundType("sculk") +SLIME = SoundType("slime") +STONE = SoundType("stone") +WOOD = SoundType("wood") +WOOL = SoundType("wool") diff --git a/mcpacker/model/core/material/soundtype_test.py b/mcpacker/model/core/material/soundtype_test.py new file mode 100644 index 0000000..893c007 --- /dev/null +++ b/mcpacker/model/core/material/soundtype_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.core.material.soundtype + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/core/season.py b/mcpacker/model/core/season.py index 95d80c4..fa32e38 100644 --- a/mcpacker/model/core/season.py +++ b/mcpacker/model/core/season.py @@ -34,7 +34,7 @@ COLD = [WINTER] # Constants ######################################################################################## -def excluding(target:Season) -> list[Season]: +def exclude(target:Season) -> list[Season]: result = [] for season in ALL: diff --git a/mcpacker/model/core/season_test.py b/mcpacker/model/core/season_test.py index 9fbd5d5..c5f4d2e 100644 --- a/mcpacker/model/core/season_test.py +++ b/mcpacker/model/core/season_test.py @@ -7,10 +7,10 @@ import mcpacker.model.core.season as season @fixture(name="notSummer") def createNotSummerList(): - yield season.excluding(season.SUMMER) + yield season.exclude(season.SUMMER) # Tests ############################################################################################ -def test_excluding(notSummer): +def test_exclude(notSummer): assert ", ".join([str(s) for s in notSummer]) == "spring, autumn, winter" diff --git a/mcpacker/model/core/world.py b/mcpacker/model/core/world.py index 2b05340..7254adf 100644 --- a/mcpacker/model/core/world.py +++ b/mcpacker/model/core/world.py @@ -1,7 +1,9 @@ -from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog -from mcpacker.model.core.fauna.mobcatalog import MobCatalog +from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog +from mcpacker.model.core.fauna.mobcatalog import MobCatalog from mcpacker.model.core.geology.depositcatalog import DepositCatalog from mcpacker.model.core.geology.mineralcatalog import MineralCatalog +from mcpacker.model.core.material.blockcatalog import BlockCatalog +from mcpacker.model.core.material.itemcatalog import ItemCatalog # Class ############################################################################################ @@ -10,12 +12,16 @@ class World: def __init__( self, - biomes:BiomeCatalog, - deposits:DepositCatalog, - minerals:MineralCatalog, - mobs:MobCatalog + biomes:BiomeCatalog|None=None, + blocks:BlockCatalog|None=None, + deposits:DepositCatalog|None=None, + items:ItemCatalog|None=None, + minerals:MineralCatalog|None=None, + mobs:MobCatalog|None=None, ): - self.biomes = biomes - self.deposits = deposits - self.minerals = minerals - self.mobs = mobs + self.biomes = biomes or BiomeCatalog() + self.blocks = blocks or BlockCatalog() + self.deposits = deposits or DepositCatalog() + self.items = items or ItemCatalog() + self.minerals = minerals or MineralCatalog() + self.mobs = mobs or MobCatalog() diff --git a/mcpacker/model/datapack/__init__.py b/mcpacker/model/datapack/__init__.py index c11094f..efe322c 100644 --- a/mcpacker/model/datapack/__init__.py +++ b/mcpacker/model/datapack/__init__.py @@ -1,22 +1,23 @@ +from collections.abc import Iterable from mcpacker.model.datapack.mod import Mod # Class ############################################################################################ -class Datapack: +class DataPack: - def __init__(self, name:str, mods:list[Mod]): + def __init__(self, name:str, mods:Iterable[Mod]|None=None): self.name = name self._mods = {} self._defaultMod = None - for mod in mods: - if not self._defaultMod: - self._defaultMod = mod - + for mod in (mods or []): self.add(mod) def add(self, mod:Mod) -> "Datapack": + if not self._defaultMod: + self._defaultMod = mod + self._mods[mod.name] = mod return self diff --git a/mcpacker/model/datapack/mod.py b/mcpacker/model/datapack/mod.py index cd8826f..ae11120 100644 --- a/mcpacker/model/datapack/mod.py +++ b/mcpacker/model/datapack/mod.py @@ -1,3 +1,5 @@ +# Class ############################################################################################ + class Mod: def __init__(self): diff --git a/mcpacker/model/mod.py b/mcpacker/model/mod.py new file mode 100644 index 0000000..bcc7565 --- /dev/null +++ b/mcpacker/model/mod.py @@ -0,0 +1,6 @@ +# Class ############################################################################################ + +class Mod: + + def __init__(self, name:str): + self.name = name diff --git a/mcpacker/model/mod_test.py b/mcpacker/model/mod_test.py new file mode 100644 index 0000000..9d34fee --- /dev/null +++ b/mcpacker/model/mod_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.mod + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/modpack.py b/mcpacker/model/modpack.py new file mode 100644 index 0000000..52d1383 --- /dev/null +++ b/mcpacker/model/modpack.py @@ -0,0 +1,31 @@ +from collections.abc import Iterable +from mcpacker.model.core.world import World +from mcpacker.model.datapack import DataPack +from mcpacker.model.mod import Mod +from mcpacker.model.resourcepack import ResourcePack +from typing import Callable + + +# Class ############################################################################################ + +class ModPack: + + def __init__( + self, + name:str, + mods:Iterable[Mod]|None=None, + world:World|None=None, + dataPack:DataPack|None=None, + resourcePack:ResourcePack|None=None, + ): + self.name = name + self.world = world or World() + self.dataPack = dataPack or DataPack(self.name) + self.resourcePack = resourcePack or ResourcePack(self.name) + + self._mods = {} + for mod in (mods or []): + self._mods[mod.name] = mod + + def augment(self, doAugment:"Callable[[ModPack], None]") -> "ModPack": + doAugment(self) diff --git a/mcpacker/model/modpack_test.py b/mcpacker/model/modpack_test.py new file mode 100644 index 0000000..c3503ec --- /dev/null +++ b/mcpacker/model/modpack_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.modpack + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/resourcepack/__init__.py b/mcpacker/model/resourcepack/__init__.py new file mode 100644 index 0000000..b2be0b2 --- /dev/null +++ b/mcpacker/model/resourcepack/__init__.py @@ -0,0 +1,40 @@ +from collections.abc import Iterable +from mcpacker.model.resourcepack.mod import Mod + + +# Class ############################################################################################ + +class ResourcePack: + + def __init__(self, name:str, mods:Iterable[Mod]|None=None): + self.name = name + self._mods = {} + self._defaultMod = None + + for mod in (mods or []): + self.add(mod) + + def add(self, mod:Mod) -> "Resourcepack": + if not self._defaultMod: + self._defaultMod = mod + + self._mods[mod.name] = mod + return self + + def get(self, modName:str) -> Mod: + return self._mods.get(modName, None) + + @property + def defaultMod(self) -> Mod: + return self._defaultMod + + @defaultMod.setter + def setDefaultMod(self, mod:Mod) -> "Resourcepack": + existingMod = self.get(mod.name) + if not existingMod: + self.add(mod) + elif existingMod != mod: + raise Exception(f"Resourcepack already has a mod named {mod.name}") + + self._defaultMod = mod + diff --git a/mcpacker/model/resourcepack/kind.py b/mcpacker/model/resourcepack/kind.py new file mode 100644 index 0000000..3af73ec --- /dev/null +++ b/mcpacker/model/resourcepack/kind.py @@ -0,0 +1,23 @@ +# Class ############################################################################################ + +class Kind: + + def __init__(self, name:str): + self.name = name + + def __eq__(self, other) -> bool: + if type(self) != type(other): return False + if self.name != othere.name: return False + return True + + def __repr__(self) -> str: + return f"Kind<{self.name}>" + + def __str__(self) -> str: + return self.name + + +# Constants ######################################################################################## + +ITEM = Kind("item") +BLOCK = Kind("block") diff --git a/mcpacker/model/resourcepack/kind_test.py b/mcpacker/model/resourcepack/kind_test.py new file mode 100644 index 0000000..1d7c727 --- /dev/null +++ b/mcpacker/model/resourcepack/kind_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.resourcepack.kind + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/model/resourcepack/mod.py b/mcpacker/model/resourcepack/mod.py new file mode 100644 index 0000000..5c0bc92 --- /dev/null +++ b/mcpacker/model/resourcepack/mod.py @@ -0,0 +1,8 @@ +# Class ############################################################################################ + +class Mod: + + def __init__(self): + self.blockStates = [] + self.models = [] + self.textures = [] diff --git a/mcpacker/model/resourcepack/mod_test.py b/mcpacker/model/resourcepack/mod_test.py new file mode 100644 index 0000000..be11191 --- /dev/null +++ b/mcpacker/model/resourcepack/mod_test.py @@ -0,0 +1,8 @@ +import mcpacker.model.resourcepack.mod + + +# Tests ############################################################################################ + +def test_syntax(): + pass + diff --git a/mcpacker/model/resourcepack/texture.py b/mcpacker/model/resourcepack/texture.py new file mode 100644 index 0000000..77b5d5a --- /dev/null +++ b/mcpacker/model/resourcepack/texture.py @@ -0,0 +1,10 @@ +from mcpacker.model.resourcepack.kind import Kind + + +# Class ############################################################################################ + +class Texture: + + def __init__(self, imageFileName:str, kind:Kind): + self.imageFileName = imageFileName + self.kind = kind diff --git a/mcpacker/model/resourcepack/texture_test.py b/mcpacker/model/resourcepack/texture_test.py new file mode 100644 index 0000000..255b070 --- /dev/null +++ b/mcpacker/model/resourcepack/texture_test.py @@ -0,0 +1,7 @@ +import mcpacker.model.resourcepack.texture + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/assets/textures/block/peat_block.png b/mcpacker/pack/mysteriousisland/assets/images/peat_block.png similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/textures/block/peat_block.png rename to mcpacker/pack/mysteriousisland/assets/images/peat_block.png diff --git a/mcpacker/pack/mysteriousisland/assets/textures/item/peat_chunk.png b/mcpacker/pack/mysteriousisland/assets/images/peat_chunk.png similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/textures/item/peat_chunk.png rename to mcpacker/pack/mysteriousisland/assets/images/peat_chunk.png diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_bed_loam_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_bed_loam_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_bed_loam_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_bed_loam_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_bif_iron_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_bif_iron_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_bif_iron_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_bif_iron_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_epithermal_silver_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_epithermal_silver_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_epithermal_silver_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_epithermal_silver_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_evaporite_nitrate_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_nitrate_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_evaporite_nitrate_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_nitrate_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_evaporite_salt_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_salt_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_evaporite_salt_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_salt_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_fulmarole_sulfur_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_fulmarole_sulfur_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_fulmarole_sulfur_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_fulmarole_sulfur_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_geode_amethyst_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_geode_amethyst_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_geode_amethyst_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_geode_amethyst_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_greisen_tin_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_greisen_tin_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_greisen_tin_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_greisen_tin_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_hydrothermal_emerald_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_hydrothermal_emerald_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_hydrothermal_emerald_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_hydrothermal_emerald_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_laterite_aluminum_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_laterite_aluminum_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_laterite_aluminum_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_laterite_aluminum_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_lavatube_diamond_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_lavatube_diamond_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_lavatube_diamond_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_lavatube_diamond_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_mvt_lead_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_mvt_lead_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_mvt_lead_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_mvt_lead_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_porphyry_copper_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_porphyry_copper_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_porphyry_copper_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_porphyry_copper_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_seam_bituminouscoal_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_bituminouscoal_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_seam_bituminouscoal_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_bituminouscoal_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_seam_peatcoal_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_peatcoal_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_seam_peatcoal_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_peatcoal_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_sedimentary_iron_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_sedimentary_iron_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_sedimentary_iron_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_sedimentary_iron_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/structure/deposit_skarnlapis_marker.nbt b/mcpacker/pack/mysteriousisland/assets/nbts/deposit_skarnlapis_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/structure/deposit_skarnlapis_marker.nbt rename to mcpacker/pack/mysteriousisland/assets/nbts/deposit_skarnlapis_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/biomecatalog.py b/mcpacker/pack/mysteriousisland/biomecatalog.py index 57c40c3..421813b 100644 --- a/mcpacker/pack/mysteriousisland/biomecatalog.py +++ b/mcpacker/pack/mysteriousisland/biomecatalog.py @@ -1,6 +1,6 @@ -from mcpacker.model.core.ecology.biome import Biome -from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog +from mcpacker.model.core.ecology.biome import Biome from mcpacker.model.core.ecology.biomefilter import BiomeFilter +from mcpacker.model.modpack import ModPack import mcpacker.model.core.ecology.flora as FL import mcpacker.model.core.ecology.geology as GE @@ -9,157 +9,306 @@ import mcpacker.model.core.ecology.humidity as HU import mcpacker.model.core.ecology.soil as SO import mcpacker.model.core.ecology.water as WA -# Constants ######################################################################################## -CATALOG = BiomeCatalog([ - Biome("aberdeen", "minecraft:windswept_gravelly_hills", - FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ROCKY, WA.INLAND - ), - Biome("archangel", "minecraft:frozen_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("aspen", "minecraft:frozen_peaks", - FL.BARREN, GE.IGNEOUS, HE.FROZEN, HU.WET, SO.ROCKY, WA.INLAND - ), - Biome("bombay", "minecraft:lukewarm_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("boston", "minecraft:cold_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.BOREAL, HU.WET, SO.CLAYEY, WA.OCEAN - ), - Biome("bryce", "minecraft:eroded_badlands", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND - ), - Biome("calcutta", "minecraft:mangrove_swamp", - FL.FOREST, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.CLAYEY, WA.INLAND - ), - Biome("cornwall", "minecraft:windswept_hills", - FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ROCKY, WA.INLAND - ), - Biome("dallas", "minecraft:savanna", - FL.FIELD, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.SANDY, WA.INLAND - ), - Biome("duluth", "minecraft:frozen_river", - FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.RIVER - ), - Biome("durango", "minecraft:savanna_plateau", - FL.FIELD, GE.IGNEOUS, HE.SUBTROPICAL, HU.DRY, SO.SANDY, WA.INLAND - ), - Biome("freiburg", "minecraft:dark_forest", - FL.CANOPY, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.CLAYEY, WA.INLAND - ), - Biome("glasgow", "minecraft:windswept_forest", - FL.CLEARING, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("haarlem", "minecraft:flower_forest", - FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND - ), - Biome("halifax", "minecraft:deep_cold_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.BOREAL, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("hammerfest", "minecraft:ice_spikes", - FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.WET, SO.ROCKY, WA.INLAND - ), - Biome("havana", "minecraft:deep_lukewarm_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("hilo", "minecraft:mushroom_fields", - FL.CLEARING, GE.IGNEOUS, HE.SUBTROPICAL, HU.WET, SO.FUNGAL, WA.INLAND - ), - Biome("honolulu", "minecraft:deep_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("innnesbruk", "minecraft:meadow", - FL.FIELD, GE.SEDIMENTARY, HE.BOREAL, HU.DAMP, SO.PEATY, WA.INLAND - ), - Biome("irkutsk", "minecraft:taiga", - FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("jackson", "minecraft:jagged_peaks", - FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DRY, SO.ROCKY, WA.INLAND - ), - Biome("juneau", "minecraft:old_growth_spruce_taiga", - FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.PEATY, WA.INLAND - ), - Biome("kansascity", "minecraft:plains", - FL.FIELD, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND - ), - Biome("kola", "minecraft:snowy_taiga", - FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("kyoto", "minecraft:cherry_grove", - FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ROCKY, WA.INLAND - ), - Biome("madras", "minecraft:sparse_jungle", - FL.CLEARING, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND - ), - Biome("memphis", "minecraft:river", - FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.RIVER - ), - Biome("minsk", "minecraft:old_growth_birch_forest", - FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("moab", "minecraft:windswept_savanna", - FL.FIELD, GE.IGNEOUS, HE.SUBTROPICAL, HU.DRY, SO.ROCKY, WA.INLAND - ), - Biome("mobile", "minecraft:swamp", - FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.PEATY, WA.SWAMP - ), - Biome("moscow", "minecraft:snowy_plains", - FL.FIELD, GE.SEDIMENTARY, HE.FROZEN, HU.DAMP, SO.LOAMY, WA.INLAND - ), - Biome("nassau", "minecraft:warm_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.SANDY, WA.COAST - ), - Biome("nice", "minecraft:beach", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DAMP, SO.SANDY, WA.COAST - ), - Biome("nuuk", "minecraft:beach", - FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.DAMP, SO.SANDY, WA.COAST - ), - Biome("perm", "minecraft:old_growth_pine_taiga", - FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("phoenix", "minecraft:desert", - FL.BARREN, GE.SEDIMENTARY, HE.TROPICAL, HU.DRY, SO.SANDY, WA.INLAND - ), - Biome("plymouth", "minecraft:stony_shore", - FL.BARREN, GE.METAMORPHIC, HE.TEMPERATE, HU.DAMP, SO.ROCKY, WA.COAST - ), - Biome("portland", "minecraft:forest", - FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND - ), - Biome("quito", "minecraft:stony_peaks", - FL.BARREN, GE.IGNEOUS, HE.BOREAL, HU.DRY, SO.ROCKY, WA.INLAND - ), - Biome("rangoon", "minecraft:bamboo_jungle", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.LOAMY, WA.INLAND - ), - Biome("sanfrancisco", "minecraft:ocean", - FL.BARREN, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("santafe", "minecraft:wooded_badlands", - FL.CLEARING, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND - ), - Biome("singapore", "minecraft:jungle", - FL.CANOPY, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND - ), - Biome("tombstone", "minecraft:badlands", - FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND - ), - Biome("topeka", "minecraft:sunflower_plains", - FL.FIELD, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND - ), - Biome("tromso", "minecraft:deep_frozen_ocean", - FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.OCEAN - ), - Biome("umea", "minecraft:grove", - FL.CLEARING, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("warsaw", "minecraft:birch_forest", - FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ACIDIC, WA.INLAND - ), - Biome("zurich", "minecraft:snowy_slopes", - FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ROCKY, WA.INLAND - ), -]) +# Functions ######################################################################################## + +def addBiomes(pack:ModPack): + pack.world.biomes.add( + Biome("aberdeen", "minecraft:windswept_gravelly_hills", + FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("archangel", "minecraft:frozen_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("aspen", "minecraft:frozen_peaks", + FL.BARREN, GE.IGNEOUS, HE.FROZEN, HU.WET, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("bombay", "minecraft:lukewarm_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("boston", "minecraft:cold_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.BOREAL, HU.WET, SO.CLAYEY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("bryce", "minecraft:eroded_badlands", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("calcutta", "minecraft:mangrove_swamp", + FL.FOREST, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.CLAYEY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("cornwall", "minecraft:windswept_hills", + FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("dallas", "minecraft:savanna", + FL.FIELD, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.SANDY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("duluth", "minecraft:frozen_river", + FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.RIVER + ) + ) + + pack.world.biomes.add( + Biome("durango", "minecraft:savanna_plateau", + FL.FIELD, GE.IGNEOUS, HE.SUBTROPICAL, HU.DRY, SO.SANDY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("freiburg", "minecraft:dark_forest", + FL.CANOPY, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.CLAYEY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("glasgow", "minecraft:windswept_forest", + FL.CLEARING, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("haarlem", "minecraft:flower_forest", + FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("halifax", "minecraft:deep_cold_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.BOREAL, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("hammerfest", "minecraft:ice_spikes", + FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.WET, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("havana", "minecraft:deep_lukewarm_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("hilo", "minecraft:mushroom_fields", + FL.CLEARING, GE.IGNEOUS, HE.SUBTROPICAL, HU.WET, SO.FUNGAL, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("honolulu", "minecraft:deep_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("innnesbruk", "minecraft:meadow", + FL.FIELD, GE.SEDIMENTARY, HE.BOREAL, HU.DAMP, SO.PEATY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("irkutsk", "minecraft:taiga", + FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("jackson", "minecraft:jagged_peaks", + FL.BARREN, GE.METAMORPHIC, HE.BOREAL, HU.DRY, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("juneau", "minecraft:old_growth_spruce_taiga", + FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.PEATY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("kansascity", "minecraft:plains", + FL.FIELD, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("kola", "minecraft:snowy_taiga", + FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("kyoto", "minecraft:cherry_grove", + FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("madras", "minecraft:sparse_jungle", + FL.CLEARING, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("memphis", "minecraft:river", + FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.RIVER + ) + ) + + pack.world.biomes.add( + Biome("minsk", "minecraft:old_growth_birch_forest", + FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("moab", "minecraft:windswept_savanna", + FL.FIELD, GE.IGNEOUS, HE.SUBTROPICAL, HU.DRY, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("mobile", "minecraft:swamp", + FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.PEATY, WA.SWAMP + ) + ) + + pack.world.biomes.add( + Biome("moscow", "minecraft:snowy_plains", + FL.FIELD, GE.SEDIMENTARY, HE.FROZEN, HU.DAMP, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("nassau", "minecraft:warm_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.SANDY, WA.COAST + ) + ) + + pack.world.biomes.add( + Biome("nice", "minecraft:beach", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DAMP, SO.SANDY, WA.COAST + ) + ) + + pack.world.biomes.add( + Biome("nuuk", "minecraft:snowy_beach", + FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.DAMP, SO.SANDY, WA.COAST + ) + ) + + pack.world.biomes.add( + Biome("perm", "minecraft:old_growth_pine_taiga", + FL.FOREST, GE.METAMORPHIC, HE.BOREAL, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("phoenix", "minecraft:desert", + FL.BARREN, GE.SEDIMENTARY, HE.TROPICAL, HU.DRY, SO.SANDY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("plymouth", "minecraft:stony_shore", + FL.BARREN, GE.METAMORPHIC, HE.TEMPERATE, HU.DAMP, SO.ROCKY, WA.COAST + ) + ) + + pack.world.biomes.add( + Biome("portland", "minecraft:forest", + FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("quito", "minecraft:stony_peaks", + FL.BARREN, GE.IGNEOUS, HE.BOREAL, HU.DRY, SO.ROCKY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("rangoon", "minecraft:bamboo_jungle", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("sanfrancisco", "minecraft:ocean", + FL.BARREN, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("santafe", "minecraft:wooded_badlands", + FL.CLEARING, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("singapore", "minecraft:jungle", + FL.CANOPY, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("tombstone", "minecraft:badlands", + FL.BARREN, GE.SEDIMENTARY, HE.SUBTROPICAL, HU.DRY, SO.CLAYEY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("topeka", "minecraft:sunflower_plains", + FL.FIELD, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.LOAMY, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("tromso", "minecraft:deep_frozen_ocean", + FL.BARREN, GE.SEDIMENTARY, HE.FROZEN, HU.WET, SO.SANDY, WA.OCEAN + ) + ) + + pack.world.biomes.add( + Biome("umea", "minecraft:grove", + FL.CLEARING, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("warsaw", "minecraft:birch_forest", + FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE, HU.DAMP, SO.ACIDIC, WA.INLAND + ) + ) + + pack.world.biomes.add( + Biome("zurich", "minecraft:snowy_slopes", + FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ROCKY, WA.INLAND + ) + ) diff --git a/mcpacker/pack/mysteriousisland/blockcatalog.py b/mcpacker/pack/mysteriousisland/blockcatalog.py new file mode 100644 index 0000000..68634dd --- /dev/null +++ b/mcpacker/pack/mysteriousisland/blockcatalog.py @@ -0,0 +1,23 @@ +from mcpacker.model.core.material.block import Block +from mcpacker.model.core.material.blockcatalog import BlockCatalog +from mcpacker.model.core.material.item import Item +from mcpacker.model.core.material.loottable import LootTable +from mcpacker.model.core.material.loot import Loot +from mcpacker.model.modpack import ModPack + +import mcpacker.model.core.material.soundtype as SO + + +# Functions ######################################################################################## + +def addBlocks(pack:ModPack): + blocks = pack.world.blocks + items = pack.world.items + + blocks.add(Block( + gameId = "kubejs:peat_block", + loot = LootTable(Loot(items.get("kubejs:peat_chunk"), 2, 9)), + name = "Peat Block", + soundType = SO.DIRT, + tags = ["minecraft:mineable/shovel"], + )) diff --git a/mcpacker/pack/mysteriousisland/blockcatalog_test.py b/mcpacker/pack/mysteriousisland/blockcatalog_test.py new file mode 100644 index 0000000..620396f --- /dev/null +++ b/mcpacker/pack/mysteriousisland/blockcatalog_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.blockcatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/datapack.py b/mcpacker/pack/mysteriousisland/datapack.py new file mode 100644 index 0000000..afcbf6c --- /dev/null +++ b/mcpacker/pack/mysteriousisland/datapack.py @@ -0,0 +1,8 @@ +from mcpacker.model.modpack import ModPack +from mcpacker.model.datapack import DataPack + + +# Functions ######################################################################################## + +def addDataPack(modPack:ModPack): + pass diff --git a/mcpacker/pack/mysteriousisland/datapack_test.py b/mcpacker/pack/mysteriousisland/datapack_test.py new file mode 100644 index 0000000..7ba8318 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/datapack_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.datapack + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/depositcatalog.py b/mcpacker/pack/mysteriousisland/depositcatalog.py index 5e2c8c5..5488efa 100644 --- a/mcpacker/pack/mysteriousisland/depositcatalog.py +++ b/mcpacker/pack/mysteriousisland/depositcatalog.py @@ -1,8 +1,7 @@ -from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF +from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF from mcpacker.model.core.geology.deposit.metaldeposit import MetalDeposit -from mcpacker.model.core.geology.depositcatalog import DepositCatalog -from mcpacker.model.core.geology.inclusion import Inclusion as I -from mcpacker.pack.mysteriousisland.mineralcatalog import CATALOG as M +from mcpacker.model.core.geology.inclusion import Inclusion as I +from mcpacker.model.modpack import ModPack import mcpacker.model.core.altitude as AL import mcpacker.model.core.ecology.flora as FL @@ -16,13 +15,19 @@ import mcpacker.model.core.scarcity as SC # Catalog ########################################################################################## -CATALOG = C = DepositCatalog() +def addDeposits(pack:ModPack): + minerals = pack.world.minerals + deposits = pack.world.deposits -C.add(MetalDeposit( - name = "bif_iron", - scarcity = SC.COMMON, - 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, - proportion = 0.2, -)) + deposits.add(MetalDeposit( + name = "bif_iron", + scarcity = SC.COMMON, + biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]), + inclusions = [ + I(minerals.get("iron"), 50), + I(minerals.get("quartz"), 45), + I(minerals.get("uranium"), 5) + ], + bulk = BU.LARGE, + proportion = 0.2, + )) diff --git a/mcpacker/pack/mysteriousisland/itemcatalog.py b/mcpacker/pack/mysteriousisland/itemcatalog.py new file mode 100644 index 0000000..388b76b --- /dev/null +++ b/mcpacker/pack/mysteriousisland/itemcatalog.py @@ -0,0 +1,8 @@ +from mcpacker.model.core.material.item import Item +from mcpacker.model.modpack import ModPack + + +# Constants ######################################################################################## + +def addItems(pack:ModPack): + pack.world.items.add(Item("kubejs:peak_chunk")) diff --git a/mcpacker/pack/mysteriousisland/itemcatalog_test.py b/mcpacker/pack/mysteriousisland/itemcatalog_test.py new file mode 100644 index 0000000..620396f --- /dev/null +++ b/mcpacker/pack/mysteriousisland/itemcatalog_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.blockcatalog + + +# Class ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/mineralcatalog.py b/mcpacker/pack/mysteriousisland/mineralcatalog.py index e97be34..643fb41 100644 --- a/mcpacker/pack/mysteriousisland/mineralcatalog.py +++ b/mcpacker/pack/mysteriousisland/mineralcatalog.py @@ -1,6 +1,7 @@ -from mcpacker.model.core.geology.mineral import Mineral +from mcpacker.model.core.geology.mineral import Mineral from mcpacker.model.core.geology.mineralcatalog import MineralCatalog -from mcpacker.model.core.geology.replacement import Replacement +from mcpacker.model.core.geology.replacement import Replacement +from mcpacker.model.modpack import ModPack # Constants ######################################################################################## @@ -41,69 +42,70 @@ def makeRailcraftOreMineral(name:str) -> Mineral: # Catalog ########################################################################################## -CATALOG = C = MineralCatalog() +def addMinerals(pack:ModPack): + minerals = pack.world.minerals -# Basic Ores -C.add(makeOreMineral("coal")) -C.add(makeOreMineral("copper")) -C.add(makeOreMineral("diamond")) -C.add(makeOreMineral("emerald")) -C.add(makeOreMineral("gold")) -C.add(makeOreMineral("iron")) -C.add(makeOreMineral("lapis")) -C.add(makeOreMineral("redstone")) + # Basic Ores + minerals.add(makeOreMineral("coal")) + minerals.add(makeOreMineral("copper")) + minerals.add(makeOreMineral("diamond")) + minerals.add(makeOreMineral("emerald")) + minerals.add(makeOreMineral("gold")) + minerals.add(makeOreMineral("iron")) + minerals.add(makeOreMineral("lapis")) + minerals.add(makeOreMineral("redstone")) -# Crystals -C.add(makeMineral("amethyst", "amethyst_block")) -C.add(makeMineral("glowstone", "glowstone")) -C.add(makeMineral("quartz", f"{OQ}:quartz_ore", f"{OQ}:deepslate_quartz_ore")) -C.add(makeMineral("salt", "butcher:saltblock")) + # Crystals + minerals.add(makeMineral("amethyst", "amethyst_block")) + minerals.add(makeMineral("glowstone", "glowstone")) + minerals.add(makeMineral("quartz", f"{OQ}:quartz_ore", f"{OQ}:deepslate_quartz_ore")) + minerals.add(makeMineral("salt", "butcher:saltblock")) -# Earth, gravel, etc. -C.add(makeMineral("clay", "clay")) -C.add(makeMineral("coarsedirt", "coarse_dirt")) -C.add(makeMineral("dirt", "dirt")) -C.add(makeMineral("gravel", "gravel")) -C.add(makeMineral("loam", "farmersdelight:rich_soil")) -C.add(makeMineral("packedice", "packed_ice")) -C.add(makeMineral("peat", "kubejs:peat_block")) -C.add(makeMineral("redsand", "redsand")) -C.add(makeMineral("sand", "sand")) -C.add(makeMineral("soulsand", "soulsand")) + # Earth, gravel, etc. + minerals.add(makeMineral("clay", "clay")) + minerals.add(makeMineral("coarsedirt", "coarse_dirt")) + minerals.add(makeMineral("dirt", "dirt")) + minerals.add(makeMineral("gravel", "gravel")) + minerals.add(makeMineral("loam", "farmersdelight:rich_soil")) + minerals.add(makeMineral("packedice", "packed_ice")) + minerals.add(makeMineral("peat", "kubejs:peat_block")) + minerals.add(makeMineral("redsand", "redsand")) + minerals.add(makeMineral("sand", "sand")) + minerals.add(makeMineral("soulsand", "soulsand")) -# Stone -C.add(makeMineral("andesite", "andesite")) -C.add(makeMineral("arkrose", "red_sandstone")) -C.add(makeMineral("basalt", "basalt")) -C.add(makeMineral("breccia", "cobblestone")) -C.add(makeMineral("chalk", "calcite")) -C.add(makeMineral("diorite", "diorite")) -C.add(makeMineral("dolostone", "end_stone")) -C.add(makeMineral("gneiss", "deepslate")) -C.add(makeMineral("granite", "granite")) -C.add(makeMineral("greywacke", "stone")) -C.add(makeMineral("komatite", "blackstone")) -C.add(makeMineral("limestone", "dripstone_block")) -C.add(makeMineral("magma", "magma_block")) -C.add(makeMineral("marble", f"{RC}:quarried_stone")) -C.add(makeMineral("netherite", "ancient_debris")) -C.add(makeMineral("obsidian", "obsidian")) -C.add(makeMineral("pumice", "netherrack")) -C.add(makeMineral("sandstone", "sandstone")) -C.add(makeMineral("tuff", "tuff")) + # Stone + minerals.add(makeMineral("andesite", "andesite")) + minerals.add(makeMineral("arkrose", "red_sandstone")) + minerals.add(makeMineral("basalt", "basalt")) + minerals.add(makeMineral("breccia", "cobblestone")) + minerals.add(makeMineral("chalk", "calcite")) + minerals.add(makeMineral("diorite", "diorite")) + minerals.add(makeMineral("dolostone", "end_stone")) + minerals.add(makeMineral("gneiss", "deepslate")) + minerals.add(makeMineral("granite", "granite")) + minerals.add(makeMineral("greywacke", "stone")) + minerals.add(makeMineral("komatite", "blackstone")) + minerals.add(makeMineral("limestone", "dripstone_block")) + minerals.add(makeMineral("magma", "magma_block")) + minerals.add(makeMineral("marble", f"{RC}:quarried_stone")) + minerals.add(makeMineral("netherite", "ancient_debris")) + minerals.add(makeMineral("obsidian", "obsidian")) + minerals.add(makeMineral("pumice", "netherrack")) + minerals.add(makeMineral("sandstone", "sandstone")) + minerals.add(makeMineral("tuff", "tuff")) -# Immersive Engineering Ores -C.add(makeImmersiveEngineeringOreMineral("aluminum")) -C.add(makeImmersiveEngineeringOreMineral("lead")) -C.add(makeImmersiveEngineeringOreMineral("nickel")) -C.add(makeImmersiveEngineeringOreMineral("silver")) -C.add(makeImmersiveEngineeringOreMineral("uranium")) + # Immersive Engineering Ores + minerals.add(makeImmersiveEngineeringOreMineral("aluminum")) + minerals.add(makeImmersiveEngineeringOreMineral("lead")) + minerals.add(makeImmersiveEngineeringOreMineral("nickel")) + minerals.add(makeImmersiveEngineeringOreMineral("silver")) + minerals.add(makeImmersiveEngineeringOreMineral("uranium")) -# Railcraft Ores -C.add(Mineral("saltpeter", [ - Replacement("sand", f"{RC}:saltpeter_ore"), - Replacement("sandstone", f"{RC}:saltpeter_ore"), -])) -C.add(makeRailcraftOreMineral("sulfur")) -C.add(makeRailcraftOreMineral("tin")) -C.add(makeRailcraftOreMineral("zinc")) + # Railcraft Ores + minerals.add(Mineral("saltpeter", [ + Replacement("sand", f"{RC}:saltpeter_ore"), + Replacement("sandstone", f"{RC}:saltpeter_ore"), + ])) + minerals.add(makeRailcraftOreMineral("sulfur")) + minerals.add(makeRailcraftOreMineral("tin")) + minerals.add(makeRailcraftOreMineral("zinc")) diff --git a/mcpacker/pack/mysteriousisland/mobcatalog.py b/mcpacker/pack/mysteriousisland/mobcatalog.py index e18d8a9..178a12b 100644 --- a/mcpacker/pack/mysteriousisland/mobcatalog.py +++ b/mcpacker/pack/mysteriousisland/mobcatalog.py @@ -1,8 +1,9 @@ from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF -from mcpacker.model.core.fauna.mob import Mob -from mcpacker.model.core.fauna.mobcatalog import MobCatalog -from mcpacker.model.core.fauna.mobplacement import MobPlacement -from mcpacker.model.core.habitat import Habitat +from mcpacker.model.core.fauna.mob import Mob +from mcpacker.model.core.fauna.mobcatalog import MobCatalog +from mcpacker.model.core.fauna.mobplacement import MobPlacement +from mcpacker.model.core.habitat import Habitat +from mcpacker.model.modpack import ModPack import mcpacker.model.core.altitude as AL import mcpacker.model.core.ecology.flora as FL @@ -20,165 +21,357 @@ import mcpacker.model.core.season as SE # Constants ######################################################################################## -CATALOG = MobCatalog([ - MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL), - Habitat( - altitude = AL.LOWLANDS, - biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]), - seasons = SE.SUMMER, - group = GR.merge(GR.SOLO, GR.PAIR), - scarcity = SC.COMMON - ).derive( - altitude = AL.UPLANDS, scarcity = SC.SPARSE, - ).derive( - altitude = AL.LOWLANDS, seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON, - ).derive( - altitude = AL.UPLANDS, scarcity = SC.UNUSUAL, +def addMobs(pack:ModPack): + mobs = pack.world.mobs + + mobs.add( + MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL), + Habitat( + altitude = AL.LOWLANDS, + biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]), + seasons = SE.SUMMER, + group = GR.merge(GR.SOLO, GR.PAIR), + scarcity = SC.COMMON + ).derive( + altitude = AL.UPLANDS, scarcity = SC.SPARSE, + ).derive( + altitude = AL.LOWLANDS, seasons = SE.exclude(SE.SUMMER), scarcity = SC.UNCOMMON, + ).derive( + altitude = AL.UPLANDS, scarcity = SC.UNUSUAL, + ) ) - ), - MobPlacement(Mob("black_bear", "bearminimum:black_bear"), - Habitat( - altitude = AL.span(AL.LOWLANDS, AL.ALPINE), - biomeFilter = BF([HE.TEMPERATE, FL.FOREST]), - seasons = SE.AUTUMN, - group = GR.merge(GR.SOLO, GR.FAMILY), - scarcity = SC.UNCOMMON, - ).derive( - seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.SPARSE - ).derive( - seasons = SE.WINTER, scarcity = SC.UNUSUAL - ).derive( - biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), - seasons = SE.AUTUMN, - scarcity = SC.SPARSE - ).derive( - seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL - ).derive( - seasons = SE.WINTER, scarcity = SC.RARE + ) + + mobs.add( + MobPlacement(Mob("black_bear", "bearminimum:black_bear"), + Habitat( + altitude = AL.span(AL.LOWLANDS, AL.ALPINE), + biomeFilter = BF([HE.TEMPERATE, FL.FOREST]), + seasons = SE.AUTUMN, + group = GR.merge(GR.SOLO, GR.FAMILY), + scarcity = SC.UNCOMMON, + ).derive( + seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.SPARSE + ).derive( + seasons = SE.WINTER, scarcity = SC.UNUSUAL + ).derive( + biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), + seasons = SE.AUTUMN, + scarcity = SC.SPARSE + ).derive( + seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL + ).derive( + seasons = SE.WINTER, scarcity = SC.RARE + ) ) - ), - MobPlacement(Mob("blaze", "minecraft:blaze"), - Habitat( - altitude = AL.PLUTONIC, - location = LO.CAVE, - group = GR.SOLO, - scarcity = SC.UNCOMMON + ) + + mobs.add( + MobPlacement(Mob("blaze", "minecraft:blaze"), + Habitat( + altitude = AL.PLUTONIC, + location = LO.CAVE, + group = GR.SOLO, + scarcity = SC.UNCOMMON + ) ) - ), - MobPlacement(Mob("bogged", "minecraft:bogged")), - MobPlacement(Mob("brown_bear", "bearminimum:brown_bear"), - Habitat( - altitude = AL.span(AL.LOWLANDS, AL.ALPINE), - biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), - seasons = SE.AUTUMN, - group = GR.SOLO, - scarcity = SC.SPARSE - ).derive( - seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL - ).derive( - seasons = SE.WINTER, scarcity = SC.RARE + ) + + mobs.add( + MobPlacement(Mob("bogged", "minecraft:bogged")) + ) + + mobs.add( + MobPlacement(Mob("brown_bear", "bearminimum:brown_bear"), + Habitat( + altitude = AL.span(AL.LOWLANDS, AL.ALPINE), + biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), + seasons = SE.AUTUMN, + group = GR.SOLO, + scarcity = SC.SPARSE + ).derive( + seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL + ).derive( + seasons = SE.WINTER, scarcity = SC.RARE + ) ) - ), - MobPlacement(Mob("bulwark", "immersiveengineering:bulwark")), - MobPlacement(Mob("camel", "minecraft:camel", AC.CREPUSCULAR), - Habitat( - altitude = AL.span(AL.DUNES, AL.LOWLANDS), - biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]), - seasons = SE.DRY, - group = GR.FAMILY, - scarcity = SC.UNUSUAL, - ).derive( - seasons = SE.WET, scarcity = SC.RARE + ) + + mobs.add( + MobPlacement(Mob("bulwark", "immersiveengineering:bulwark")) + ) + + mobs.add( + MobPlacement(Mob("camel", "minecraft:camel", AC.CREPUSCULAR), + Habitat( + altitude = AL.span(AL.DUNES, AL.LOWLANDS), + biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]), + seasons = SE.DRY, + group = GR.FAMILY, + scarcity = SC.UNUSUAL, + ).derive( + seasons = SE.WET, scarcity = SC.RARE + ) ) - ), - MobPlacement(Mob("cat", "minecraft:cat")), - MobPlacement(Mob("cave_spider", "minecraft:cave_spider"), - Habitat( - altitude = AL.span(AL.OVERBURDEN, AL.HILLS), - location = LO.CAVE, - group = GR.SOLO, - scarcity = SC.UNCOMMON + ) + + mobs.add( + MobPlacement(Mob("cat", "minecraft:cat")) + ) + + mobs.add( + MobPlacement(Mob("cave_spider", "minecraft:cave_spider"), + Habitat( + altitude = AL.span(AL.OVERBURDEN, AL.HILLS), + location = LO.CAVE, + group = GR.SOLO, + scarcity = SC.UNCOMMON + ) ) - ), - MobPlacement(Mob("chameleon", "cold_sweat:chameleon"), - Habitat( - altitude = AL.span(AL.DUNES, AL.UPLANDS), - biomeFilter = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]), - seasons = SE.WET, - group = GR.merge(GR.SOLO, GR.FAMILY), - scarcity = SC.COMMON, - ).derive( - seasons = SE.DRY, scarcity = SC.UNCOMMON, - ).derive( - biomeFilter = BF([HE.TROPICAL, HU.WET, FL.CLEARING]), - seasons = SE.WET, - scarcity = SC.UNCOMMON - ).derive( - seasons = SE.DRY, scarcity = SC.SPARSE, + ) + + mobs.add( + MobPlacement(Mob("chameleon", "cold_sweat:chameleon"), + Habitat( + altitude = AL.span(AL.DUNES, AL.UPLANDS), + biomeFilter = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]), + seasons = SE.WET, + group = GR.merge(GR.SOLO, GR.FAMILY), + scarcity = SC.COMMON, + ).derive( + seasons = SE.DRY, scarcity = SC.UNCOMMON, + ).derive( + biomeFilter = BF([HE.TROPICAL, HU.WET, FL.CLEARING]), + seasons = SE.WET, + scarcity = SC.UNCOMMON + ).derive( + seasons = SE.DRY, scarcity = SC.SPARSE, + ) ) - ), - MobPlacement(Mob("chicken", "minecraft:chicken"), - Habitat( - altitude = AL.span(AL.LOWLANDS, AL.UPLANDS), - biomeFilter = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]), - seasons = SE.SUMMER, - group = GR.TROUP, - scarcity = SC.COMMON, - ).derive( - seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON + ) + + mobs.add( + MobPlacement(Mob("chicken", "minecraft:chicken"), + Habitat( + altitude = AL.span(AL.LOWLANDS, AL.UPLANDS), + biomeFilter = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]), + seasons = SE.SUMMER, + group = GR.TROUP, + scarcity = SC.COMMON, + ).derive( + seasons = SE.exclude(SE.SUMMER), scarcity = SC.UNCOMMON + ) ) - ), - MobPlacement(Mob("cod", "minecraft:cod")), - MobPlacement(Mob("commando", "immersiveengineering:commando")), - MobPlacement(Mob("cow", "minecraft:cow")), - MobPlacement(Mob("crab", "crabbersdelight:crab")), - MobPlacement(Mob("creeper", "minecraft:creeper")), - MobPlacement(Mob("dolphin", "minecraft:dolphin")), - MobPlacement(Mob("donkey", "minecraft:donkey")), - MobPlacement(Mob("drowned", "minecraft:drowned")), - MobPlacement(Mob("enderman", "minecraft:enderman")), - MobPlacement(Mob("evoker", "minecraft:evoker")), - MobPlacement(Mob("fox", "minecraft:fox")), - MobPlacement(Mob("frog", "minecraft:frog")), - MobPlacement(Mob("fusilier", "immersiveengineering:fusilier")), - MobPlacement(Mob("glow_squid", "minecraft:glow_squid")), - MobPlacement(Mob("goat", "minecraft:goat")), - MobPlacement(Mob("hoglin", "minecraft:hoglin")), - MobPlacement(Mob("horse", "minecraft:horse")), - MobPlacement(Mob("husk", "minecraft:husk")), - MobPlacement(Mob("llama", "minecraft:llama")), - MobPlacement(Mob("magma_cube", "minecraft:magma_cube")), - MobPlacement(Mob("mooshroom", "minecraft:mooshroom")), - MobPlacement(Mob("mule", "minecraft:mule")), - MobPlacement(Mob("ocelot", "minecraft:ocelot")), - MobPlacement(Mob("panda", "minecraft:panda")), - MobPlacement(Mob("parrot", "minecraft:parrot")), - MobPlacement(Mob("pig", "minecraft:pig")), - MobPlacement(Mob("pillager", "minecraft:pillager")), - MobPlacement(Mob("polar_bear", "minecraft:polar_bear")), - MobPlacement(Mob("pufferfish", "minecraft:pufferfish")), - MobPlacement(Mob("rabbit", "minecraft:rabbit")), - MobPlacement(Mob("raccoon", "animalplus:raccoon")), - MobPlacement(Mob("ravager", "minecraft:ravager")), - MobPlacement(Mob("red_panda", "animalplus:red_panda")), - MobPlacement(Mob("salmon", "minecraft:salmon")), - MobPlacement(Mob("sheep", "minecraft:sheep")), - MobPlacement(Mob("skeleton", "minecraft:skeleton")), - MobPlacement(Mob("slime", "minecraft:slime")), - MobPlacement(Mob("spider", "minecraft:spider")), - MobPlacement(Mob("squid", "minecraft:squid")), - MobPlacement(Mob("tropical_fish", "minecraft:tropical_fish")), - MobPlacement(Mob("turtle", "minecraft:turtle")), - MobPlacement(Mob("vex", "minecraft:vex")), - MobPlacement(Mob("villager", "minecraft:villager")), - MobPlacement(Mob("vindicator", "minecraft:vindicator")), - MobPlacement(Mob("wandering_trader", "minecraft:wandering_trader")), - MobPlacement(Mob("warden", "minecraft:warden")), - MobPlacement(Mob("witch", "minecraft:witch")), - MobPlacement(Mob("wither_skeleton", "minecraft:wither_skeleton")), - MobPlacement(Mob("wither", "minecraft:wither")), - MobPlacement(Mob("wolf", "minecraft:wolf")), - MobPlacement(Mob("zoglin", "minecraft:zoglin")), - MobPlacement(Mob("zombie_villager", "minecraft:zombie_villager")), - MobPlacement(Mob("zombie", "minecraft:zombie")), -]) + ) + + mobs.add( + MobPlacement(Mob("cod", "minecraft:cod")) + ) + + mobs.add( + MobPlacement(Mob("commando", "immersiveengineering:commando")) + ) + + mobs.add( + MobPlacement(Mob("cow", "minecraft:cow")) + ) + + mobs.add( + MobPlacement(Mob("crab", "crabbersdelight:crab")) + ) + + mobs.add( + MobPlacement(Mob("creeper", "minecraft:creeper")) + ) + + mobs.add( + MobPlacement(Mob("dolphin", "minecraft:dolphin")) + ) + + mobs.add( + MobPlacement(Mob("donkey", "minecraft:donkey")) + ) + + mobs.add( + MobPlacement(Mob("drowned", "minecraft:drowned")) + ) + + mobs.add( + MobPlacement(Mob("enderman", "minecraft:enderman")) + ) + + mobs.add( + MobPlacement(Mob("evoker", "minecraft:evoker")) + ) + + mobs.add( + MobPlacement(Mob("fox", "minecraft:fox")) + ) + + mobs.add( + MobPlacement(Mob("frog", "minecraft:frog")) + ) + + mobs.add( + MobPlacement(Mob("fusilier", "immersiveengineering:fusilier")) + ) + + mobs.add( + MobPlacement(Mob("glow_squid", "minecraft:glow_squid")) + ) + + mobs.add( + MobPlacement(Mob("goat", "minecraft:goat")) + ) + + mobs.add( + MobPlacement(Mob("hoglin", "minecraft:hoglin")) + ) + + mobs.add( + MobPlacement(Mob("horse", "minecraft:horse")) + ) + + mobs.add( + MobPlacement(Mob("husk", "minecraft:husk")) + ) + + mobs.add( + MobPlacement(Mob("llama", "minecraft:llama")) + ) + + mobs.add( + MobPlacement(Mob("magma_cube", "minecraft:magma_cube")) + ) + + mobs.add( + MobPlacement(Mob("mooshroom", "minecraft:mooshroom")) + ) + + mobs.add( + MobPlacement(Mob("mule", "minecraft:mule")) + ) + + mobs.add( + MobPlacement(Mob("ocelot", "minecraft:ocelot")) + ) + + mobs.add( + MobPlacement(Mob("panda", "minecraft:panda")) + ) + + mobs.add( + MobPlacement(Mob("parrot", "minecraft:parrot")) + ) + + mobs.add( + MobPlacement(Mob("pig", "minecraft:pig")) + ) + + mobs.add( + MobPlacement(Mob("pillager", "minecraft:pillager")) + ) + + mobs.add( + MobPlacement(Mob("polar_bear", "minecraft:polar_bear")) + ) + + mobs.add( + MobPlacement(Mob("pufferfish", "minecraft:pufferfish")) + ) + + mobs.add( + MobPlacement(Mob("rabbit", "minecraft:rabbit")) + ) + + mobs.add( + MobPlacement(Mob("raccoon", "animalplus:raccoon")) + ) + + mobs.add( + MobPlacement(Mob("ravager", "minecraft:ravager")) + ) + + mobs.add( + MobPlacement(Mob("red_panda", "animalplus:red_panda")) + ) + + mobs.add( + MobPlacement(Mob("salmon", "minecraft:salmon")) + ) + + mobs.add( + MobPlacement(Mob("sheep", "minecraft:sheep")) + ) + + mobs.add( + MobPlacement(Mob("skeleton", "minecraft:skeleton")) + ) + + mobs.add( + MobPlacement(Mob("slime", "minecraft:slime")) + ) + + mobs.add( + MobPlacement(Mob("spider", "minecraft:spider")) + ) + + mobs.add( + MobPlacement(Mob("squid", "minecraft:squid")) + ) + + mobs.add( + MobPlacement(Mob("tropical_fish", "minecraft:tropical_fish")) + ) + + mobs.add( + MobPlacement(Mob("turtle", "minecraft:turtle")) + ) + + mobs.add( + MobPlacement(Mob("vex", "minecraft:vex")) + ) + + mobs.add( + MobPlacement(Mob("villager", "minecraft:villager")) + ) + + mobs.add( + MobPlacement(Mob("vindicator", "minecraft:vindicator")) + ) + + mobs.add( + MobPlacement(Mob("wandering_trader", "minecraft:wandering_trader")) + ) + + mobs.add( + MobPlacement(Mob("warden", "minecraft:warden")) + ) + + mobs.add( + MobPlacement(Mob("witch", "minecraft:witch")) + ) + + mobs.add( + MobPlacement(Mob("wither_skeleton", "minecraft:wither_skeleton")) + ) + + mobs.add( + MobPlacement(Mob("wither", "minecraft:wither")) + ) + + mobs.add( + MobPlacement(Mob("wolf", "minecraft:wolf")) + ) + + mobs.add( + MobPlacement(Mob("zoglin", "minecraft:zoglin")) + ) + + mobs.add( + MobPlacement(Mob("zombie_villager", "minecraft:zombie_villager")) + ) + + mobs.add( + MobPlacement(Mob("zombie", "minecraft:zombie")) + ) diff --git a/mcpacker/pack/mysteriousisland/modpack.py b/mcpacker/pack/mysteriousisland/modpack.py new file mode 100644 index 0000000..fb7488b --- /dev/null +++ b/mcpacker/pack/mysteriousisland/modpack.py @@ -0,0 +1,27 @@ +from mcpacker.model.modpack import ModPack +from mcpacker.pack.mysteriousisland.biomecatalog import addBiomes +from mcpacker.pack.mysteriousisland.blockcatalog import addBlocks +from mcpacker.pack.mysteriousisland.depositcatalog import addDeposits +from mcpacker.pack.mysteriousisland.itemcatalog import addItems +from mcpacker.pack.mysteriousisland.mineralcatalog import addMinerals +from mcpacker.pack.mysteriousisland.mobcatalog import addMobs +from mcpacker.pack.mysteriousisland.datapack import addDataPack +from mcpacker.pack.mysteriousisland.resourcepack import addResourcePack + + +# Constants ######################################################################################## + +def buildModPack(): + pack = ModPack("mysteriousisland") + + # Order is significant as layers have dependencies + pack.augment(addBiomes) + pack.augment(addItems) + pack.augment(addBlocks) + pack.augment(addMinerals) + pack.augment(addDeposits) + pack.augment(addMobs) + pack.augment(addResourcePack) + pack.augment(addDataPack) + + return pack diff --git a/mcpacker/pack/mysteriousisland/modpack_test.py b/mcpacker/pack/mysteriousisland/modpack_test.py new file mode 100644 index 0000000..6b71165 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/modpack_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.modpack + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/resourcepack.py b/mcpacker/pack/mysteriousisland/resourcepack.py new file mode 100644 index 0000000..d4c81c9 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/resourcepack.py @@ -0,0 +1,8 @@ +from mcpacker.model.modpack import ModPack +from mcpacker.model.resourcepack import ResourcePack + + +# Functions ######################################################################################## + +def addResourcePack(modPack:ModPack): + pass diff --git a/mcpacker/pack/mysteriousisland/resourcepack_test.py b/mcpacker/pack/mysteriousisland/resourcepack_test.py new file mode 100644 index 0000000..e47b200 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/resourcepack_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.resourcepack + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/runner.py b/mcpacker/pack/mysteriousisland/runner.py index e07e2f6..8a32479 100644 --- a/mcpacker/pack/mysteriousisland/runner.py +++ b/mcpacker/pack/mysteriousisland/runner.py @@ -1,33 +1,10 @@ -from mcpacker.emit.markdown.biomereport import BiomeReport -from mcpacker.emit.markdown.mineralreport import MineralReport -from mcpacker.emit.markdown.mobreport import MobReport -from mcpacker.emit.markdown.reportwriter import ReportWriter -from mcpacker.pack.mysteriousisland.world import WORLD -from mcpacker.ui.runner import Runner as BaseRunner +from mcpacker.pack.mysteriousisland.modpack import buildModPack +from mcpacker.ui.runner import Runner import sys -# Constants ######################################################################################## - -REPORT_PATH = "./output/markdown/mysteriousisland" - - -# Class ############################################################################################ - -class Runner(BaseRunner): - - def _command_writeReports(self): - writer = ReportWriter([ - BiomeReport(self.world), - MineralReport(self.world), - MobReport(self.world), - ]) - writer.write(REPORT_PATH) - - - # Script ########################################################################################### if __name__ == "__main__": - Runner(WORLD).run(sys.argv) + Runner(buildModPack()).run(sys.argv) diff --git a/mcpacker/pack/mysteriousisland/runner_test.py b/mcpacker/pack/mysteriousisland/runner_test.py new file mode 100644 index 0000000..2cf35e7 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/runner_test.py @@ -0,0 +1,7 @@ +import mcpacker.pack.mysteriousisland.runner + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/pack/mysteriousisland/world.py b/mcpacker/pack/mysteriousisland/world.py deleted file mode 100644 index 5e22509..0000000 --- a/mcpacker/pack/mysteriousisland/world.py +++ /dev/null @@ -1,10 +0,0 @@ -from mcpacker.model.core.world import World -from mcpacker.pack.mysteriousisland.biomecatalog import CATALOG as biomeCatalog -from mcpacker.pack.mysteriousisland.depositcatalog import CATALOG as depositCatalog -from mcpacker.pack.mysteriousisland.mineralcatalog import CATALOG as mineralCatalog -from mcpacker.pack.mysteriousisland.mobcatalog import CATALOG as mobCatalog - - -# Constants ######################################################################################## - -WORLD = World(biomeCatalog, depositCatalog, mineralCatalog, mobCatalog) diff --git a/mcpacker/ui/runner.py b/mcpacker/ui/runner.py index 60d831e..b923633 100644 --- a/mcpacker/ui/runner.py +++ b/mcpacker/ui/runner.py @@ -1,15 +1,25 @@ -from mcpacker.model.core.world import World +from mcpacker.emit.markdown.reportwriter import ReportWriter +from mcpacker.emit.markdown.biomereport import BiomeReport +from mcpacker.emit.markdown.mineralreport import MineralReport +from mcpacker.emit.markdown.mobreport import MobReport +from mcpacker.model.modpack import ModPack import inspect +import os import sys +# Constants ######################################################################################## + +OUTPUT_PATH = "output" + + # Class ############################################################################################ class Runner: - def __init__(self, world:World): - self.world = world + def __init__(self, pack:ModPack|None=None): + self.pack = pack or ModPack("untitled") def abort(self, message:str, status:int=-1): print(message) @@ -26,3 +36,13 @@ class Runner: sys.exit(0) abort("No command named: " + argv[1]) + + # Commands ################################################################# + + def _command_writeReports(self): + writer = ReportWriter([ + BiomeReport(self.pack), + MineralReport(self.pack), + MobReport(self.pack), + ]) + writer.write(os.path.join(OUTPUT_PATH, self.pack.name, "markdown")) diff --git a/mcpacker/ui/runner_test.py b/mcpacker/ui/runner_test.py index 37faf31..e29eb96 100644 --- a/mcpacker/ui/runner_test.py +++ b/mcpacker/ui/runner_test.py @@ -1,4 +1,4 @@ -from mcpacker.ui.runner import Runner +import mcpacker.ui.runner # Tests ############################################################################################