Add the ability to disable existing placed features

This commit is contained in:
Andrew Miner
2025-10-16 17:59:20 -06:00
parent 87b6362d12
commit 286ba774d6
19 changed files with 156 additions and 51 deletions
@@ -1,6 +1,15 @@
from mcpacker.json import JsonBlob
# Class ############################################################################################ # Class ############################################################################################
class ConfiguredFeature: class ConfiguredFeature:
def __init__(self, gameId:str): def __init__(self, gameId:str):
self.gameId = gameId self.gameId = gameId
def asJsonBlob(self) -> JsonBlob:
return {
"type": self.gameId,
"config": {},
}
@@ -1,4 +1,5 @@
from mcpacker.format.datapack.configuredfeature import ConfiguredFeature from mcpacker.format.datapack.configuredfeature import ConfiguredFeature
from mcpacker.json import JsonBlob
from typing import Any from typing import Any
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@@ -13,7 +14,7 @@ class RandomPatch(ConfiguredFeature):
def __init__( def __init__(
self, self,
gameId:str, gameId:str,
feature:PlacedFeature, feature:"PlacedFeature",
tries:int=128, tries:int=128,
xzSpread:int=7, xzSpread:int=7,
ySpread:int=3, ySpread:int=3,
@@ -25,7 +26,7 @@ class RandomPatch(ConfiguredFeature):
self.xzSpread = xzSpread self.xzSpread = xzSpread
self.ySpread = ySpread self.ySpread = ySpread
def asData(self) -> dict[str,Any]: def asJsonBlob(self) -> JsonBlob:
return { return {
"type": self.gameId, "type": self.gameId,
"feature": self.feature.gameId, "feature": self.feature.gameId,
@@ -1,6 +1,7 @@
from mcpacker.format.datapack.blockstate import BlockState from mcpacker.format.datapack.blockstate import BlockState
from mcpacker.format.datapack.placedfeature import PlacedFeature
from mcpacker.format.datapack.blockstateprovider.simplestateprovider import SimpleStateProvider from mcpacker.format.datapack.blockstateprovider.simplestateprovider import SimpleStateProvider
from mcpacker.format.datapack.configuredfeature.simpleblock import SimpleBlock from mcpacker.format.datapack.configuredfeature.randompatch import RandomPatch
from pytest import fixture from pytest import fixture
@@ -14,25 +15,22 @@ def createBlockState():
def createProvider(state:BlockState): def createProvider(state:BlockState):
return SimpleStateProvider(state) return SimpleStateProvider(state)
@fixture(name="placedFeature")
def createPlacedFeature():
return PlacedFeature("noop", [])
@fixture(name="feature") @fixture(name="feature")
def createSimpleBlockFeature(provider:SimpleStateProvider): def createFeature(placedFeature:PlacedFeature):
return SimpleBlock(provider) return RandomPatch("test", placedFeature)
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(feature:SimpleBlock): def test_asJsonBlob(feature:RandomPatch):
assert feature.asJsonBlob() == { assert feature.asJsonBlob() == {
"type": "minecraft:simple_block", "type": "minecraft:random_patch",
"config": { "feature": "noop",
"to_place": { "tries": 128,
"type": "minecraft:simple_state_provider", "xz_spread": 7,
"state": { "y_spread": 3,
"Name": "minecraft:button",
"Properties": {
"waterlogged": "true"
}
}
}
}
} }
+9 -1
View File
@@ -1,10 +1,18 @@
from collections.abc import Iterable
from mcpacker.format.datapack.placement import Placement from mcpacker.format.datapack.placement import Placement
from mcpacker.json import JsonBlob
# Class ############################################################################################ # Class ############################################################################################
class PlacedFeature: class PlacedFeature:
def __init__(self, gameId:str, placements:list[Placement]): def __init__(self, gameId:str, placements:Iterable[Placement]):
self.gameId = gameId self.gameId = gameId
self.placements = placements self.placements = placements
def asJsonBlob(self) -> JsonBlob:
return {
"feature": self.gameId,
"placements": [p.asJsonBlob() for p in self.placements],
}
@@ -1,6 +1,14 @@
from mcpacker.json import JsonBlob
# Class ############################################################################################ # Class ############################################################################################
class Placement: class Placement:
def __init__(self, gameId:str): def __init__(self, gameId:str):
self.gameId = gameId self.gameId = gameId
def asJsonBlob(self) -> JsonBlob:
return {
"type": self.gameId,
}
@@ -7,7 +7,3 @@ class Biome(Placement):
def __init__(self): def __init__(self):
super().__init__("minecraft:biome") super().__init__("minecraft:biome")
def asData(self) -> dict[str,Any]:
return { "type": self.gameId }
@@ -12,7 +12,7 @@ def createPlacement():
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(placement): def test_asData(placement):
assert placement.asData() == { assert placement.asJsonBlob() == {
"type": "minecraft:biome", "type": "minecraft:biome",
} }
@@ -1,7 +1,9 @@
from mcpacker.format.datapack.heightmaptype import HeightMapType from mcpacker.format.datapack.heightmaptype import HeightMapType
from mcpacker.format.datapack.placement import Placement from mcpacker.format.datapack.placement import Placement
from mcpacker.json import JsonBlob
from typing import Any from typing import Any
# Class ############################################################################################ # Class ############################################################################################
class HeightMap(Placement): class HeightMap(Placement):
@@ -10,7 +12,7 @@ class HeightMap(Placement):
super().__init__("minecraft:heightmap") super().__init__("minecraft:heightmap")
self.heightMap = heightMap self.heightMap = heightMap
def asData(self) -> dict[str,Any]: def asJsonBlob(self) -> JsonBlob:
return { return {
"type": self.gameId, "type": self.gameId,
"heightmap": self.heightMap.asData() "heightmap": self.heightMap.asData()
@@ -13,7 +13,7 @@ def createPlacement():
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(placement): def test_asData(placement):
assert placement.asData() == { assert placement.asJsonBlob() == {
"type": "minecraft:heightmap", "type": "minecraft:heightmap",
"heightmap": "WORLD_SURFACE" "heightmap": "WORLD_SURFACE"
} }
@@ -1,13 +1,10 @@
from mcpacker.format.datapack.placement import Placement from mcpacker.format.datapack.placement import Placement
from typing import Any from typing import Any
# Class ############################################################################################ # Class ############################################################################################
class InSquare(Placement): class InSquare(Placement):
def __init__(self): def __init__(self):
super().__init__("minecraft:in_square") super().__init__("minecraft:in_square")
def asData(self) -> dict[str,Any]:
return { "type": self.gameId }
@@ -12,7 +12,7 @@ def createPlacement():
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(placement): def test_asData(placement):
assert placement.asData() == { assert placement.asJsonBlob() == {
"type": "minecraft:in_square", "type": "minecraft:in_square",
} }
@@ -1,6 +1,8 @@
from mcpacker.format.datapack.placement import Placement from mcpacker.format.datapack.placement import Placement
from mcpacker.json import JsonBlob
from typing import Any from typing import Any
# Class ############################################################################################ # Class ############################################################################################
class RarityFilter(Placement): class RarityFilter(Placement):
@@ -9,9 +11,9 @@ class RarityFilter(Placement):
super().__init__("minecraft:rarity_filter") super().__init__("minecraft:rarity_filter")
self.chance = chance self.chance = chance
def asData(self) -> dict[str,Any]: def asJsonBlob(self) -> JsonBlob:
return { return {
"type": self.gameId, "type": self.gameId,
"chance": self.chance "chance": self.chance,
} }
@@ -12,7 +12,7 @@ def createPlacement():
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(placement): def test_asData(placement):
assert placement.asData() == { assert placement.asJsonBlob() == {
"type": "minecraft:rarity_filter", "type": "minecraft:rarity_filter",
"chance": 4 "chance": 4
} }
+9 -8
View File
@@ -1,6 +1,7 @@
from collections.abc import Iterable from collections.abc import Iterable
from mcpacker.model.core.world import World
from mcpacker.format.datapack import DataPack from mcpacker.format.datapack import DataPack
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.core.world import World
from mcpacker.model.mod import Mod from mcpacker.model.mod import Mod
from mcpacker.model.resourcepack import ResourcePack from mcpacker.model.resourcepack import ResourcePack
from typing import Callable from typing import Callable
@@ -23,15 +24,15 @@ class ModPack:
world:World|None=None, world:World|None=None,
dataPack:DataPack|None=None, dataPack:DataPack|None=None,
resourcePack:ResourcePack|None=None, resourcePack:ResourcePack|None=None,
disabledFeatures:Iterable[ResourceId]|None=None
): ):
self.name = name self.name = name
self.world = world or World()
self.dataPack = dataPack or DataPack(self.name)
self.resourcePack = resourcePack or ResourcePack(self.name)
self._mods = {} self.dataPack = dataPack or DataPack(self.name)
for mod in (mods or []): self.mods = {mod.name: mod for mod in (mods or [])}
self._mods[mod.name] = mod self.disabledFeatures = list(disabledFeatures or [])
self.resourcePack = resourcePack or ResourcePack(self.name)
self.world = world or World()
def augment(self, doAugment:AugmentFunc) -> Self: def augment(self, doAugment:AugmentFunc) -> Self:
doAugment(self) doAugment(self)
@@ -0,0 +1,32 @@
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.modpack import ModPack
# Helper Functions #################################################################################
def addDisabledFeatures(pack:ModPack):
d = pack.disabledFeatures
def add(resourceText:str):
pack.disabledFeatures.append(ResourceId.parse(resourceText))
# Disable Vanilla ore generation
add("minecraft:ore_coal_lower")
add("minecraft:ore_coal_upper")
add("minecraft:ore_copper_large")
add("minecraft:ore_copper")
add("minecraft:ore_diamond_buried")
add("minecraft:ore_diamond_large")
add("minecraft:ore_diamond_medium")
add("minecraft:ore_diamond")
add("minecraft:ore_emerald")
add("minecraft:ore_gold_deltas")
add("minecraft:ore_gold_extra")
add("minecraft:ore_gold_lower")
add("minecraft:ore_gold")
add("minecraft:ore_iron_middle")
add("minecraft:ore_iron_small")
add("minecraft:ore_iron_upper")
add("minecraft:ore_lapis_buried")
add("minecraft:ore_lapis")
add("minecraft:ore_redstone_lower")
add("minecraft:ore_redstone")
@@ -0,0 +1,7 @@
import mcpacker.pack.mysteriousisland.adddisabledfeatures
# Tests ############################################################################################
def test_syntax():
pass
+11 -9
View File
@@ -1,12 +1,13 @@
from mcpacker.model.modpack import ModPack from mcpacker.model.modpack import ModPack
from mcpacker.pack.mysteriousisland.addbiomes import addBiomes from mcpacker.pack.mysteriousisland.addbiomes import addBiomes
from mcpacker.pack.mysteriousisland.addblocks import addBlocks from mcpacker.pack.mysteriousisland.addblocks import addBlocks
from mcpacker.pack.mysteriousisland.adddatapack import addDataPack from mcpacker.pack.mysteriousisland.adddatapack import addDataPack
from mcpacker.pack.mysteriousisland.adddeposits import addDeposits from mcpacker.pack.mysteriousisland.adddeposits import addDeposits
from mcpacker.pack.mysteriousisland.additems import addItems from mcpacker.pack.mysteriousisland.adddisabledfeatures import addDisabledFeatures
from mcpacker.pack.mysteriousisland.addminerals import addMinerals from mcpacker.pack.mysteriousisland.additems import addItems
from mcpacker.pack.mysteriousisland.addmobs import addMobs from mcpacker.pack.mysteriousisland.addminerals import addMinerals
from mcpacker.pack.mysteriousisland.addmobspawns import addMobSpawns from mcpacker.pack.mysteriousisland.addmobs import addMobs
from mcpacker.pack.mysteriousisland.addmobspawns import addMobSpawns
from mcpacker.pack.mysteriousisland.addresourcepack import addResourcePack from mcpacker.pack.mysteriousisland.addresourcepack import addResourcePack
@@ -23,6 +24,7 @@ def buildModPack():
pack.augment(addDeposits) pack.augment(addDeposits)
pack.augment(addMobs) pack.augment(addMobs)
pack.augment(addMobSpawns) pack.augment(addMobSpawns)
pack.augment(addDisabledFeatures)
pack.augment(addResourcePack) pack.augment(addResourcePack)
pack.augment(addDataPack) pack.augment(addDataPack)
+2
View File
@@ -4,6 +4,7 @@ from mcpacker.format.report.mineralreport import MineralReport
from mcpacker.format.report.mobspawnreport import MobSpawnReport from mcpacker.format.report.mobspawnreport import MobSpawnReport
from mcpacker.model.modpack import ModPack from mcpacker.model.modpack import ModPack
from mcpacker.write.compositewriter import CompositeWriter from mcpacker.write.compositewriter import CompositeWriter
from mcpacker.write.datapack.disablefeaturewriter import DisableFeatureWriter
from mcpacker.write.datapack.disablespawnwriter import DisableSpawnWriter from mcpacker.write.datapack.disablespawnwriter import DisableSpawnWriter
from mcpacker.write.datapack.metawriter import DataPackMetaWriter from mcpacker.write.datapack.metawriter import DataPackMetaWriter
from mcpacker.write.datapack.writer import DataPackWriter from mcpacker.write.datapack.writer import DataPackWriter
@@ -69,6 +70,7 @@ class Runner:
SpawnerWriter(p, o), SpawnerWriter(p, o),
DataPackWriter(p, o, [ DataPackWriter(p, o, [
DataPackMetaWriter(p, o, 48), DataPackMetaWriter(p, o, 48),
DisableFeatureWriter(p, o),
DisableSpawnWriter(p, o), DisableSpawnWriter(p, o),
]), ]),
ResourcePackWriter(p, o, [ ResourcePackWriter(p, o, [
@@ -0,0 +1,40 @@
from mcpacker.format.datapack.biomemodifier.removefeature import RemoveFeatureBiomeModifier
from mcpacker.format.datapack.configuredfeature import ConfiguredFeature
from mcpacker.format.datapack.placedfeature import PlacedFeature
from mcpacker.write.writer import Writer
import mcpacker.json as json
# Class ############################################################################################
class DisableFeatureWriter(Writer):
def doWrite(self):
if not self.pack.disabledFeatures: return
self._writeRemoveFeaturesBiomeModifier()
self._writeNoopConfiguredFeature()
self._writeNoopPlacedFeatures()
# Private Methods ##########################################################
def _writeNoopConfiguredFeature(self):
feature = ConfiguredFeature("minecraft:no_op")
path = self.locator.configuredFeatures() / "noop.json"
self.resetOutputFile(path)
path.write_text(json.dumps(feature.asJsonBlob(), indent=json.INDENT))
def _writeNoopPlacedFeatures(self):
for placedFeature in self.pack.disabledFeatures:
path = self.locator.placedFeatures(placedFeature.mod) / f"{placedFeature.name}.json"
self.resetOutputFile(path)
feature = PlacedFeature(f"{self.pack.name}:noop", [])
path.write_text(json.dumps(feature.asJsonBlob(), indent=json.INDENT))
def _writeRemoveFeaturesBiomeModifier(self):
features = [str(f) for f in self.pack.disabledFeatures]
modifier = RemoveFeatureBiomeModifier("#c:is_overworld", features)
path = self.locator.biomeModifiers() / "remove_disabled_features.json"
self.resetOutputFile(path)
path.write_text(json.dumps(modifier.asJsobBlob(), indent=json.INDENT))