Add placed feature foramtters for plants
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
from mcpacker.format.json import JsonBlob
|
||||||
|
from mcpacker.model.flora.patch import Patch
|
||||||
|
from mcpacker.model.flora.plantspawn import PlantSpawn
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
|
||||||
|
import mcpacker.model.flora.immersion as IM
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class CropPlacedFeature:
|
||||||
|
|
||||||
|
def __init__(self, pack:ModPack, spawn:PlantSpawn):
|
||||||
|
self.pack = pack
|
||||||
|
self.spawn = spawn
|
||||||
|
|
||||||
|
def asJsonBlob(self) -> JsonBlob:
|
||||||
|
return {
|
||||||
|
"feature": f"{self.pack.name}:crop/{self.spawn.plant.name}",
|
||||||
|
"placement": self._buildPlacements(),
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def patch(self) -> Patch:
|
||||||
|
if not isinstance(self.spawn.plant, Patch): raise ValueError()
|
||||||
|
return self.spawn.plant
|
||||||
|
|
||||||
|
# Private Methods ##########################################################
|
||||||
|
|
||||||
|
def _buildPlacements(self) -> list[JsonBlob]:
|
||||||
|
livesIn = "minecraft:air"
|
||||||
|
if self.patch.immersion == IM.SUBMERGED:
|
||||||
|
livesIn = "minecraft:water"
|
||||||
|
|
||||||
|
placements:list[JsonBlob] = [
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": livesIn,
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"offset": [0, -1, 0],
|
||||||
|
"blocks": list(str(s) for s in self.patch.substrates),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.patch.immersion == IM.ADJACENT:
|
||||||
|
placements.append(self._buildWaterAdjacentPlacement())
|
||||||
|
|
||||||
|
return placements
|
||||||
|
|
||||||
|
def _buildWaterAdjacentPlacement(self) -> JsonBlob:
|
||||||
|
return {
|
||||||
|
"type": "minecraft:any_of",
|
||||||
|
"predicates": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [ 1, -1, 0 ]
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [ -1, -1, 0 ]
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [ 0, -1, 1 ]
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [ 0, -1, -1 ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
from mcpacker.format.datapack.placedfeature.crop import CropPlacedFeature
|
||||||
|
from mcpacker.format.json import JsonBlob
|
||||||
|
from mcpacker.model.ecology.biomefilter import BiomeFilter as BF
|
||||||
|
from mcpacker.model.ecotype import Ecotype
|
||||||
|
from mcpacker.model.flora.patch import Patch
|
||||||
|
from mcpacker.model.flora.plantspawn import PlantSpawn
|
||||||
|
from mcpacker.model.flora.tree import Tree
|
||||||
|
from mcpacker.model.habitat import Habitat
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.json import dumps
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
import mcpacker.model.altitude as AL
|
||||||
|
import mcpacker.model.ecology.flora as FL
|
||||||
|
import mcpacker.model.ecology.heat as HE
|
||||||
|
import mcpacker.model.ecology.humidity as HU
|
||||||
|
import mcpacker.model.ecology.soil as SO
|
||||||
|
import mcpacker.model.ecology.water as WA
|
||||||
|
import mcpacker.model.flora.canopyshape as CA
|
||||||
|
import mcpacker.model.flora.density as DE
|
||||||
|
import mcpacker.model.flora.immersion as IM
|
||||||
|
import mcpacker.model.flora.trunkshape as TR
|
||||||
|
import mcpacker.model.scarcity as SC
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="pack")
|
||||||
|
def createModPack():
|
||||||
|
yield ModPack("test")
|
||||||
|
|
||||||
|
@fixture(name="farmCropBlob")
|
||||||
|
def createFarmCropBlob(pack:ModPack):
|
||||||
|
yield CropPlacedFeature(
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "potato",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.span(AL.UPLANDS, AL.HILLS),
|
||||||
|
biomeFilters = BF([FL.FOREST, HE.BOREAL, HU.DAMP, SO.ACIDIC]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.UNCOMMON,
|
||||||
|
),
|
||||||
|
plant = Patch(
|
||||||
|
name = "potato",
|
||||||
|
blocks = "farmersdelight:wild_potatoes",
|
||||||
|
density = DE.THIN,
|
||||||
|
radius = 4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
@fixture(name="waterAdjacentCropBlob")
|
||||||
|
def createWaterAdjacentBlob(pack:ModPack):
|
||||||
|
yield CropPlacedFeature(
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "sugarcane",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.DUNES,
|
||||||
|
biomeFilters = BF([(WA.RIVER, WA.SWAMP)]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.COMMON,
|
||||||
|
),
|
||||||
|
plant = Patch(
|
||||||
|
name = "sugarcane",
|
||||||
|
blocks = "minecraft:sugarcane",
|
||||||
|
density = DE.CARPET,
|
||||||
|
immersion = IM.ADJACENT,
|
||||||
|
radius = 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
@fixture(name="submergedCropBlob")
|
||||||
|
def createSubmergedCropBlob(pack:ModPack):
|
||||||
|
yield CropPlacedFeature(
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "rice",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.SURFACE,
|
||||||
|
biomeFilters = BF([(WA.RIVER, WA.SWAMP)]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.UNCOMMON,
|
||||||
|
),
|
||||||
|
plant = Patch(
|
||||||
|
name = "rice",
|
||||||
|
blocks = "farmersdelight:wild_rice",
|
||||||
|
density = DE.PACKED,
|
||||||
|
immersion = IM.SUBMERGED,
|
||||||
|
radius = 6,
|
||||||
|
substrates = [ "minecraft:sand", "minecraft:dirt" ],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_farmCrop(farmCropBlob:JsonBlob):
|
||||||
|
assert dumps(farmCropBlob) == textwrap.dedent("""
|
||||||
|
{
|
||||||
|
"feature": "test:crop/potato",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"offset": [
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
"#minecraft:dirt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""").strip()
|
||||||
|
|
||||||
|
def test_submergedCrop(submergedCropBlob:JsonBlob):
|
||||||
|
assert dumps(submergedCropBlob) == textwrap.dedent("""
|
||||||
|
{
|
||||||
|
"feature": "test:crop/rice",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:water"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"offset": [
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
"minecraft:sand",
|
||||||
|
"minecraft:dirt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""").strip()
|
||||||
|
|
||||||
|
def test_waterAdjacentCrop(waterAdjacentCropBlob:JsonBlob):
|
||||||
|
assert dumps(waterAdjacentCropBlob) == textwrap.dedent("""
|
||||||
|
{
|
||||||
|
"feature": "test:crop/sugarcane",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"offset": [
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"blocks": [
|
||||||
|
"#minecraft:dirt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:any_of",
|
||||||
|
"predicates": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [
|
||||||
|
1,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:matching_fluids",
|
||||||
|
"fluids": [
|
||||||
|
"minecraft:water",
|
||||||
|
"minecraft:flowing_water"
|
||||||
|
],
|
||||||
|
"offset": [
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
-1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""").strip()
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
from mcpacker.model.altitude import Altitude
|
||||||
|
from mcpacker.format.json import JsonBlob
|
||||||
|
from mcpacker.model.flora.patch import Patch
|
||||||
|
from mcpacker.model.flora.plantspawn import PlantSpawn
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
|
||||||
|
import mcpacker.model.altitude as AL
|
||||||
|
import mcpacker.model.scarcity as SC
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class PatchPlacedFeature:
|
||||||
|
|
||||||
|
def __init__(self, pack:ModPack, spawn:PlantSpawn, altitude:Altitude):
|
||||||
|
self.altitude = altitude
|
||||||
|
self.pack = pack
|
||||||
|
self.spawn = spawn
|
||||||
|
|
||||||
|
def asJsonBlob(self) -> JsonBlob|None:
|
||||||
|
fullRange = self.spawn.habitat.altitude
|
||||||
|
band = AL.intersect(self.altitude, fullRange)
|
||||||
|
if not band: return None
|
||||||
|
|
||||||
|
kind = "tree"
|
||||||
|
if isinstance(self.spawn.plant, Patch):
|
||||||
|
kind = "patch"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"feature": f"{self.pack.name}:{kind}/{self.spawn.plant.name}",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "mincraft:rarity_filter",
|
||||||
|
"chance": self._getRarityChance(),
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:in_square",
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:biome",
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:height_range",
|
||||||
|
"height": {
|
||||||
|
"type": "minecraft:constant",
|
||||||
|
"value": {
|
||||||
|
"absolute": band.bottom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air",
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
"type": "minecraft:environment_scan",
|
||||||
|
"direction_of_search": "up",
|
||||||
|
"max_steps": min(32, band.top - band.bottom),
|
||||||
|
"target_condition": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Private Methods ##########################################################
|
||||||
|
|
||||||
|
def _getRarityChance(self) -> int:
|
||||||
|
return {
|
||||||
|
SC.ABSENT: 100000,
|
||||||
|
SC.RARE: 64,
|
||||||
|
SC.UNUSUAL: 32,
|
||||||
|
SC.SPARSE: 16,
|
||||||
|
SC.UNCOMMON: 8,
|
||||||
|
SC.COMMON: 3,
|
||||||
|
SC.CARPET: 2
|
||||||
|
}[self.spawn.ecotype.scarcity]
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
from mcpacker.format.datapack.placedfeature.patch import PatchPlacedFeature
|
||||||
|
from mcpacker.format.json import JsonBlob
|
||||||
|
from mcpacker.model.ecology.biomefilter import BiomeFilter as BF
|
||||||
|
from mcpacker.model.ecotype import Ecotype
|
||||||
|
from mcpacker.model.flora.patch import Patch
|
||||||
|
from mcpacker.model.flora.plantspawn import PlantSpawn
|
||||||
|
from mcpacker.model.flora.tree import Tree
|
||||||
|
from mcpacker.model.habitat import Habitat
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.json import dumps
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
import mcpacker.model.altitude as AL
|
||||||
|
import mcpacker.model.ecology.flora as FL
|
||||||
|
import mcpacker.model.ecology.heat as HE
|
||||||
|
import mcpacker.model.ecology.humidity as HU
|
||||||
|
import mcpacker.model.ecology.soil as SO
|
||||||
|
import mcpacker.model.ecology.water as WA
|
||||||
|
import mcpacker.model.flora.canopyshape as CA
|
||||||
|
import mcpacker.model.flora.density as DE
|
||||||
|
import mcpacker.model.flora.immersion as IM
|
||||||
|
import mcpacker.model.flora.trunkshape as TR
|
||||||
|
import mcpacker.model.scarcity as SC
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="pack")
|
||||||
|
def createModPack():
|
||||||
|
yield ModPack("test")
|
||||||
|
|
||||||
|
@fixture(name="farmPatchBlob")
|
||||||
|
def createFarmPatchBlob(pack:ModPack):
|
||||||
|
yield PatchPlacedFeature(
|
||||||
|
altitude = AL.UPLANDS,
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "potato",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.span(AL.UPLANDS, AL.HILLS),
|
||||||
|
biomeFilters = BF([FL.FOREST, HE.BOREAL, HU.DAMP, SO.ACIDIC]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.UNCOMMON,
|
||||||
|
),
|
||||||
|
plant = Patch(
|
||||||
|
name = "potato",
|
||||||
|
blocks = "farmersdelight:wild_potatoes",
|
||||||
|
density = DE.THIN,
|
||||||
|
radius = 4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
@fixture(name="waterAdjacentBlob")
|
||||||
|
def createWaterAdjacentBlob(pack:ModPack):
|
||||||
|
yield PatchPlacedFeature(
|
||||||
|
altitude = AL.DUNES,
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "sugarcane",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.DUNES,
|
||||||
|
biomeFilters = BF([(WA.RIVER, WA.SWAMP)]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.COMMON,
|
||||||
|
),
|
||||||
|
plant = Patch(
|
||||||
|
name = "sugarcane",
|
||||||
|
blocks = "minecraft:sugarcane",
|
||||||
|
density = DE.CARPET,
|
||||||
|
immersion = IM.ADJACENT,
|
||||||
|
radius = 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
@fixture(name="treeBlob")
|
||||||
|
def createTreeBlob(pack:ModPack):
|
||||||
|
yield PatchPlacedFeature(
|
||||||
|
altitude = AL.LOWLANDS,
|
||||||
|
pack = pack,
|
||||||
|
spawn = PlantSpawn(
|
||||||
|
name = "apple",
|
||||||
|
habitat = Habitat(
|
||||||
|
altitude = AL.LOWLANDS,
|
||||||
|
biomeFilters = BF([(FL.FOREST, FL.CLEARING), HE.TEMPERATE, SO.LOAMY]),
|
||||||
|
),
|
||||||
|
ecotype = Ecotype(
|
||||||
|
scarcity = SC.SPARSE,
|
||||||
|
),
|
||||||
|
plant = Tree(
|
||||||
|
name = "apple",
|
||||||
|
foliage = "fruitsdelight:apple_leaves",
|
||||||
|
log = "minecraft:oak_log",
|
||||||
|
trunkShape = TR.STRAIGHT,
|
||||||
|
trunkHeightMin = 3,
|
||||||
|
trunkHeightMax = 5,
|
||||||
|
canopyShape = CA.BLOB,
|
||||||
|
canopyHeight = 3,
|
||||||
|
canopyRadius = 2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).asJsonBlob()
|
||||||
|
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_farmPatch(farmPatchBlob:JsonBlob):
|
||||||
|
assert dumps(farmPatchBlob) == textwrap.dedent("""
|
||||||
|
{
|
||||||
|
"feature": "test:patch/potato",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "mincraft:rarity_filter",
|
||||||
|
"chance": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:in_square"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:biome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:height_range",
|
||||||
|
"height": {
|
||||||
|
"type": "minecraft:constant",
|
||||||
|
"value": {
|
||||||
|
"absolute": 92
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:environment_scan",
|
||||||
|
"direction_of_search": "up",
|
||||||
|
"max_steps": 32,
|
||||||
|
"target_condition": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""").strip()
|
||||||
|
|
||||||
|
def test_tree(treeBlob:JsonBlob):
|
||||||
|
assert dumps(treeBlob) == textwrap.dedent("""
|
||||||
|
{
|
||||||
|
"feature": "test:tree/apple",
|
||||||
|
"placement": [
|
||||||
|
{
|
||||||
|
"type": "mincraft:rarity_filter",
|
||||||
|
"chance": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:in_square"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:biome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:height_range",
|
||||||
|
"height": {
|
||||||
|
"type": "minecraft:constant",
|
||||||
|
"value": {
|
||||||
|
"absolute": 70
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:block_predicate_filter",
|
||||||
|
"predicate": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "minecraft:environment_scan",
|
||||||
|
"direction_of_search": "up",
|
||||||
|
"max_steps": 22,
|
||||||
|
"target_condition": {
|
||||||
|
"type": "minecraft:matching_blocks",
|
||||||
|
"blocks": "minecraft:air"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""").strip()
|
||||||
@@ -70,7 +70,22 @@ ALL = OVERGROUND + UNDERGROUND + UNDERWATER
|
|||||||
|
|
||||||
# Helper Functions #################################################################################
|
# Helper Functions #################################################################################
|
||||||
|
|
||||||
def span(*altitudes:Altitude):
|
def intersect(*altitudes:Altitude) -> Altitude|None:
|
||||||
|
if not altitudes: return None
|
||||||
|
|
||||||
|
bottom = altitudes[0].bottom
|
||||||
|
top = altitudes[0].top
|
||||||
|
|
||||||
|
for index in range(1, len(altitudes)):
|
||||||
|
bottom = max(bottom, altitudes[index].bottom)
|
||||||
|
top = min(top, altitudes[index].top)
|
||||||
|
|
||||||
|
if bottom >= top:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return Altitude(altitudes[0].name, bottom, top)
|
||||||
|
|
||||||
|
def span(*altitudes:Altitude) -> Altitude:
|
||||||
if not altitudes: return ANYWHERE
|
if not altitudes: return ANYWHERE
|
||||||
result = Altitude("", ANYWHERE.top, ANYWHERE.bottom)
|
result = Altitude("", ANYWHERE.top, ANYWHERE.bottom)
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,4 @@ from mcpacker.write.writer import Writer
|
|||||||
class BlockStateWriter(Writer):
|
class BlockStateWriter(Writer):
|
||||||
|
|
||||||
def doWrite(self):
|
def doWrite(self):
|
||||||
for mod in self.pack.resourcePack.mods:
|
pass
|
||||||
for blockState in mod.blockStates:
|
|
||||||
path = self.locator.blockStates() # filename?
|
|
||||||
# TODO: not implemented
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user