From 5f15dac9e9c069754d2842ab11774e1a49ba0f0a Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Fri, 10 Oct 2025 19:43:28 -0600 Subject: [PATCH] Add static asssets capability --- mcpacker/model/blockfactory.py | 26 ++++ mcpacker/model/core/resourceid.py | 7 +- mcpacker/model/datapack/__init__.py | 8 +- mcpacker/model/resourcepack/__init__.py | 19 ++- mcpacker/model/resourcepack/blockstate.py | 25 ++++ mcpacker/model/resourcepack/model.py | 13 ++ mcpacker/model/resourcepack/modresource.py | 14 +- mcpacker/model/resourcepack/variant.py | 13 ++ mcpacker/model/resourcepack/variant_test.py | 17 +++ .../pack/mysteriousisland/addmobspawns.py | 4 +- mcpacker/pack/mysteriousisland/modpack.py | 2 + .../structure/deposit/bed_loam_marker.nbt} | Bin .../structure/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 .../structure/deposit/greisen_tin_marker.nbt} | Bin .../deposit/hydrothermal_emerald_marker.nbt} | Bin .../deposit/laterite_aluminum_marker.nbt} | Bin .../deposit/lavatube_diamond_marker.nbt} | Bin .../structure/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 .../structure/deposit/skarnlapis_marker.nbt} | Bin .../required_data/modpack/pack.mcmeta | 6 + .../kubejs/textures/block}/peat_block.png | Bin .../kubejs/textures/item}/peat_chunk.png | Bin mcpacker/pack/testpack/static/test.md | 1 + mcpacker/ui/runner.py | 14 +- mcpacker/ui/runner_test.py | 19 +-- mcpacker/write/compositewriter.py | 37 +++++ mcpacker/write/incontrol/spawnerwriter.py | 3 +- mcpacker/write/locator.py | 137 ++++++++++++++++++ mcpacker/write/locator_test.py | 56 +++++++ mcpacker/write/markdown/mobspawnreport.py | 2 +- .../write/resourcepack/blockstatewriter.py | 12 ++ mcpacker/write/staticwriter.py | 23 +++ mcpacker/write/writer.py | 40 +---- mcpacker/write/writer_test.py | 30 ++++ 43 files changed, 458 insertions(+), 70 deletions(-) create mode 100644 mcpacker/model/blockfactory.py create mode 100644 mcpacker/model/resourcepack/blockstate.py create mode 100644 mcpacker/model/resourcepack/model.py create mode 100644 mcpacker/model/resourcepack/variant.py create mode 100644 mcpacker/model/resourcepack/variant_test.py rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_bed_loam_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/bed_loam_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_bif_iron_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/bif_iron_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_epithermal_silver_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/epithermal_silver_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_evaporite_nitrate_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_nitrate_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_evaporite_salt_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_salt_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_fulmarole_sulfur_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/fulmarole_sulfur_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_geode_amethyst_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/geode_amethyst_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_greisen_tin_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/greisen_tin_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_hydrothermal_emerald_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/hydrothermal_emerald_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_laterite_aluminum_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/laterite_aluminum_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_lavatube_diamond_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/lavatube_diamond_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_mvt_lead_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/mvt_lead_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_porphyry_copper_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/porphyry_copper_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_seam_bituminouscoal_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_bituminouscoal_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_seam_peatcoal_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_peatcoal_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_sedimentary_iron_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/sedimentary_iron_marker.nbt} (100%) rename mcpacker/pack/mysteriousisland/{assets/nbts/deposit_skarnlapis_marker.nbt => static/global_packs/required_data/modpack/data/modpack/structure/deposit/skarnlapis_marker.nbt} (100%) create mode 100644 mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/pack.mcmeta rename mcpacker/pack/mysteriousisland/{assets/images => static/resourcepack/assets/kubejs/textures/block}/peat_block.png (100%) rename mcpacker/pack/mysteriousisland/{assets/images => static/resourcepack/assets/kubejs/textures/item}/peat_chunk.png (100%) create mode 100644 mcpacker/pack/testpack/static/test.md create mode 100644 mcpacker/write/compositewriter.py create mode 100644 mcpacker/write/locator.py create mode 100644 mcpacker/write/locator_test.py create mode 100644 mcpacker/write/resourcepack/blockstatewriter.py create mode 100644 mcpacker/write/staticwriter.py create mode 100644 mcpacker/write/writer_test.py diff --git a/mcpacker/model/blockfactory.py b/mcpacker/model/blockfactory.py new file mode 100644 index 0000000..2f63a12 --- /dev/null +++ b/mcpacker/model/blockfactory.py @@ -0,0 +1,26 @@ +from mcpacker.model.resourcepack.blockstate import BlockState +from mcpacker.model.resourcepack.variant import Variant +from mcpacker.model.resourcepack.model import Model +from mcpacker.model.modpack import ModPack +from mcpacker.model.core.resourceid import ResourceId + + +# Class ############################################################################################ + +class BlockFactory: + + def __init__(self, pack:ModPack): + self.pack = pack + + def makeBasicBlock(self, name:str, gameId:ResourceId): + basicCubeModelId = ResourceId.parse("block/cube_all") + textureId = ResourceId.parse(f"{gameId.mod}:block/{gameId.name}") + blockId = ResourceId.parse(f"{gameId.mod}:block/{gameId.name}") + + resource = self.pack.resourcePack.get(gameId.mod) + resource.blockModels.append(Model(basicCubeModelId, {"all": textureId})) + resource.itemModels.append(Model(blockId)) + resource.blockStates.append(BlockState(Variant(blockId))) + + data = self.pack.dataPack.get(gameId.mod) + diff --git a/mcpacker/model/core/resourceid.py b/mcpacker/model/core/resourceid.py index 7872e65..ced286a 100644 --- a/mcpacker/model/core/resourceid.py +++ b/mcpacker/model/core/resourceid.py @@ -12,11 +12,14 @@ class ResourceId: return str(resourceId) @staticmethod - def canonical(text:str): + def canonical(text:str) -> str: return str(ResourceId.parse(text)) @staticmethod - def parse(text:str): + def parse(text:"ResourceId|str") -> "ResourceId": + if isinstance(text, ResourceId): + return text + isTag = False if text.startswith("#"): isTag = True diff --git a/mcpacker/model/datapack/__init__.py b/mcpacker/model/datapack/__init__.py index 351d994..2a2cf20 100644 --- a/mcpacker/model/datapack/__init__.py +++ b/mcpacker/model/datapack/__init__.py @@ -21,8 +21,12 @@ class DataPack: self._mods[mod.name] = mod return self - def get(self, name:str) -> ModData|None: - return self._mods.get(name, None) + def get(self, name:str) -> ModData: + result = self._mods.get(name, None) + if not result: + result = self._mods[name] = ModData(name) + + return result @property def defaultMod(self) -> ModData|None: diff --git a/mcpacker/model/resourcepack/__init__.py b/mcpacker/model/resourcepack/__init__.py index 221113b..8e0387c 100644 --- a/mcpacker/model/resourcepack/__init__.py +++ b/mcpacker/model/resourcepack/__init__.py @@ -1,4 +1,5 @@ from collections.abc import Iterable +from collections.abc import Iterator from mcpacker.model.resourcepack.modresource import ModResource @@ -18,11 +19,15 @@ class ResourcePack: if not self._defaultMod: self._defaultMod = mod - self._mods[mod.name] = mod + self._mods[mod.mod] = mod return self - def get(self, name:str) -> ModResource|None: - return self._mods.get(name, None) + def get(self, name:str) -> ModResource: + result = self._mods.get(name, None) + if not result: + result = self._mods[name] = ModResource(name) + + return result @property def defaultMod(self) -> ModResource|None: @@ -31,11 +36,15 @@ class ResourcePack: @defaultMod.setter def defaultMod(self, mod:ModResource): if mod: - existingMod = self.get(mod.name) + existingMod = self.get(mod.mod) if not existingMod: self.add(mod) elif existingMod != mod: - raise Exception(f"Resourcepack already has a mod named {mod.name}") + raise Exception(f"Resourcepack already has a mod named {mod.mod}") self._defaultMod = mod + @property + def mods(self) -> Iterator[ModResource]: + for mod in self._mods.values(): + yield mod diff --git a/mcpacker/model/resourcepack/blockstate.py b/mcpacker/model/resourcepack/blockstate.py new file mode 100644 index 0000000..6515e6a --- /dev/null +++ b/mcpacker/model/resourcepack/blockstate.py @@ -0,0 +1,25 @@ +from mcpacker.model.resourcepack.variant import Variant + + +# Class ############################################################################################ + +class BlockState: + """ + A mapping between a block and the model(s) used to represent it in game. + + see: https://minecraft.wiki/w/Tutorial:Models#Block_states + """ + + def __init__(self, defaultVariant:Variant|None=None): + self.variants:dict[str,Variant] = {} + + if defaultVariant: + self.defaultVariant = defaultVariant + + @property + def defaultVariant(self) -> Variant|None: + return self.variants.get("", None) + + @defaultVariant.setter + def defaultVariant(self, value:Variant): + self.variants[""] = value diff --git a/mcpacker/model/resourcepack/model.py b/mcpacker/model/resourcepack/model.py new file mode 100644 index 0000000..376e512 --- /dev/null +++ b/mcpacker/model/resourcepack/model.py @@ -0,0 +1,13 @@ +from mcpacker.model.core.resourceid import ResourceId + + +# Class ############################################################################################ + +class Model: + """ + Describes how to create a 2D or 3D representation of an object in the game + """ + + def __init__(self, parent:ResourceId, textures:dict[str,ResourceId]|None=None): + self.parent = parent + self.textures = {k:v for k,v in (textures or {}).items()} diff --git a/mcpacker/model/resourcepack/modresource.py b/mcpacker/model/resourcepack/modresource.py index 5c866e4..a2f0662 100644 --- a/mcpacker/model/resourcepack/modresource.py +++ b/mcpacker/model/resourcepack/modresource.py @@ -1,9 +1,13 @@ +from mcpacker.model.resourcepack.blockstate import BlockState +from mcpacker.model.resourcepack.model import Model + + # Class ############################################################################################ class ModResource: - def __init__(self, name:str): - self.name = name - self.blockStates:list[str] = [] - self.models:list[str] = [] - self.textures:list[str] = [] + def __init__(self, mod:str): + self.mod = mod + self.blockStates:list[BlockState] = [] + self.blockModels:list[Model] = [] + self.itemModels:list[Model] = [] diff --git a/mcpacker/model/resourcepack/variant.py b/mcpacker/model/resourcepack/variant.py new file mode 100644 index 0000000..6b9609a --- /dev/null +++ b/mcpacker/model/resourcepack/variant.py @@ -0,0 +1,13 @@ +from mcpacker.model.core.resourceid import ResourceId + + +# Class ############################################################################################ + +class Variant: + + def __init__(self, model:ResourceId|str, x:int=0, y:int=0, uvlock:bool=False, weight:int=1): + self.model = ResourceId.parse(model) + self.x = x + self.y = y + self.uvlock = uvlock + self.weight = weight diff --git a/mcpacker/model/resourcepack/variant_test.py b/mcpacker/model/resourcepack/variant_test.py new file mode 100644 index 0000000..863a54d --- /dev/null +++ b/mcpacker/model/resourcepack/variant_test.py @@ -0,0 +1,17 @@ +from mcpacker.model.resourcepack.variant import Variant +from pytest import fixture + + +# Fixtures ######################################################################################### + +@fixture(name="variant") +def createVariant(): + yield Variant("grass", 90, 180, True, 10) + + +# Tests ############################################################################################ + +def test_variant(variant:Variant): + assert str(variant.model) == "minecraft:grass" + assert variant.x == 90 + assert variant.uvlock == True diff --git a/mcpacker/pack/mysteriousisland/addmobspawns.py b/mcpacker/pack/mysteriousisland/addmobspawns.py index d1d0729..7ba2f71 100644 --- a/mcpacker/pack/mysteriousisland/addmobspawns.py +++ b/mcpacker/pack/mysteriousisland/addmobspawns.py @@ -21,7 +21,7 @@ import mcpacker.model.core.season as SE # Constants ######################################################################################## -def addMobs(pack:ModPack): +def addMobSpawns(pack:ModPack): mobs = pack.world.mobs spawns = pack.world.mobSpawns @@ -202,7 +202,7 @@ def addMobs(pack:ModPack): ).derive( altitude = AL.LOWLANDS, seasons = [SE.AUTUMN, SE.WINTER], - groups = GR.TROUP, + group = GR.TROUP, scarcity = SC.SPARSE, ) ) diff --git a/mcpacker/pack/mysteriousisland/modpack.py b/mcpacker/pack/mysteriousisland/modpack.py index 711f80d..38110f0 100644 --- a/mcpacker/pack/mysteriousisland/modpack.py +++ b/mcpacker/pack/mysteriousisland/modpack.py @@ -6,6 +6,7 @@ from mcpacker.pack.mysteriousisland.adddeposits import addDeposits from mcpacker.pack.mysteriousisland.additems import addItems from mcpacker.pack.mysteriousisland.addminerals import addMinerals from mcpacker.pack.mysteriousisland.addmobs import addMobs +from mcpacker.pack.mysteriousisland.addmobspawns import addMobSpawns from mcpacker.pack.mysteriousisland.addresourcepack import addResourcePack @@ -21,6 +22,7 @@ def buildModPack(): pack.augment(addMinerals) pack.augment(addDeposits) pack.augment(addMobs) + pack.augment(addMobSpawns) pack.augment(addResourcePack) pack.augment(addDataPack) diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_bed_loam_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/bed_loam_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_bed_loam_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/bed_loam_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_bif_iron_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/bif_iron_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_bif_iron_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/bif_iron_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_epithermal_silver_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/epithermal_silver_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_epithermal_silver_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/epithermal_silver_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_nitrate_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_nitrate_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_nitrate_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_nitrate_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_salt_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_salt_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_evaporite_salt_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/evaporite_salt_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_fulmarole_sulfur_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/fulmarole_sulfur_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_fulmarole_sulfur_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/fulmarole_sulfur_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_geode_amethyst_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/geode_amethyst_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_geode_amethyst_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/geode_amethyst_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_greisen_tin_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/greisen_tin_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_greisen_tin_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/greisen_tin_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_hydrothermal_emerald_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/hydrothermal_emerald_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_hydrothermal_emerald_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/hydrothermal_emerald_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_laterite_aluminum_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/laterite_aluminum_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_laterite_aluminum_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/laterite_aluminum_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_lavatube_diamond_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/lavatube_diamond_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_lavatube_diamond_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/lavatube_diamond_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_mvt_lead_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/mvt_lead_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_mvt_lead_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/mvt_lead_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_porphyry_copper_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/porphyry_copper_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_porphyry_copper_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/porphyry_copper_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_bituminouscoal_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_bituminouscoal_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_bituminouscoal_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_bituminouscoal_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_peatcoal_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_peatcoal_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_seam_peatcoal_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/seam_peatcoal_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_sedimentary_iron_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/sedimentary_iron_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_sedimentary_iron_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/sedimentary_iron_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/assets/nbts/deposit_skarnlapis_marker.nbt b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/skarnlapis_marker.nbt similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/nbts/deposit_skarnlapis_marker.nbt rename to mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/data/modpack/structure/deposit/skarnlapis_marker.nbt diff --git a/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/pack.mcmeta b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/pack.mcmeta new file mode 100644 index 0000000..591fe28 --- /dev/null +++ b/mcpacker/pack/mysteriousisland/static/global_packs/required_data/modpack/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 48, + "description": "modpack overrides for Mysterious Island" + } +} diff --git a/mcpacker/pack/mysteriousisland/assets/images/peat_block.png b/mcpacker/pack/mysteriousisland/static/resourcepack/assets/kubejs/textures/block/peat_block.png similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/images/peat_block.png rename to mcpacker/pack/mysteriousisland/static/resourcepack/assets/kubejs/textures/block/peat_block.png diff --git a/mcpacker/pack/mysteriousisland/assets/images/peat_chunk.png b/mcpacker/pack/mysteriousisland/static/resourcepack/assets/kubejs/textures/item/peat_chunk.png similarity index 100% rename from mcpacker/pack/mysteriousisland/assets/images/peat_chunk.png rename to mcpacker/pack/mysteriousisland/static/resourcepack/assets/kubejs/textures/item/peat_chunk.png diff --git a/mcpacker/pack/testpack/static/test.md b/mcpacker/pack/testpack/static/test.md new file mode 100644 index 0000000..b1c7ff0 --- /dev/null +++ b/mcpacker/pack/testpack/static/test.md @@ -0,0 +1 @@ +testpack diff --git a/mcpacker/ui/runner.py b/mcpacker/ui/runner.py index c1b49c7..8243d35 100644 --- a/mcpacker/ui/runner.py +++ b/mcpacker/ui/runner.py @@ -4,7 +4,8 @@ from mcpacker.write.markdown.biomereport import BiomeReport from mcpacker.write.markdown.mineralreport import MineralReport from mcpacker.write.markdown.mobspawnreport import MobSpawnReport from mcpacker.write.markdown.reportwriter import ReportWriter -from mcpacker.write.writer import CompositeWriter +from mcpacker.write.compositewriter import CompositeWriter +from mcpacker.write.staticwriter import StaticWriter from pathlib import Path import inspect @@ -44,15 +45,14 @@ class Runner: # Commands ################################################################# def _command_writeReports(self): - writer = CompositeWriter(self.pack, self.outputDir, [ + CompositeWriter(self.pack, self.outputDir, [ BiomeReport, MineralReport, MobSpawnReport, - ]) - writer.write() + ]).write() def _command_writeModPack(self): - writer = CompositeWriter(self.pack, self.outputDir, [ + CompositeWriter(self.pack, self.outputDir, [ + StaticWriter, SpawnerWriter, - ]) - writer.write() + ]).write() diff --git a/mcpacker/ui/runner_test.py b/mcpacker/ui/runner_test.py index 0e643a0..9f17cbf 100644 --- a/mcpacker/ui/runner_test.py +++ b/mcpacker/ui/runner_test.py @@ -70,30 +70,31 @@ def defineAddMobSpawnss(): @fixture(name="pack") def createPack(addBiomes, addMobs, addMobSpawns): - pack = ModPack("testModPack") + pack = ModPack("testpack") pack.augment(addBiomes) pack.augment(addMobs) pack.augment(addMobSpawns) yield pack @fixture(name="modPackRunner") -def createModPackRunner(tmp_path:Path): - runner = Runner(ModPack("testModPack"), tmp_path) +def createModPackRunner(tmp_path:Path, pack:ModPack): + runner = Runner(pack, tmp_path) runner._command_writeModPack() yield runner @fixture(name="reportRunner") -def createReportRunner(tmp_path:Path): - runner = Runner(ModPack("testModPack"), tmp_path) +def createReportRunner(tmp_path:Path, pack:ModPack): + runner = Runner(pack, tmp_path) runner._command_writeReports() yield runner # Tests ############################################################################################ def test_writeModPack(tmp_path:Path, modPackRunner:Runner): - assert (tmp_path/"testModPack"/"config"/"incontrol"/"spawner.json").exists() + assert (tmp_path/"testpack"/"config"/"incontrol"/"spawner.json").exists() + assert (tmp_path/"testpack"/"test.md").exists() def test_writeReports(tmp_path:Path, reportRunner:Runner): - assert (tmp_path/"testModPack"/"reports"/"biomes.md").exists() - assert (tmp_path/"testModPack"/"reports"/"minerals.md").exists() - assert (tmp_path/"testModPack"/"reports"/"mobspawns.md").exists() + assert (tmp_path/"testpack"/"reports"/"biomes.md").exists() + assert (tmp_path/"testpack"/"reports"/"minerals.md").exists() + assert (tmp_path/"testpack"/"reports"/"mobspawns.md").exists() diff --git a/mcpacker/write/compositewriter.py b/mcpacker/write/compositewriter.py new file mode 100644 index 0000000..97fdc09 --- /dev/null +++ b/mcpacker/write/compositewriter.py @@ -0,0 +1,37 @@ +from collections.abc import Iterable +from mcpacker.model.modpack import ModPack +from mcpacker.write.writer import Writer +from pathlib import Path +from typing import TypeVar + +import os +import shutil + + +# Type Support ##################################################################################### + +WriterSubclass = TypeVar("WriterSubclass", bound=Writer) + + +# Class ############################################################################################ + +class CompositeWriter(Writer): + + def __init__( + self, + pack:ModPack, + outputDir:Path, + writers:Iterable[type[WriterSubclass]]|None=None + ): + super().__init__(pack, outputDir) + + self._writers:list[Writer] = [] + for writerClass in (writers or []): + self.add(writerClass) + + def add(self, writerClass:type[WriterSubclass]): + self._writers.append(writerClass(self.pack, self.outputDir)) + + def write(self): + for writer in self._writers: + writer.write() diff --git a/mcpacker/write/incontrol/spawnerwriter.py b/mcpacker/write/incontrol/spawnerwriter.py index 2619a7b..7ba7731 100644 --- a/mcpacker/write/incontrol/spawnerwriter.py +++ b/mcpacker/write/incontrol/spawnerwriter.py @@ -15,6 +15,7 @@ import mcpacker.model.core.dimension as DI import mcpacker.model.core.fauna.location as LO import mcpacker.model.core.scarcity as SC import mcpacker.model.time as TI +import os # Class ############################################################################################ @@ -26,7 +27,7 @@ class SpawnerWriter(Writer): def write(self): path = self.outputDir / self.pack.name / INCONTROL_CONFIG_DIR / "spawner.json" - path.parent.mkdir(parents=True) + self.resetOutputFile(path) path.write_text(json.dumps(self._makeAllRules(), indent=json.INDENT)) # Private Functions ######################################################## diff --git a/mcpacker/write/locator.py b/mcpacker/write/locator.py new file mode 100644 index 0000000..29bfb17 --- /dev/null +++ b/mcpacker/write/locator.py @@ -0,0 +1,137 @@ +from mcpacker.model.modpack import ModPack +from pathlib import Path +from typing import Protocol +from typing import TypeVar +from typing import TypeAlias + + +# Class ############################################################################################ + +class Locator: + """ + Locator identifies various important paths within a modpack. + + It currently has added support for the following mods: + + * Cold Sweat + * InControl! + * InfoDump + * KubeJS + * Large Ore Deposits + * Thirst Was Taken + """ + + def __init__(self, pack:ModPack, outputDir:Path): + self._pack = pack + self._outputDir = outputDir + + def biomeModifiers(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "neoforge" / "biome_modifier" + + def blockStates(self, modName:str|None=None, resourcePackName:str|None=None) -> Path: + return self.resourcePackMod(modName, resourcePackName) / "blockstates" + + def config(self) -> Path: + return self.root() / "config" + + def configuredFeatures(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "worldgen" / "configured_feature" + + def dataPack(self, dataPackName:str|None=None): + return self.dataPacks() / (dataPackName or f"{self._pack.name}_override") + + def dataPackMod(self, modName:str|None=None, dataPackName:str|None=None): + return self.dataPack(dataPackName) / "data" / (modName or self._pack.name) + + def dataPacks(self) -> Path: + return self.root() / "datapacks" + + def functions(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "functions" + + def lootModifiers(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "loot_modifiers" + + def lootTables(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "loot_tables" + + def models(self, modName:str|None=None, resourcePackName:str|None=None) -> Path: + return self.resourcePackMod(modName, resourcePackName) / "models" + + def placedFeatures(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "worldgen" / "placed_feature" + + def recipes(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "recipes" + + def resourcePack(self, resourcePackName:str|None=None) -> Path: + return self.resourcePacks() / (resourcePackName or f"{self._pack.name}_override") + + def resourcePackMod(self, modName:str|None=None, resourcePackName:str|None=None) -> Path: + return self.resourcePack(resourcePackName) / "assets" / (modName or self._pack.name) + + def resourcePacks(self) -> Path: + return self.root() / "resourcepacks" + + def root(self) -> Path: + return self._outputDir / self._pack.name + + def structures(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "structure" + + def structureSets(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "structure_set" + + def tags(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "tags" + + def templatePools(self, modName:str|None=None, dataPackName:str|None=None) -> Path: + return self.dataPackMod(modName, dataPackName) / "template_pool" + + # ColdSweat Mixins ######################################################### + + def cos_config(self) -> Path: + return self.config() / "coldsweat" + + # InControl Mixins ######################################################### + + def inc_config(self) -> Path: + return self.config() / "incontrol" + + # InfoDump Mixins ########################################################## + + def ifd_root(self) -> Path: + return self.root() / "infodump" + + # KubeJS Mixins ############################################################ + + def kbj_root(self) -> Path: + return self.root() / "kubejs" + + def kbj_clientScripts(self) -> Path: + return self.kbj_root() / "client_scripts" + + def kbj_serverScripts(self) -> Path: + return self.kbj_root() / "server_scripts" + + def kbj_startupScripts(self) -> Path: + return self.kbj_root() / "startup_scripts" + + # Large Ore Deposits Mixins ################################################ + + def lod_config(self) -> Path: + return self.config() / "adlods" + + def lod_deposits(self) -> Path: + return self.lod_config() / "Deposits" + + def lod_geodes(self) -> Path: + return self.lod_config() / "Geodes" + + def lod_vanilla(self) -> Path: + return self.lod_config() / "Vanilla" + + # ThirstWasTaken ########################################################### + + def twt_config(self) -> Path: + return self.config() / "thirst" diff --git a/mcpacker/write/locator_test.py b/mcpacker/write/locator_test.py new file mode 100644 index 0000000..27e3403 --- /dev/null +++ b/mcpacker/write/locator_test.py @@ -0,0 +1,56 @@ +from mcpacker.write.locator import Locator +from mcpacker.model.modpack import ModPack +from pathlib import Path +from pytest import fixture + + +# Fixtures ######################################################################################### + +@fixture(name="locator") +def createLocator(): + return Locator(ModPack("testPack"), Path("output")) + + +# Tests ############################################################################################ + +def test_blockStates(locator:Locator): + assert ( + locator.blockStates() == + Path( + "output/testPack/resourcepacks/testPack_override/" + + "assets/testPack/blockstates" + ) + ) + +def test_configuredFeatures(locator:Locator): + assert ( + locator.configuredFeatures() == + Path( + "output/testPack/datapacks/testPack_override/" + + "data/testPack/worldgen/configured_feature" + ) + ) + +def test_configuredFeaturesSpecificDataPack(locator:Locator): + assert ( + locator.configuredFeatures(dataPackName="alternate") == + Path( + "output/testPack/datapacks/alternate/" + + "data/testPack/worldgen/configured_feature" + ) + ) + +def test_configuredFeaturesSpecificMod(locator:Locator): + assert ( + locator.configuredFeatures("farmersdelight") == + Path( + "output/testPack/datapacks/testPack_override/" + + "data/farmersdelight/worldgen/configured_feature" + ) + ) + +def test_kbj_serverScripts(locator:Locator): + assert locator.kbj_serverScripts() == Path("output/testPack/kubejs/server_scripts") + +def test_root(locator:Locator): + assert locator.root() == Path("output/testPack") diff --git a/mcpacker/write/markdown/mobspawnreport.py b/mcpacker/write/markdown/mobspawnreport.py index 206ef29..73685ca 100644 --- a/mcpacker/write/markdown/mobspawnreport.py +++ b/mcpacker/write/markdown/mobspawnreport.py @@ -35,7 +35,7 @@ class MobSpawnReport(MarkdownWriter): line(", ".join([t.name for t in trait])) for trait in habitat.biomeFilter.prohibited: - category = type(trait[0]).__name__ + category = type(trait).__name__ self.text("* ").text(category).text(": not: ").line(trait.name) self.outdent() diff --git a/mcpacker/write/resourcepack/blockstatewriter.py b/mcpacker/write/resourcepack/blockstatewriter.py new file mode 100644 index 0000000..dbc32a9 --- /dev/null +++ b/mcpacker/write/resourcepack/blockstatewriter.py @@ -0,0 +1,12 @@ +from mcpacker.write.writer import Writer + +# Class ############################################################################################ + +class BlockStateWiter(Writer): + + def write(self): + for mod in self.pack.resourcePack.mods: + for blockState in mod.blockStates: + path = self.outputDir/self.pack.name/"resourcepacks" + + diff --git a/mcpacker/write/staticwriter.py b/mcpacker/write/staticwriter.py new file mode 100644 index 0000000..02a65bf --- /dev/null +++ b/mcpacker/write/staticwriter.py @@ -0,0 +1,23 @@ +from mcpacker.model.modpack import ModPack +from mcpacker.write.writer import Writer +from pathlib import Path + +import shutil + + +# Constants ######################################################################################## + +SOURCE_BASE = Path("mcpacker") / "pack" + + +# Class ############################################################################################ + +class StaticWriter(Writer): + + def __init__(self, pack:ModPack, outputDir:Path): + super().__init__(pack, outputDir) + + def write(self): + sourcePath = SOURCE_BASE / self.pack.name / "static" + targetPath = self.outputDir / self.pack.name + shutil.copytree(sourcePath, targetPath, dirs_exist_ok=True) diff --git a/mcpacker/write/writer.py b/mcpacker/write/writer.py index da9c375..611468a 100644 --- a/mcpacker/write/writer.py +++ b/mcpacker/write/writer.py @@ -1,17 +1,10 @@ -from collections.abc import Iterable from mcpacker.model.modpack import ModPack from pathlib import Path -from typing import TypeVar import os import shutil -# Type Support ##################################################################################### - -WriterSubclass = TypeVar("WriterSubclass", bound="Writer") - - # Class ############################################################################################ class Writer: @@ -20,35 +13,10 @@ class Writer: self.pack = pack self.outputDir = outputDir - def resetOutputDir(self): - if self.outputDir.exists(): - shutil.rmtree(self.outputDir) - - self.outputDir.mkdir(parents=True) + def resetOutputFile(self, file:Path): + if file.exists(): + os.remove(file) + file.parent.mkdir(parents=True, exist_ok=True) def write(self): raise NotImplementedError() - - -# Class ############################################################################################ - -class CompositeWriter(Writer): - - def __init__( - self, - pack:ModPack, - outputDir:Path, - writers:Iterable[type[WriterSubclass]]|None=None - ): - super().__init__(pack, outputDir) - - self._writers:list[Writer] = [] - for writerClass in (writers or []): - self.add(writerClass) - - def add(self, writerClass:type[WriterSubclass]): - self._writers.append(writerClass(self.pack, self.outputDir)) - - def write(self): - for writer in self._writers: - writer.write() diff --git a/mcpacker/write/writer_test.py b/mcpacker/write/writer_test.py new file mode 100644 index 0000000..4cbe935 --- /dev/null +++ b/mcpacker/write/writer_test.py @@ -0,0 +1,30 @@ +from mcpacker.write.writer import Writer +from mcpacker.model.modpack import ModPack +from pathlib import Path +from pytest import fixture + + +# Helpers ########################################################################################## + +class SampleWriter(Writer): + + def write(self): + path = self.outputDir/self.pack.name/"samplewriter.md" + self.resetOutputFile(path) + path.write_text("alpha bravo charlie") + + +# Fixtures ######################################################################################### + +@fixture(name="writer") +def createWriter(tmp_path): + writer = SampleWriter(ModPack("testpack"), tmp_path) + writer.write() + yield writer + + +# Tests ############################################################################################ + +def test_write(tmp_path:Path, writer:SampleWriter): + path = tmp_path/"testpack"/"samplewriter.md" + assert path.read_text() == "alpha bravo charlie"