diff --git a/mcpacker/format/datapack/__init__.py b/mcpacker/format/datapack/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mcpacker/format/datapack/biomemodifier/__init__.py b/mcpacker/format/datapack/biomemodifier/__init__.py new file mode 100644 index 0000000..422d28a --- /dev/null +++ b/mcpacker/format/datapack/biomemodifier/__init__.py @@ -0,0 +1,11 @@ +from mcpacker.json import JsonBlob + + +# Classes ########################################################################################## + +class BiomeModifier: + + def asJsonBlob(self) -> JsonBlob: + return { + "type": "neoforge:none", + } diff --git a/mcpacker/format/datapack/biomemodifier/addfeature.py b/mcpacker/format/datapack/biomemodifier/addfeature.py new file mode 100644 index 0000000..3af87d1 --- /dev/null +++ b/mcpacker/format/datapack/biomemodifier/addfeature.py @@ -0,0 +1,28 @@ +from collections.abc import Iterable +from mcpacker.format.datapack.biomemodifier import BiomeModifier +from mcpacker.format.datapack.biomemodifier.generationstep import GenerationStep +from mcpacker.json import JsonBlob + + +# Class ############################################################################################ + +class AddFeatureBiomeModifier(BiomeModifier): + + def __init__(self, biomes:Iterable[str]|str, features:Iterable[str]|str, step:GenerationStep): + if isinstance(biomes, str): + biomes = [biomes] + + if isinstance(features, str): + features = [features] + + self.biomes = biomes + self.features = features + self.step = step + + def asJsobBlob(self) -> JsonBlob: + return { + "type": "neoforge:add_features", + "biomes": list(self.biomes), + "features": list(self.features), + "step": str(self.step), + } diff --git a/mcpacker/format/datapack/biomemodifier/generationstep.py b/mcpacker/format/datapack/biomemodifier/generationstep.py new file mode 100644 index 0000000..a7c3b15 --- /dev/null +++ b/mcpacker/format/datapack/biomemodifier/generationstep.py @@ -0,0 +1,52 @@ +from typing import Any + + +# Class ############################################################################################ + +class GenerationStep: + + def __init__(self, gameId:str): + self.gameId = gameId + + def __eq__(self, other:Any) -> bool: + if type(self) != type(other): return False + if self.gameId != other.gameId: return False + return True + + def __hash__(self) -> int: + return hash(self.gameId) + + def __repr__(self) -> str: + return f"GenerationStep(gameId={repr(self.gameId)})" + + def __str__(self) -> str: + return self.gameId + + +# Constants ######################################################################################## + +RAW_GENERATION = GenerationStep("raw_generation") +LAKES = GenerationStep("lakes") +LOCAL_MODIFICATIONS = GenerationStep("local_modifications") +UNDERGROUND_STRUCTURES = GenerationStep("underground_structures") +SURFACE_STRUCTURES = GenerationStep("surface_structures") +STRONGHOLDS = GenerationStep("strongholds") +UNDERGROUND_ORES = GenerationStep("underground_ores") +UNDERGROUND_DECORATION = GenerationStep("underground_decoration") +FLUID_SPRINGS = GenerationStep("fluid_springs") +VEGETAL_DECORATION = GenerationStep("vegetal_decoration") +TOP_LAYER_MODIFICATION = GenerationStep("top_layer_modification") + +ALL = [ + RAW_GENERATION, + LAKES, + LOCAL_MODIFICATIONS, + UNDERGROUND_STRUCTURES, + SURFACE_STRUCTURES, + STRONGHOLDS, + UNDERGROUND_ORES, + UNDERGROUND_DECORATION, + FLUID_SPRINGS, + VEGETAL_DECORATION, + TOP_LAYER_MODIFICATION, +] diff --git a/mcpacker/format/datapack/biomemodifier/removefeature.py b/mcpacker/format/datapack/biomemodifier/removefeature.py new file mode 100644 index 0000000..7727262 --- /dev/null +++ b/mcpacker/format/datapack/biomemodifier/removefeature.py @@ -0,0 +1,37 @@ +from collections.abc import Iterable +from mcpacker.format.datapack.biomemodifier import BiomeModifier +from mcpacker.format.datapack.biomemodifier.generationstep import GenerationStep +from mcpacker.json import JsonBlob + + +# Classes ########################################################################################## + +class RemoveFeatureBiomeModifier(BiomeModifier): + + def __init__( + self, + biomes:Iterable[str]|str, + features:Iterable[str]|str, + step:GenerationStep|None=None + ): + if isinstance(biomes, str): + biomes = [biomes] + + if isinstance(features, str): + features = [features] + + self.biomes = biomes + self.features = features + self.step = step + + def asJsobBlob(self) -> JsonBlob: + result:dict[str,JsonBlob] = { + "type": "neoforge:remove_features", + "biomes": list(self.biomes), + "features": list(self.features), + } + + if self.step: + result["step"] = str(self.step) + + return result diff --git a/mcpacker/format/datapack/biomemodifier/removespawn.py b/mcpacker/format/datapack/biomemodifier/removespawn.py new file mode 100644 index 0000000..971906a --- /dev/null +++ b/mcpacker/format/datapack/biomemodifier/removespawn.py @@ -0,0 +1,22 @@ +from collections.abc import Iterable +from mcpacker.format.datapack.biomemodifier import BiomeModifier +from mcpacker.json import JsonBlob + + +# Classes ########################################################################################## + +class RemoveSpawnBiomeModifier(BiomeModifier): + + def __init__(self, biomes:Iterable[str]|str, entityTypes:Iterable[str]): + if isinstance(biomes, str): + biomes = [biomes] + + self.biomes = biomes + self.entityTypes = entityTypes + + def asJsonBlob(self) -> JsonBlob: + return { + "type": "neoforge:remove_spawns", + "biomes": list(self.biomes), + "entity_types": list(self.entityTypes), + } diff --git a/mcpacker/ui/runner.py b/mcpacker/ui/runner.py index 1e5b8a1..786629b 100644 --- a/mcpacker/ui/runner.py +++ b/mcpacker/ui/runner.py @@ -4,6 +4,7 @@ from mcpacker.format.report.mineralreport import MineralReport from mcpacker.format.report.mobspawnreport import MobSpawnReport from mcpacker.model.modpack import ModPack from mcpacker.write.compositewriter import CompositeWriter +from mcpacker.write.datapack.disablespawnwriter import DisableSpawnWriter from mcpacker.write.datapack.metawriter import DataPackMetaWriter from mcpacker.write.datapack.writer import DataPackWriter from mcpacker.write.incontrol.spawnerwriter import SpawnerWriter @@ -49,21 +50,28 @@ class Runner: # Commands ################################################################# def _command_writeReports(self): - CompositeWriter(self.pack, self.outputDir, [ - ReportWriter(self.pack, BiomeReport, self.outputDir, "biomes.txt"), - ReportWriter(self.pack, DepositReport, self.outputDir, "deposits.txt"), - ReportWriter(self.pack, MineralReport, self.outputDir, "minerals.txt"), - ReportWriter(self.pack, MobSpawnReport, self.outputDir, "mobspawns.txt"), + p = self.pack + o = self.outputDir + + CompositeWriter(p, o, [ + ReportWriter(p, BiomeReport, o, "biomes.txt"), + ReportWriter(p, DepositReport, o, "deposits.txt"), + ReportWriter(p, MineralReport, o, "minerals.txt"), + ReportWriter(p, MobSpawnReport, o, "mobspawns.txt"), ]).write() def _command_writeModPack(self): - CompositeWriter(self.pack, self.outputDir, [ - StaticWriter(self.pack, self.outputDir), - SpawnerWriter(self.pack, self.outputDir), - DataPackWriter(self.pack, self.outputDir, [ - DataPackMetaWriter(self.pack, self.outputDir, 48), + p = self.pack + o = self.outputDir + + CompositeWriter(p, o, [ + StaticWriter(p, o), + SpawnerWriter(p, o), + DataPackWriter(p, o, [ + DataPackMetaWriter(p, o, 48), + DisableSpawnWriter(p, o), ]), - ResourcePackWriter(self.pack, self.outputDir, [ - ResourcePackMetaWriter(self.pack, self.outputDir, 34), + ResourcePackWriter(p, o, [ + ResourcePackMetaWriter(p, o, 34), ]), ]).write() diff --git a/mcpacker/ui/runner_test.py b/mcpacker/ui/runner_test.py index c7b84c6..21f58ec 100644 --- a/mcpacker/ui/runner_test.py +++ b/mcpacker/ui/runner_test.py @@ -92,9 +92,11 @@ def createReportRunner(tmp_path:Path, pack:ModPack): def test_writeModPack(tmp_path:Path, modPackRunner:Runner): assert (tmp_path/"testpack"/"config"/"incontrol"/"spawner.json").exists() + assert (tmp_path/"testpack"/"datapacks"/"testpack.jar").exists() assert (tmp_path/"testpack"/"test.md").exists() def test_writeReports(tmp_path:Path, reportRunner:Runner): assert (tmp_path/"testpack"/"reports"/"biomes.txt").exists() + assert (tmp_path/"testpack"/"reports"/"deposits.txt").exists() assert (tmp_path/"testpack"/"reports"/"minerals.txt").exists() assert (tmp_path/"testpack"/"reports"/"mobspawns.txt").exists() diff --git a/mcpacker/write/compositewriter.py b/mcpacker/write/compositewriter.py index 6779d9e..55bca97 100644 --- a/mcpacker/write/compositewriter.py +++ b/mcpacker/write/compositewriter.py @@ -1,5 +1,6 @@ from collections.abc import Iterable from mcpacker.model.modpack import ModPack +from mcpacker.write.locator import Locator from mcpacker.write.writer import Writer from pathlib import Path @@ -12,13 +13,10 @@ class CompositeWriter(Writer): self, pack:ModPack, outputDir:Path, - writers:Iterable[Writer]|None=None + writers:Iterable[Writer]|None=None, ): super().__init__(pack, outputDir) - - self._writers:list[Writer] = [] - for writer in (writers or []): - self._writers.append(writer) + self._writers:list[Writer] = list(writers or []) def doWrite(self): for writer in self._writers: diff --git a/mcpacker/write/datapack/disablespawnwriter.py b/mcpacker/write/datapack/disablespawnwriter.py new file mode 100644 index 0000000..55f5177 --- /dev/null +++ b/mcpacker/write/datapack/disablespawnwriter.py @@ -0,0 +1,19 @@ +from mcpacker.format.datapack.biomemodifier.removespawn import RemoveSpawnBiomeModifier +from mcpacker.write.writer import Writer + +import mcpacker.json as json + + +# Class ############################################################################################ + +class DisableSpawnWriter(Writer): + """ + Writes files to disable vanilla spawns for mobs who are to be spawned using custom rules. + """ + + def doWrite(self): + entityTypes = [m.gameId for m in self.pack.world.mobs] + modifier = RemoveSpawnBiomeModifier("#c:is_overworld", entityTypes) + path = self.locator.biomeModifiers() / "remove_managed_mob_spawns.json" + self.resetOutputFile(path) + path.write_text(json.dumps(modifier.asJsonBlob(), indent=json.INDENT)) diff --git a/mcpacker/write/locator.py b/mcpacker/write/locator.py index 1125df8..372e790 100644 --- a/mcpacker/write/locator.py +++ b/mcpacker/write/locator.py @@ -56,7 +56,7 @@ class Locator: 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") + return self.dataPacks() / (dataPackName or f"{self.pack.name}") def dataPackMod(self, modName:str|None=None, dataPackName:str|None=None): return self.dataPack(dataPackName) / "data" / (modName or self.pack.name) @@ -83,7 +83,7 @@ class Locator: return self.dataPackMod(modName, dataPackName) / "recipes" def resourcePack(self, resourcePackName:str|None=None) -> Path: - return self.resourcePacks() / (resourcePackName or f"{self.pack.name}_override") + return self.resourcePacks() / (resourcePackName or f"{self.pack.name}") def resourcePackMod(self, modName:str|None=None, resourcePackName:str|None=None) -> Path: return self.resourcePack(resourcePackName) / "assets" / (modName or self.pack.name) diff --git a/mcpacker/write/locator_test.py b/mcpacker/write/locator_test.py index 27e3403..47371b3 100644 --- a/mcpacker/write/locator_test.py +++ b/mcpacker/write/locator_test.py @@ -17,7 +17,7 @@ def test_blockStates(locator:Locator): assert ( locator.blockStates() == Path( - "output/testPack/resourcepacks/testPack_override/" + + "output/testPack/resourcepacks/testPack/" + "assets/testPack/blockstates" ) ) @@ -26,7 +26,7 @@ def test_configuredFeatures(locator:Locator): assert ( locator.configuredFeatures() == Path( - "output/testPack/datapacks/testPack_override/" + + "output/testPack/datapacks/testPack/" + "data/testPack/worldgen/configured_feature" ) ) @@ -44,7 +44,7 @@ def test_configuredFeaturesSpecificMod(locator:Locator): assert ( locator.configuredFeatures("farmersdelight") == Path( - "output/testPack/datapacks/testPack_override/" + + "output/testPack/datapacks/testPack/" + "data/farmersdelight/worldgen/configured_feature" ) ) diff --git a/mcpacker/write/report/writer.py b/mcpacker/write/report/writer.py index 50f5a7c..d7e69c8 100644 --- a/mcpacker/write/report/writer.py +++ b/mcpacker/write/report/writer.py @@ -14,7 +14,7 @@ class ReportWriter(Writer): pack:ModPack, composerClass:type[ReportComposer], outputDir:Path, - name:str|Path + name:str|Path, ): super().__init__(pack, outputDir) self.composerClass = composerClass diff --git a/mcpacker/write/report/writer_test.py b/mcpacker/write/report/writer_test.py new file mode 100644 index 0000000..4b9db08 --- /dev/null +++ b/mcpacker/write/report/writer_test.py @@ -0,0 +1,7 @@ +import mcpacker.write.report.writer + + +# Tests ############################################################################################ + +def test_syntax(): + pass diff --git a/mcpacker/write/staticwriter.py b/mcpacker/write/staticwriter.py index 041521b..91a48fe 100644 --- a/mcpacker/write/staticwriter.py +++ b/mcpacker/write/staticwriter.py @@ -14,9 +14,6 @@ SOURCE_BASE = Path("mcpacker") / "pack" class StaticWriter(Writer): - def __init__(self, pack:ModPack, outputDir:Path): - super().__init__(pack, outputDir) - def doWrite(self): sourcePath = SOURCE_BASE / self.pack.name / "static" targetPath = self.locator.root()