Add remaining flora & fauna spawns

This commit is contained in:
Andrew Miner
2025-10-20 18:27:19 -06:00
parent 464b68fcbe
commit 0a7fe05c4f
60 changed files with 2205 additions and 243 deletions
@@ -0,0 +1,7 @@
import mcpacker.format.datapack.biomemodifier.addfeature
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.format.datapack.biomemodifier.removefeature
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.format.datapack.biomemodifier.removespawn
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.format.datapack.generationstep
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.format.datapack.structure
# Tests ############################################################################################
def test_syntax():
pass
+59 -21
View File
@@ -1,7 +1,11 @@
from mcpacker.model.modpack import ModPack
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.format.report.composer import ReportComposer
from pathlib import Path
import mcpacker.model.core.altitude as AL
import mcpacker.model.core.fauna.location as LO
# Class ############################################################################################
@@ -10,29 +14,63 @@ class BiomeReport(ReportComposer):
def doCompose(self):
for biome in self.pack.world.biomes:
self.line(f"Biome: {biome.gameId} ({biome.name})")
self.indent() # biome
self._composeTraitsLine(biome)
self._composeGeologySection(biome)
self._composeFloraSection(biome)
self._composeFaunaSection(biome)
self.outdent() # biome
self.line()
self.indent()
needsDelimiter = False
self.text("Traits: ")
for trait in biome.traits():
if needsDelimiter: self.text(", ")
needsDelimiter = True
self.text(trait)
self.line()
def _composeGeologySection(self, biome:Biome):
self.line().line("Geology:").indent()
depositCount = 0
for deposit in self.pack.world.deposits:
if not deposit.acceptsBiome(biome): continue
self.line(f"{deposit.name} ({deposit.scarcity})")
depositCount += 1
self.line()
self.line("Deposits:")
self.indent()
depositCount = 0
for deposit in self.pack.world.deposits:
if not deposit.acceptsBiome(biome): continue
self.line(deposit.name)
depositCount += 1
if depositCount == 0:
self.line("<no deposits>")
self.outdent() # deposits
if depositCount == 0:
self.line("<no deposits>")
self.outdent()
def _composeFaunaSection(self, biome:Biome):
self.line().line("Fauna:").indent()
faunaLineCount = 0
for spawn in self.pack.world.mobSpawns:
altitude = None
for habitat in spawn.acceptedBy(biome):
if habitat.location == LO.CAVE: continue
altitude = AL.span(altitude or habitat.altitude, habitat.altitude)
self.outdent()
self.line()
if altitude != None:
self.line(f"{spawn.mob.name} @ {altitude}")
faunaLineCount += 1
if faunaLineCount == 0:
self.line("<no fauna>")
self.outdent() # fauna
def _composeFloraSection(self, biome:Biome):
self.line().line("Flora:").indent()
floraLineCount = 0
for spawn in self.pack.world.plantSpawns:
if not spawn.acceptsBiome(biome): continue
self.line(f"{spawn.plant.name} @ {spawn.altitude}")
floraLineCount += 1
if floraLineCount == 0:
self.line("<no flora>")
self.outdent() # flora
def _composeTraitsLine(self, biome:Biome):
needsDelimiter = False
self.line().text("Traits: ")
for trait in biome.traits():
if needsDelimiter: self.text(", ")
needsDelimiter = True
self.text(trait)
self.line()
+20 -9
View File
@@ -5,13 +5,12 @@ from mcpacker.model.modpack import ModPack
from pytest import fixture
from typing import Callable
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
@@ -47,18 +46,30 @@ def createReport(pack:ModPack):
# Tests ############################################################################################
def test_report(report):
assert str(report).strip() == textwrap.dedent("""
assert str(report).strip() == textwrap.dedent("""
Biome: minecraft:savanna (dallas)
Traits: field, sedimentary, subtropical, dry, sandy, inland
Deposits:
Geology:
<no deposits>
Flora:
<no flora>
Fauna:
<no fauna>
Biome: minecraft:plains (kansascity)
Traits: field, sedimentary, temperate, damp, loamy, inland
Deposits:
Geology:
<no deposits>
Flora:
<no flora>
Fauna:
<no fauna>
""").strip()
@@ -0,0 +1,60 @@
from mcpacker.model.core.flora.patch import Patch
from mcpacker.model.core.flora.tree import Tree
from mcpacker.format.report.composer import ReportComposer
from mcpacker.model.core.ecology.biometrait import BiomeTrait
from mcpacker.model.modpack import ModPack
from pathlib import Path
# Class ############################################################################################
class PlantSpawnReport(ReportComposer):
def doCompose(self):
for spawn in self.pack.world.plantSpawns:
self.line(f"Plant: {spawn.name}")
self.indent() # plant
if isinstance(spawn.plant, Patch):
patch:Patch = spawn.plant
self.line().line("Patch Biology:")
self.indent() # botany
self.text("blocks: ").line(", ".join(str(b) for b in patch.blocks))
self.text("immersion: ").line(patch.immersion)
self.text("radius: ").line(patch.radius)
self.text("density: ").text(patch.density).line(f" ({patch.attempts()} attempts)")
self.text("substrates: ").line(", ".join(str(s) for s in patch.substrates))
self.outdent() # botany
elif isinstance(spawn.plant, Tree):
tree:Tree = spawn.plant
self.line().line("Tree Biology:")
self.indent() # botany
self.text("foliage: ").line(tree.foliage)
self.text("log: ").line(tree.log)
self.text("trunkShape: ").line(tree.trunkShape)
self.text("trunkHeightMin: ").line(tree.trunkHeightMin)
self.text("trunkHeightMax: ").line(tree.trunkHeightMax)
self.text("canopyShape: ").line(tree.canopyShape)
self.text("canopyHeight: ").line(tree.canopyHeight)
self.text("canopyRadius: ").line(tree.canopyRadius)
self.outdent() # botany
self.line().line("Habitat:")
self.indent() # habitat
self.text("altitude: ").line(spawn.altitude)
self.text("biomeFilters: ").line(" -OR- ".join(str(f) for f in spawn.biomeFilters))
self.text("scarcity: ").line(spawn.scarcity)
self.outdent() # habitat
self.line().line("Biomes:")
self.indent() # biomes
biomes = self.pack.world.biomes.filter(lambda b: spawn.acceptsBiome(b))
for biome in biomes:
self.line(biome)
self.outdent() # biomes
self.outdent() # plant
self.line()
@@ -0,0 +1,7 @@
import mcpacker.format.report.plantspawnreport
# Tests ############################################################################################
def test_syntax():
pass
+8
View File
@@ -0,0 +1,8 @@
import mcpacker.format.templatecomposer
# Tests ############################################################################################
def test_syntax():
pass
+9 -1
View File
@@ -92,5 +92,13 @@ def span(*altitudes:Altitude):
if bottomAltitude == topAltitude:
return bottomAltitude
result = Altitude(f"{bottomAltitude.name} to {topAltitude.name}", bottom, top)
bottomName = bottomAltitude.name
if " to " in bottomName:
(bottomName, _) = bottomName.split(" to ")
topName = topAltitude.name
if " to " in topName:
(_, topName) = topName.split(" to ")
result = Altitude(f"{bottomName} to {topName}", bottom, top)
return result
+35
View File
@@ -0,0 +1,35 @@
from mcpacker.json import JsonBlob
from mcpacker.model.core.resourceid import ResourceId
from typing import Any
# Class ############################################################################################
class BlockState:
@staticmethod
def parse(value:"BlockState|str") -> "BlockState":
if isinstance(value, BlockState): return value
return BlockState(ResourceId.parse(value))
def __init__(self, gameId:ResourceId|str, properties:JsonBlob=None):
self.gameId = ResourceId.parse(gameId)
self.properties = properties
def __eq__(self, other:Any) -> bool:
if type(self) != type(other): return False
if self.gameId != other.gameId: return False
if self.properties != other.properties: return False
return True
def __hash__(self) -> int:
return hash((self.gameId, self.properties))
def __repr__(self) -> str:
return f"BlockState(gameId={self.gameId!r}, properties={self.properties!r})"
def __str__(self) -> str:
if not self.properties:
return str(self.gameId)
return f"{self.gameId}{self.properties}"
+21
View File
@@ -0,0 +1,21 @@
from pytest import fixture
from mcpacker.model.core.blockstate import BlockState
from mcpacker.model.core.resourceid import ResourceId
# Fixtures #########################################################################################
@fixture(name="block")
def createBlockState():
yield BlockState("oak_fence", { "waterlogged": "true" })
# Tests ############################################################################################
def test_repr(block):
assert repr(block) == (
"BlockState(" +
"gameId=ResourceId(isTag=False, mod='minecraft', name='oak_fence'), " +
"properties={'waterlogged': 'true'}" +
")"
)
+12 -4
View File
@@ -1,4 +1,5 @@
from collections.abc import Sequence
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biometrait import BiomeTrait
@@ -26,8 +27,8 @@ class BiomeFilter:
def __init__(
self,
required:Sequence[BiomeTrait|Sequence[BiomeTrait]]|None=None,
prohibited:Sequence[BiomeTrait]|None=None,
required:Sequence[BiomeTrait|ResourceId|Sequence[BiomeTrait]]|None=None,
prohibited:Sequence[BiomeTrait|ResourceId]|None=None,
):
self.required = required or []
self.prohibited = prohibited or []
@@ -45,6 +46,8 @@ class BiomeFilter:
for trait in self.required:
if isinstance(trait, BiomeTrait):
required.append(str(trait))
elif isinstance(trait, ResourceId):
required.append(str(trait))
else:
required.append("(" +
" or ".join([str(option) for option in trait]) +
@@ -59,7 +62,7 @@ class BiomeFilter:
else:
result = "".join([
"must:[", " and ".join(required), "], ",
"not:[", " and ".join(prohibited), "]",
"not:[", " or ".join(prohibited), "]",
])
return result
@@ -71,6 +74,8 @@ class BiomeFilter:
if isinstance(condition, BiomeTrait):
trait = condition
if trait not in biomeTraits: return False
elif isinstance(condition, ResourceId):
if condition != biome.gameId: return False
else:
traitOptions = condition
foundMatch = False
@@ -82,6 +87,9 @@ class BiomeFilter:
if not foundMatch: return False
for prohibitedTrait in self.prohibited:
if prohibitedTrait in biomeTraits: return False
if isinstance(prohibitedTrait, ResourceId):
if prohibitedTrait == biome.gameId: return False
else:
if prohibitedTrait in biomeTraits: return False
return True
@@ -1,5 +1,6 @@
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.resourceid import ResourceId
from pytest import fixture
import mcpacker.model.core.ecology.flora as F
@@ -27,6 +28,14 @@ def createDesertBiome():
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
)
@fixture(name="inDesert")
def createDesertFilter():
yield BiomeFilter([ResourceId.parse("minecraft:desert")])
@fixture(name="notInDesert")
def createNotDesertFilter():
yield BiomeFilter([], [ResourceId.parse("minecraft:desert")])
@fixture(name="fertile")
def createFertileFilter():
yield BiomeFilter([(S.LOAMY, S.PEATY)])
@@ -59,3 +68,11 @@ def test_requireOptions(fertile, desert, forest):
def test_vetoed(barrenNotSandy, desert):
assert not barrenNotSandy.accepts(desert)
def test_requiredBiome(inDesert, desert, forest):
assert inDesert.accepts(desert)
assert not inDesert.accepts(forest)
def test_prohibitedBiome(notInDesert, desert, forest):
assert not notInDesert.accepts(desert)
assert notInDesert.accepts(forest)
+17 -4
View File
@@ -1,7 +1,8 @@
from collections.abc import Iterable
from mcpacker.model.core.habitat import Habitat
from collections.abc import Iterable
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.spawn import Spawn
from mcpacker.model.core.spawn import Spawn
# Class ############################################################################################
@@ -12,9 +13,21 @@ class MobSpawn(Spawn):
"""
def __init__(self, mob:Mob, habitats:Iterable[Habitat]|Habitat|None=None):
super().__init__(habitats)
self.mob = mob
super().__init__(habitats)
def __str__(self) -> str:
return self.name
@property
def name(self) -> str:
return self.mob.name
def acceptedBy(self, biome:Biome) -> list[Habitat]:
result = []
for habitat in self.habitats:
if habitat.accepts(biome):
result.append(habitat)
return result
+1 -1
View File
@@ -27,7 +27,7 @@ def createMobSpawn(cow, fields):
# Tests ############################################################################################
def test_cowsInFields(spawn):
assert str(spawn) == (
assert repr(spawn) == (
"Spawn(" +
"habitats=[" +
"Habitat(" +
+44
View File
@@ -0,0 +1,44 @@
from typing import Any
# Class ############################################################################################
class CanopyShape:
def __init__(self, name:str):
self.name = name
def __eq__(self, other:Any) -> 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 __lt__(self, other:Any) -> bool:
if type(self) != type(other): raise ValueError()
return self.name < other.name
def __repr__(self) -> str:
return f"CanopyShape(name={repr(self.name)})"
def __str__(self) -> str:
return self.name
# Constants ########################################################################################
ACACIA = CanopyShape("acacia")
BLOB = CanopyShape("blob")
BUSH = CanopyShape("bush")
CHERRY = CanopyShape("cherry")
DARK_OAK = CanopyShape("dark_oak")
FANCY = CanopyShape("fancy")
JUNGLE = CanopyShape("jungle")
MEGA_PINE = CanopyShape("mega_pine")
PINE = CanopyShape("pine")
RANDOM_SPREAD = CanopyShape("random_spread")
SPRUCE = CanopyShape("spruce")
ALL = [ACACIA, BLOB, BUSH, CHERRY, DARK_OAK, FANCY, JUNGLE, MEGA_PINE, PINE, RANDOM_SPREAD, SPRUCE]
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.canopyshape
# Tests ############################################################################################
def test_syntax():
pass
+38
View File
@@ -0,0 +1,38 @@
from typing import Any
# Class ############################################################################################
class Density:
def __init__(self, name:str):
self.name = name
def __eq__(self, other:Any) -> 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 __lt__(self, other:Any) -> bool:
if type(self) != type(other): raise ValueError()
return self.name < other.name
def __repr__(self) -> str:
return f"Density(name={repr(self.name)})"
def __str__(self) -> str:
return self.name
# Constants ########################################################################################
SPARSE = Density("sparse")
THIN = Density("thin")
THICK = Density("thick")
PACKED = Density("packed")
CARPET = Density("carpet")
ALL = [SPARSE, THIN, THICK, PACKED, CARPET]
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.density
# Class ############################################################################################
def test_syntax():
pass
+37
View File
@@ -0,0 +1,37 @@
from typing import Any
# Class ############################################################################################
class Immersion:
def __init__(self, name:str):
self.name = name
def __eq__(self, other:Any) -> 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 __lt__(self, other:Any) -> bool:
if type(self) != type(other): raise ValueError()
return self.name < other.name
def __repr__(self) -> str:
return f"Immersion(name={repr(self.name)})"
def __str__(self) -> str:
return self.name
# Constants ########################################################################################
DRY = Immersion("dry")
ADJACENT = Immersion("adjacent")
SUBMERGED = Immersion("submerged")
ALL = [DRY, ADJACENT, SUBMERGED]
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.immersion
# Tests ############################################################################################
def test_syntax():
pass
+87
View File
@@ -0,0 +1,87 @@
from collections.abc import Iterable
from mcpacker.model.core.blockstate import BlockState
from mcpacker.model.core.flora.density import Density
from mcpacker.model.core.flora.immersion import Immersion
from mcpacker.model.core.flora.plant import Plant
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.core.scarcity import Scarcity
import math
import mcpacker.model.core.flora.density as DE
import mcpacker.model.core.flora.immersion as IM
# Class ############################################################################################
class Patch(Plant):
def __init__(
self,
name:str,
blocks:Iterable[BlockState|str]|BlockState|str,
density:Density=DE.THICK,
radius:int=4,
substrates:Iterable[ResourceId]|Iterable[str]|ResourceId|str|None=None,
immersion:Immersion=IM.DRY,
):
super().__init__(name)
if isinstance(blocks, str) or isinstance(blocks, BlockState):
blocks = [blocks]
if not substrates:
substrates = ["#minecraft:dirt"]
if not isinstance(substrates, Iterable):
substrates = [substrates]
self.blocks = [BlockState.parse(b) for b in blocks]
self.density = density
self.immersion = immersion
self.radius = radius
self.substrates = [ResourceId.parse(s) for s in substrates]
def __repr__(self) -> str:
return (
"Patch("
f"blocks={self.blocks!r}, "
f"density={self.density!r}, "
f"immersion={self.immersion!r}, "
f"radius={self.radius!r}, "
f"substrates={self.substrates!r}"
")"
)
def attempts(self, successRate:float=0.25) -> int:
"""
Estimate how many placement attempts a generator should make for this patch.
The value models repeated random placement within a circular area until the expected
fraction of successful placements (`coverage`) for the patch's density is reached. It
accounts for both failed placements (controlled by `successRate`) and duplicate hits on
alreadyfilled blocks.
The relationship is derived from the expected coverage equation:
coverage = 1 - (1 - successRate / area) ** attempts
which rearranges to the continuous approximation:
attempts = -(area / successRate) * ln(1 - coverage)
where:
area = π * radius²
successRate = probability that any single attempt succeeds
coverage = target fill fraction for this patch's density
see ChatGPT conversation for full details: http://bit.ly/4neps2i
"""
coverage = {
DE.CARPET: 0.99,
DE.PACKED: 0.8,
DE.THICK: 0.6,
DE.THIN: 0.4,
DE.SPARSE: 0.2,
}[self.density]
return math.ceil(max(1/successRate,
-(math.pi * self.radius * self.radius / successRate) * math.log(1 - coverage)
))
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.plant
# Tests ############################################################################################
def test_syntax():
pass
+12
View File
@@ -0,0 +1,12 @@
# Class ############################################################################################
class Plant:
def __init__(self, name:str):
self.name = name
def __repr__(self) -> str:
return f"Plant(name={repr(self.name)})"
def __str__(self) -> str:
return self.name
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.plant
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.flora.plant import Plant
# Class ############################################################################################
class PlantCatalog(Catalog[Plant]):
pass
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.plantcatalog
# Tests ############################################################################################
def test_syntax():
pass
+51
View File
@@ -0,0 +1,51 @@
from collections.abc import Iterable
from mcpacker.model.core.altitude import Altitude
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.flora.plant import Plant
from mcpacker.model.core.scarcity import Scarcity
import mcpacker.model.core.altitude as AL
import mcpacker.model.core.scarcity as SC
# Class ############################################################################################
class PlantSpawn:
def __init__(
self,
plant:Plant,
altitude:Altitude=AL.ANYWHERE,
biomeFilters:Iterable[BiomeFilter]|BiomeFilter|None=None,
scarcity:Scarcity=SC.SPARSE,
):
if not biomeFilters:
biomeFilters = BiomeFilter()
if not isinstance(biomeFilters, Iterable):
biomeFilters = [biomeFilters]
self.altitude = altitude
self.biomeFilters = list(biomeFilters)
self.plant = plant
self.scarcity = scarcity
def __repr__(self) -> str:
return "".join([
"PlantSpawn(",
"altitude=", repr(self.altitude), ", ",
"biomeFilters=", repr(self.biomeFilters), ", ",
"plant=", repr(self.plant), ", ",
"scarcity=", repr(self.scarcity),
")"
])
@property
def name(self) -> str:
return self.plant.name
def acceptsBiome(self, biome:Biome) -> bool:
for biomeFilter in self.biomeFilters:
if biomeFilter.accepts(biome): return True
return False
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.plantspawn
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.flora.plantspawn import PlantSpawn
# Class ############################################################################################
class PlantSpawnCatalog(Catalog[PlantSpawn]):
pass
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.plantspawncatalog
# Tests ############################################################################################
def test_syntax():
pass
+50
View File
@@ -0,0 +1,50 @@
from mcpacker.model.core.flora.canopyshape import CanopyShape
from mcpacker.model.core.flora.trunkshape import TrunkShape
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.core.flora.plant import Plant
import mcpacker.model.core.flora.canopyshape as CA
import mcpacker.model.core.flora.trunkshape as TR
# Class ############################################################################################
class Tree(Plant):
def __init__(
self,
name:str,
foliage:ResourceId|str,
log:ResourceId|str,
trunkShape:TrunkShape=TR.STRAIGHT,
trunkHeightMin:int=3,
trunkHeightMax:int=5,
canopyShape:CanopyShape=CA.BLOB,
canopyHeight:int=3,
canopyRadius:int=2,
):
super().__init__(name)
self.foliage = foliage
self.log = log
self.trunkShape = trunkShape
self.trunkHeightMin = trunkHeightMin
self.trunkHeightMax = trunkHeightMax
self.canopyShape = canopyShape
self.canopyHeight = canopyHeight
self.canopyRadius = canopyRadius
def __repr__(self) -> str:
return "".join([
"Tree(",
"name=", repr(self.name), ", ",
"foliage=", repr(self.foliage), ", ",
"log=", repr(self.log), ", ",
"trunkShape=", repr(self.trunkShape), ", ",
"trunkHeightMin=", repr(self.trunkHeightMin), ", ",
"trunkHeightMax=", repr(self.trunkHeightMax), ", ",
"canopyShape=", repr(self.canopyShape), ", ",
"canopyHeight=", repr(self.canopyHeight), ", ",
"canopyRadius=", repr(self.canopyRadius),
")"
])
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.tree
# Tests ############################################################################################
def test_syntax():
pass
+39
View File
@@ -0,0 +1,39 @@
from typing import Any
# Class ############################################################################################
class TrunkShape:
def __init__(self, name:str):
self.name = name
def __eq__(self, other:Any) -> 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 __lt__(self, other:Any) -> bool:
if type(self) != type(other): raise ValueError()
return self.name < other.name
def __repr__(self) -> str:
return f"Density(name={repr(self.name)})"
def __str__(self) -> str:
return self.name
# Constants ########################################################################################
STRAIGHT = TrunkShape("straight")
FORKING = TrunkShape("forking")
GIANT = TrunkShape("giant")
MEGA_JUNGLE = TrunkShape("mega_jungle")
DARK_OAK = TrunkShape("dark_oak")
FANCY = TrunkShape("fancy")
ALL = [STRAIGHT, FORKING, GIANT, MEGA_JUNGLE, DARK_OAK, FANCY]
@@ -0,0 +1,7 @@
import mcpacker.model.core.flora.trunkshape
# Tests ############################################################################################
def test_syntax():
pass
+24 -20
View File
@@ -1,16 +1,17 @@
from collections.abc import Iterable
from mcpacker.model.core.altitude import Altitude
from collections.abc import Iterable
from mcpacker.model.core.altitude import Altitude
from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.fauna.group import Group
from mcpacker.model.core.fauna.location import Location
from mcpacker.model.core.scarcity import Scarcity
from mcpacker.model.core.season import Season
from mcpacker.model.core.fauna.group import Group
from mcpacker.model.core.fauna.location import Location
from mcpacker.model.core.scarcity import Scarcity
from mcpacker.model.core.season import Season
import mcpacker.model.core.altitude as A
import mcpacker.model.core.fauna.group as G
import mcpacker.model.core.altitude as A
import mcpacker.model.core.fauna.group as G
import mcpacker.model.core.fauna.location as L
import mcpacker.model.core.scarcity as C
import mcpacker.model.core.season as E
import mcpacker.model.core.scarcity as C
import mcpacker.model.core.season as E
# Class ############################################################################################
@@ -63,6 +64,19 @@ class Habitat:
")"
]])
def accepts(self, biome:Biome) -> bool:
return self.biomeFilter.accepts(biome)
def collect(self) -> "Iterable[Habitat]":
stack:list[Habitat] = []
current:Habitat|None = self
while current:
stack.append(current)
current = current._source
while stack:
yield stack.pop()
def derive(
self,
*,
@@ -84,13 +98,3 @@ class Habitat:
result._source = self
return result
def collect(self) -> "Iterable[Habitat]":
stack:list[Habitat] = []
current:Habitat|None = self
while current:
stack.append(current)
current = current._source
while stack:
yield stack.pop()
+4 -8
View File
@@ -11,14 +11,10 @@ class Spawn:
def __init__(self, habitats:Iterable[Habitat]|Habitat|None=None):
if isinstance(habitats, Habitat):
habitats = habitats.collect()
self.habitats = habitats or []
habitats = list(habitats.collect())
self.habitats = list(habitats or [])
def __repr__(self) -> str:
return (
"Spawn(" +
f"habitats=[{', '.join([repr(h) for h in self.habitats])}]" +
")"
)
return f"Spawn(habitats={self.habitats!r})"
+33 -12
View File
@@ -1,10 +1,12 @@
from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog
from mcpacker.model.core.fauna.mobcatalog import MobCatalog
from mcpacker.model.core.fauna.mobspawncatalog import MobSpawnCatalog
from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog
from mcpacker.model.core.fauna.mobcatalog import MobCatalog
from mcpacker.model.core.fauna.mobspawncatalog import MobSpawnCatalog
from mcpacker.model.core.flora.plantcatalog import PlantCatalog
from mcpacker.model.core.flora.plantspawncatalog import PlantSpawnCatalog
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
from mcpacker.model.core.material.blockcatalog import BlockCatalog
from mcpacker.model.core.material.itemcatalog import ItemCatalog
# Class ############################################################################################
@@ -19,12 +21,31 @@ class World:
items:ItemCatalog|None=None,
minerals:MineralCatalog|None=None,
mobs:MobCatalog|None=None,
mobSpawns:MobSpawnCatalog|None=None
mobSpawns:MobSpawnCatalog|None=None,
plants:PlantCatalog|None=None,
plantSpawns:PlantSpawnCatalog|None=None,
):
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()
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()
self.mobSpawns = mobSpawns or MobSpawnCatalog()
self.plants = plants or PlantCatalog()
self.plantSpawns = plantSpawns or PlantSpawnCatalog()
def __repr__(self) -> str:
return "".join([
"World(",
"biomes=", repr(self.biomes), ", ",
"blocks=", repr(self.blocks), ", ",
"deposits=", repr(self.deposits), ", ",
"items=", repr(self.items), ", ",
"minerals=", repr(self.minerals), ", ",
"mobs=", repr(self.mobs), ", ",
"mobSpawns=", repr(self.mobSpawns), ", ",
"plants=", repr(self.plants), ", ",
"plantSpawns=", repr(self.plantSpawns),
")"
])
@@ -0,0 +1,7 @@
import mcpacker.model.resourcepack.model
# Tests ############################################################################################
def test_syntax():
pass
+2 -2
View File
@@ -111,7 +111,7 @@ def addBiomes(pack:ModPack):
))
biomes.add(Biome("kola", "minecraft:snowy_taiga",
FL.BARREN, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND
FL.FOREST, GE.METAMORPHIC, HE.FROZEN, HU.DAMP, SO.ACIDIC, WA.INLAND
))
biomes.add(Biome("kyoto", "minecraft:cherry_grove",
@@ -123,7 +123,7 @@ def addBiomes(pack:ModPack):
))
biomes.add(Biome("memphis", "minecraft:river",
FL.CLEARING, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.RIVER
FL.BARREN, GE.SEDIMENTARY, HE.TEMPERATE, HU.WET, SO.SANDY, WA.RIVER
))
biomes.add(Biome("minsk", "minecraft:old_growth_birch_forest",
@@ -35,7 +35,7 @@ def addDeposits(pack:ModPack):
deposits.add(GeodeDeposit(
name = "geode_kimberlite",
altitude = AL.span(AL.MANTLE, AL.CRUST),
biomeFilters = BF([GE.IGNEOUS]),
biomeFilters = BF([GE.IGNEOUS, SO.ROCKY, WA.INLAND]),
scarcity = SC.SPARSE,
))
@@ -126,10 +126,7 @@ def addDeposits(pack:ModPack):
deposits.add(MineralDeposit(
name = "sedimentary_iron",
altitude = AL.span(AL.OVERBURDEN, AL.SOIL),
biomeFilters = BF([
FL.within(FL.CANOPY, FL.CLEARING),
(HE.TEMPERATE, HE.BOREAL)
]),
biomeFilters = BF([SO.PEATY]),
bulk = BU.LARGE,
inclusions = [I(minerals["iron"], 100)],
proportion = PR.LODE,
@@ -139,7 +136,7 @@ def addDeposits(pack:ModPack):
deposits.add(MineralDeposit(
name = "serpentine_nickel",
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([GE.METAMORPHIC, (HU.DAMP, HU.WET), (SO.ACIDIC, SO.ROCKY)]),
biomeFilters = BF([GE.METAMORPHIC, HU.DAMP, SO.ACIDIC]),
bulk = BU.SMALL,
inclusions = [I(minerals["nickel"], 70), I(minerals["iron"], 30)],
proportion = PR.LENS,
@@ -171,7 +168,7 @@ def addDeposits(pack:ModPack):
deposits.add(MineralDeposit(
name = "fumarole_sulfur",
altitude = AL.CRUST,
biomeFilters = BF([GE.IGNEOUS]),
biomeFilters = BF([GE.IGNEOUS, SO.ROCKY, WA.INLAND]),
bulk = BU.MEDIUM,
inclusions = [I(minerals["sulfur"], 100)],
proportion = PR.VENT,
@@ -230,7 +227,6 @@ def addDeposits(pack:ModPack):
name = "seam_bituminouscoal",
altitude = AL.span(AL.CRUST, AL.OVERBURDEN),
biomeFilters = [
BF([FL.FOREST, GE.SEDIMENTARY, HE.TEMPERATE]),
BF([HE.BOREAL, GE.METAMORPHIC, (SO.ACIDIC, SO.ROCKY)]),
],
bulk = BU.HUGE,
+371 -152
View File
@@ -1,22 +1,23 @@
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.mobspawn import MobSpawn
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.modpack import ModPack
from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.fauna.mobcatalog import MobCatalog
from mcpacker.model.core.fauna.mobspawn import MobSpawn
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.modpack import ModPack
import mcpacker.model.core.altitude as AL
import mcpacker.model.core.ecology.flora as FL
import mcpacker.model.core.ecology.geology as GE
import mcpacker.model.core.ecology.heat as HE
import mcpacker.model.core.altitude as AL
import mcpacker.model.core.ecology.flora as FL
import mcpacker.model.core.ecology.geology as GE
import mcpacker.model.core.ecology.heat as HE
import mcpacker.model.core.ecology.humidity as HU
import mcpacker.model.core.ecology.soil as SO
import mcpacker.model.core.ecology.water as WA
import mcpacker.model.core.fauna.active as AC
import mcpacker.model.core.fauna.group as GR
import mcpacker.model.core.fauna.location as LO
import mcpacker.model.core.scarcity as SC
import mcpacker.model.core.season as SE
import mcpacker.model.core.ecology.soil as SO
import mcpacker.model.core.ecology.water as WA
import mcpacker.model.core.fauna.active as AC
import mcpacker.model.core.fauna.group as GR
import mcpacker.model.core.fauna.location as LO
import mcpacker.model.core.scarcity as SC
import mcpacker.model.core.season as SE
# Constants ########################################################################################
@@ -26,11 +27,30 @@ def addMobSpawns(pack:ModPack):
spawns = pack.world.mobSpawns
spawns.add(
MobSpawn(mobs["animalplus:raccoon"])
MobSpawn(mobs["animalplus:raccoon"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilter = BF([(FL.CANOPY, FL.FOREST), HE.within(HE.TEMPERATE, HE.BOREAL)]),
seasons = SE.exclude(SE.WINTER),
group = GR.merge(GR.SOLO, GR.PAIR),
scarcity = SC.UNCOMMON,
).derive(
seasons = SE.WINTER,
scarcity = SC.SPARSE,
)
)
)
spawns.add(
MobSpawn(mobs["animalplus:red_panda"])
MobSpawn(mobs["animalplus:red_panda"],
Habitat(
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilter = BF([ResourceId.parse("bamboo_forest")]),
seasons = SE.ALL,
group = GR.merge(GR.SOLO, GR.PAIR),
scarcity = SC.SPARSE,
)
)
)
spawns.add(
@@ -60,17 +80,21 @@ def addMobSpawns(pack:ModPack):
spawns.add(
MobSpawn(mobs["minecraft:armadillo"],
Habitat(
altitude = AL.LOWLANDS,
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]),
seasons = SE.SUMMER,
group = GR.merge(GR.SOLO, GR.PAIR),
scarcity = SC.COMMON
altitude = AL.LOWLANDS,
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY, SO.CLAYEY]),
seasons = SE.SUMMER,
group = GR.merge(GR.SOLO, GR.PAIR),
scarcity = SC.COMMON
).derive(
altitude = AL.UPLANDS, scarcity = SC.SPARSE,
altitude = AL.UPLANDS,
scarcity = SC.SPARSE,
).derive(
altitude = AL.LOWLANDS, seasons = SE.exclude(SE.SUMMER), scarcity = SC.UNCOMMON,
altitude = AL.LOWLANDS,
scarcity = SC.UNCOMMON,
seasons = SE.exclude(SE.SUMMER),
).derive(
altitude = AL.UPLANDS, scarcity = SC.UNUSUAL,
altitude = AL.UPLANDS,
scarcity = SC.UNUSUAL,
)
)
)
@@ -79,25 +103,21 @@ def addMobSpawns(pack:ModPack):
MobSpawn(mobs["minecraft:blaze"],
Habitat(
altitude = AL.PLUTONIC,
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:bogged"])
)
spawns.add(
MobSpawn(mobs["bearminimum:brown_bear"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.ALPINE),
altitude = AL.span(AL.LOWLANDS, AL.ALPINE),
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]),
seasons = SE.AUTUMN,
group = GR.SOLO,
scarcity = SC.SPARSE
seasons = SE.AUTUMN,
group = GR.SOLO,
scarcity = SC.SPARSE
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL
).derive(
@@ -124,9 +144,9 @@ def addMobSpawns(pack:ModPack):
MobSpawn(mobs["minecraft:cave_spider"],
Habitat(
altitude = AL.span(AL.OVERBURDEN, AL.HILLS),
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
)
)
@@ -134,21 +154,14 @@ def addMobSpawns(pack:ModPack):
spawns.add(
MobSpawn(mobs["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,
altitude = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilter = BF([(FL.CANOPY, FL.FOREST), HE.TROPICAL, HU.WET, WA.INLAND]),
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,
seasons = SE.DRY,
scarcity = SC.UNCOMMON,
)
)
)
@@ -156,14 +169,14 @@ def addMobSpawns(pack:ModPack):
spawns.add(
MobSpawn(mobs["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,
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF([FL.CLEARING, HE.TROPICAL, HU.WET], [SO.FUNGAL]),
seasons = SE.SUMMER,
group = GR.TROUP,
scarcity = SC.COMMON,
).derive(
seasons = SE.exclude(SE.SUMMER),
scarcity = SC.UNCOMMON
seasons = SE.exclude(SE.SUMMER),
scarcity = SC.UNCOMMON
)
)
)
@@ -171,14 +184,11 @@ def addMobSpawns(pack:ModPack):
spawns.add(
MobSpawn(mobs["minecraft:cod"],
Habitat(
altitude = AL.span(AL.SHALLOWS, AL.DEEPS),
biomeFilter = BF([WA.OCEAN, [HE.TEMPERATE, HE.BOREAL]]),
seasons = SE.ALL,
group = GR.HERD,
scarcity = SC.COMMON,
).derive(
biomeFilter = BF([WA.OCEAN, HE.FROZEN]),
scarcity = SC.SPARSE,
altitude = AL.span(AL.SHALLOWS, AL.DEEPS),
biomeFilter = BF([HE.BOREAL, WA.OCEAN]),
seasons = SE.ALL,
group = GR.HERD,
scarcity = SC.COMMON,
)
)
)
@@ -198,12 +208,12 @@ def addMobSpawns(pack:ModPack):
),
seasons = [SE.SPRING, SE.SUMMER],
group = GR.HERD,
scarcity = SC.COMMON,
scarcity = SC.SPARSE,
).derive(
altitude = AL.LOWLANDS,
seasons = [SE.AUTUMN, SE.WINTER],
group = GR.TROUP,
scarcity = SC.SPARSE,
scarcity = SC.UNUSUAL,
)
)
)
@@ -215,10 +225,10 @@ def addMobSpawns(pack:ModPack):
biomeFilter = BF([WA.COAST, [HE.TROPICAL, HE.SUBTROPICAL]]),
seasons = SE.ALL,
group = GR.SOLO,
scarcity = SC.COMMON,
scarcity = SC.UNCOMMON,
).derive(
biomeFilter = BF([WA.COAST, [HE.TEMPERATE, HE.BOREAL]]),
scarcity = SC.UNCOMMON,
scarcity = SC.SPARSE,
)
)
)
@@ -245,8 +255,9 @@ def addMobSpawns(pack:ModPack):
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY, FL.FIELD]),
seasons = [SE.SUMMER, SE.AUTUMN],
group = GR.FAMILY,
scarcity = SC.UNCOMMON,
scarcity = SC.SPARSE,
).derive(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
seasons = [SE.WINTER, SE.SPRING],
scarcity = SC.SPARSE,
)
@@ -267,145 +278,353 @@ def addMobSpawns(pack:ModPack):
))
spawns.add(
MobSpawn(mobs["minecraft:frog"])
MobSpawn(mobs["minecraft:frog"],
Habitat(
altitude = AL.span(AL.SURFACE, AL.DUNES),
biomeFilter = BF([(HE.TROPICAL, HE.TEMPERATE), HU.WET, WA.SWAMP]),
group = GR.HERD,
scarcity = SC.COMMON,
seasons = [SE.SUMMER],
).derive(
seasons = [SE.SPRING],
scarcity = SC.SPARSE,
).derive(
seasons = [SE.AUTUMN],
scarcity = SC.UNUSUAL,
).derive(
seasons = [SE.WINTER],
scarcity = SC.ABSENT,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:glow_squid"])
MobSpawn(mobs["minecraft:glow_squid"],
Habitat(
altitude = AL.ABYSS,
biomeFilter = BF([WA.OCEAN], [HE.FROZEN]),
group = GR.SOLO,
location = LO.WATER,
scarcity = SC.RARE,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:goat"])
MobSpawn(mobs["minecraft:goat"],
Habitat(
altitude = AL.span(AL.HILLS, AL.CRAGS),
biomeFilter = BF([(HE.BOREAL, HE.FROZEN), SO.ROCKY]),
group = GR.FAMILY,
scarcity = SC.UNCOMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:horse"])
MobSpawn(mobs["minecraft:horse"],
Habitat(
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilter = BF(
[FL.FIELD, (HE.SUBTROPICAL, HE.TEMPERATE), (SO.LOAMY, SO.PEATY, SO.SANDY)]
),
group = GR.HERD,
scarcity = SC.UNUSUAL,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:husk"])
MobSpawn(mobs["minecraft:llama"],
Habitat(
altitude = AL.span(AL.ALPINE, AL.PEAKS),
biomeFilter = BF([(HE.BOREAL, HE.FROZEN), SO.ROCKY]),
group = GR.HERD,
scarcity = SC.UNCOMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:llama"])
MobSpawn(mobs["minecraft:magma_cube"],
Habitat(
altitude = AL.PLUTONIC,
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:magma_cube"])
MobSpawn(mobs["minecraft:mooshroom"],
Habitat(
altitude = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilter = BF([SO.FUNGAL]),
group = GR.HERD,
scarcity = SC.UNCOMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:mooshroom"])
MobSpawn(mobs["minecraft:ocelot"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilter = BF([FL.CANOPY, HE.TROPICAL, HU.WET]),
group = GR.SOLO,
scarcity = SC.RARE,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:mule"])
MobSpawn(mobs["minecraft:panda"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF([ResourceId.parse("bamboo_forest")]),
group = GR.SOLO,
scarcity = SC.UNUSUAL,
seasons = SE.exclude(SE.SPRING),
).derive(
group = GR.PAIR,
seasons = SE.SPRING,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:ocelot"])
MobSpawn(mobs["minecraft:parrot"],
Habitat(
altitude = AL.span(AL.DUNES, AL.HILLS),
biomeFilter = BF([(FL.CANOPY, FL.FOREST), HE.TROPICAL, HU.WET]),
group = GR.PAIR,
scarcity = SC.COMMON,
seasons = SE.ALL,
).derive(
biomeFilter = BF([FL.CLEARING, HE.TROPICAL, HU.WET], [SO.FUNGAL]),
scarcity = SC.UNCOMMON,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:panda"])
MobSpawn(mobs["minecraft:pig"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilter = BF([
FL.within(FL.CANOPY, FL.CLEARING),
HE.within(HE.SUBTROPICAL, HE.TEMPERATE)
]),
group = GR.TROUP,
scarcity = SC.COMMON,
seasons = [SE.SUMMER],
).derive(
scarcity = SC.UNCOMMON,
seasons = SE.exclude(SE.SUMMER),
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:parrot"])
MobSpawn(mobs["minecraft:polar_bear"],
Habitat(
altitude = AL.DUNES,
biomeFilter = BF([HE.FROZEN, (WA.COAST, WA.OCEAN)]),
group = GR.PAIR,
scarcity = SC.UNUSUAL,
seasons = [SE.SPRING, SE.WINTER]
).derive(
group = GR.SOLO,
seasons = [SE.SUMMER, SE.AUTUMN],
scarcity = SC.RARE,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:pig"])
MobSpawn(mobs["minecraft:pufferfish"],
Habitat(
altitude = AL.SHALLOWS,
biomeFilter = BF([(HE.TEMPERATE, HE.TROPICAL), WA.OCEAN]),
group = GR.TROUP,
location = LO.WATER,
scarcity = SC.UNCOMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:polar_bear"])
MobSpawn(mobs["minecraft:rabbit"],
Habitat(
altitude = AL.span(AL.DUNES, AL.ALPINE),
biomeFilter = BF([
FL.within(FL.CANOPY, FL.FIELD),
HE.within(HE.SUBTROPICAL, HE.BOREAL),
WA.INLAND,
]),
group = GR.FAMILY,
scarcity = SC.COMMON,
seasons = [SE.SPRING],
).derive(
scarcity = SC.SPARSE,
seasons = [SE.SUMMER, SE.AUTUMN],
).derive(
scarcity = SC.SPARSE,
seasons = [SE.WINTER],
).derive(
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilter = BF([FL.BARREN, HE.TROPICAL, HU.DRY]),
group = GR.PAIR,
scarcity = SC.SPARSE,
seasons = SE.exclude(SE.SUMMER),
).derive(
scarcity = SC.UNUSUAL,
seasons = [SE.SUMMER],
).derive(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF([FL.within(FL.FOREST, FL.FIELD), HE.FROZEN]),
scarcity = SC.SPARSE,
seasons = SE.exclude(SE.WINTER),
).derive(
scarcity = SC.UNUSUAL,
seasons = [SE.WINTER],
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:pufferfish"])
MobSpawn(mobs["minecraft:salmon"],
Habitat(
altitude = AL.span(AL.SURFACE, AL.SHALLOWS),
biomeFilter = BF([WA.RIVER], [HE.FROZEN]),
group = GR.HERD,
scarcity = SC.COMMON,
seasons = [SE.AUTUMN],
).derive(
scarcity = SC.UNCOMMON,
seasons = [SE.SPRING],
).derive(
seasons = [SE.SUMMER, SE.WINTER],
scarcity = SC.ABSENT,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:rabbit"])
MobSpawn(mobs["minecraft:sheep"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF([FL.within(FL.FOREST, FL.FIELD), HE.BOREAL]),
group = GR.HERD,
scarcity = SC.UNCOMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:salmon"])
MobSpawn(mobs["minecraft:slime"],
Habitat(
altitude = AL.span(AL.SURFACE, AL.DUNES),
biomeFilter = BF([HE.TEMPERATE, WA.SWAMP]),
group = GR.SOLO,
scarcity = SC.UNCOMMON,
seasons = [SE.SPRING],
).derive(
scarcity = SC.UNUSUAL,
seasons = SE.exclude(SE.SPRING),
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:sheep"])
MobSpawn(mobs["minecraft:spider"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilter = BF([FL.CANOPY, HE.TEMPERATE]),
group = GR.SOLO,
scarcity = SC.COMMON,
seasons = [SE.SUMMER],
).derive(
scarcity = SC.UNCOMMON,
seasons = [SE.SPRING, SE.AUTUMN],
).derive(
scarcity = SC.SPARSE,
seasons = [SE.WINTER],
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:skeleton"])
MobSpawn(mobs["minecraft:squid"],
Habitat(
altitude = AL.DEEPS,
biomeFilter = BF([WA.OCEAN], [HE.FROZEN]),
group = GR.SOLO,
location = LO.WATER,
scarcity = SC.SPARSE,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:slime"])
MobSpawn(mobs["minecraft:tropical_fish"],
Habitat(
altitude = AL.SHALLOWS,
biomeFilter = BF([HE.TROPICAL, WA.OCEAN]),
group = GR.HERD,
location = LO.WATER,
scarcity = SC.COMMON,
seasons = SE.ALL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:spider"])
MobSpawn(mobs["minecraft:turtle"],
Habitat(
altitude = AL.span(AL.SURFACE, AL.SHALLOWS),
biomeFilter = BF([HE.within(HE.TROPICAL, HE.SUBTROPICAL), WA.OCEAN]),
group = GR.SOLO,
scarcity = SC.SPARSE,
seasons = SE.ALL,
).derive(
altitude = AL.DUNES,
biomeFilter = BF([HE.within(HE.TROPICAL, HE.SUBTROPICAL), WA.COAST]),
group = GR.SOLO,
scarcity = SC.UNUSUAL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:squid"])
)
spawns.add(
MobSpawn(mobs["minecraft:tropical_fish"])
)
spawns.add(
MobSpawn(mobs["minecraft:turtle"])
)
spawns.add(
MobSpawn(mobs["minecraft:vex"])
)
spawns.add(
MobSpawn(mobs["minecraft:villager"])
)
spawns.add(
MobSpawn(mobs["minecraft:vindicator"])
)
spawns.add(
MobSpawn(mobs["minecraft:wandering_trader"])
)
spawns.add(
MobSpawn(mobs["minecraft:warden"])
)
spawns.add(
MobSpawn(mobs["minecraft:witch"])
)
spawns.add(
MobSpawn(mobs["minecraft:wither_skeleton"])
)
spawns.add(
MobSpawn(mobs["minecraft:wither"])
)
spawns.add(
MobSpawn(mobs["minecraft:wolf"])
)
spawns.add(
MobSpawn(mobs["minecraft:zoglin"])
)
spawns.add(
MobSpawn(mobs["minecraft:zombie_villager"])
)
spawns.add(
MobSpawn(mobs["minecraft:zombie"])
MobSpawn(mobs["minecraft:wolf"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF([FL.CANOPY, HE.TEMPERATE, WA.INLAND]),
group = GR.TROUP,
scarcity = SC.COMMON,
seasons = SE.ALL,
).derive(
biomeFilter = BF([
FL.within(FL.FOREST, FL.FIELD), (HE.TEMPERATE, HE.BOREAL), WA.INLAND,
]),
scarcity = SC.UNCOMMON,
).derive(
biomeFilter = BF([FL.within(FL.FOREST, FL.FIELD), HE.FROZEN, WA.INLAND]),
scarcity = SC.UNUSUAL,
).derive(
biomeFilter = BF([(FL.CLEARING, FL.FIELD), HE.SUBTROPICAL, WA.INLAND]),
scarcity = SC.SPARSE,
)
)
)
+484
View File
@@ -0,0 +1,484 @@
from mcpacker.model.core.blockstate import BlockState
from mcpacker.model.core.flora.patch import Patch
from mcpacker.model.core.flora.tree import Tree
from mcpacker.model.modpack import ModPack
import mcpacker.model.core.flora.canopyshape as CA
import mcpacker.model.core.flora.density as DE
import mcpacker.model.core.flora.immersion as IM
import mcpacker.model.core.flora.trunkshape as TR
# Constants ########################################################################################
CD = "corndelight"
FD = "farmersdelight"
IE = "immersiveengineering"
IH = "immersivehealing"
MC = "minecraft"
RD = "rusticdelight"
RW = "realisticwheat"
UD = "fruitsdelight"
SU = "supplementaries"
# Functions ########################################################################################
def addPlants(pack:ModPack):
plants = pack.world.plants
# Crop Patches #############################################################
plants.add(Patch(
name = "athelas",
blocks = f"{IH}:medica_herb_block",
density = DE.THIN,
radius = 3,
))
plants.add(Patch(
name = "beetroot",
blocks = f"{FD}:wild_beetroots",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "bellpepper",
blocks = f"{RD}:wild_bell_peppers",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "blueberry",
blocks = BlockState(f"{UD}:blueberry_bush", {"age": 4}),
density = DE.THICK,
radius = 5,
))
plants.add(Patch(
name = "brownmushroom",
blocks = BlockState(f"{FD}:brown_mushroom_colony", {"age": 3}),
density = DE.PACKED,
radius = 3,
))
plants.add(Patch(
name = "cabbage",
blocks = f"{FD}:wild_cabbages",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "carrot",
blocks = f"{FD}:wild_carrots",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "coffee",
blocks = f"{RD}:wild_coffee",
density = DE.THIN,
radius = 5,
))
plants.add(Patch(
name = "corn",
blocks = f"{CD}:wild_corn",
density = DE.THICK,
radius = 5,
))
plants.add(Patch(
name = "cotton",
blocks = f"{CD}:wild_cotton",
density = DE.THICK,
radius = 6,
))
plants.add(Patch(
name = "currant",
blocks = BlockState(f"{MC}:sweet_berry_bush", {"age": 3}),
density = DE.THICK,
radius = 5,
))
plants.add(Patch(
name = "cranberry",
blocks = f"{UD}:cranberry_bush",
density = DE.CARPET,
immersion = IM.ADJACENT,
radius = 4,
))
plants.add(Patch(
name = "flax",
blocks = f"{SU}:wild_flax",
density = DE.THICK,
radius = 5,
))
plants.add(Patch(
name = "hamimelon",
blocks = f"{UD}:hamimelon",
density = DE.PACKED,
radius = 5,
))
plants.add(Patch(
name = "hemp",
blocks = BlockState(f"{IE}:hemp", {"half": "lower"}),
density = DE.THICK,
radius = 6,
))
plants.add(Patch(
name = "lemon",
blocks = BlockState(f"{UD}:lemon_tree", {"age": 4}),
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "melon",
blocks = f"{MC}:melon",
density = DE.PACKED,
radius = 5,
))
plants.add(Patch(
name = "onion",
blocks = f"{FD}:wild_onions",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "pineapple",
blocks = BlockState(f"{UD}:pineapple", {"age": 4}),
density = DE.SPARSE,
radius = 4,
))
plants.add(Patch(
name = "potato",
blocks = f"{FD}:wild_potatoes",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "pumpkin",
blocks = f"{MC}:pumpkin",
density = DE.PACKED,
radius = 5,
))
plants.add(Patch(
name = "redmushroom",
blocks = BlockState(f"{FD}:red_mushroom_colony", {"age": 3}),
density = DE.PACKED,
radius = 3,
))
plants.add(Patch(
name = "rice",
blocks = f"{FD}:wild_rice",
density = DE.THICK,
immersion = IM.SUBMERGED,
radius = 7,
))
plants.add(Patch(
name = "sugarcane",
blocks = f"{MC}:sugar_cane",
immersion = IM.ADJACENT,
density = DE.THICK,
radius = 5,
))
plants.add(Patch(
name = "sunflower",
blocks = BlockState(f"{MC}:sunflower", {"half": "lower"}),
density = DE.THIN,
radius = 5,
))
plants.add(Patch(
name = "tomato",
blocks = f"{FD}:wild_tomatoes",
density = DE.THIN,
radius = 5,
))
plants.add(Patch(
name = "wheat",
blocks = f"{RW}:wild_wheat",
density = DE.THIN,
radius = 6,
))
# Flower Patches ###########################################################
plants.add(Patch(
name = "allium",
blocks = f"{MC}:allium",
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "azurebluet",
blocks = f"{MC}:azure_bluet",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "blueorchid",
blocks = f"{MC}:blue_orchid",
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "cornflower",
blocks = f"{MC}:cornflower",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "daisy",
blocks = f"{MC}:oxeye_daisy",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "dandelion",
blocks = f"{MC}:dandelion",
density = DE.CARPET,
radius = 5,
))
plants.add(Patch(
name = "lilac",
blocks = f"{MC}:lilac",
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "lily",
blocks = f"{MC}:lily_of_the_valley",
density = DE.THICK,
radius = 3,
))
plants.add(Patch(
name = "peony",
blocks = f"{MC}:peony",
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "poppy",
blocks = f"{MC}:poppy",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "rose_black",
blocks = f"{MC}:wither_rose",
density = DE.SPARSE,
radius = 2,
))
plants.add(Patch(
name = "rose_bush",
blocks = BlockState(f"{MC}:rose_bush", {"half": "lower"}),
density = DE.SPARSE,
radius = 3,
))
plants.add(Patch(
name = "tulip_orange",
blocks = f"{MC}:orange_tulip",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "tulip_pink",
blocks = f"{MC}:pink_tulip",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "tulip_red",
blocks = f"{MC}:red_tulip",
density = DE.THIN,
radius = 4,
))
plants.add(Patch(
name = "tulip_white",
blocks = f"{MC}:white_tulip",
density = DE.THIN,
radius = 4,
))
# Trees ####################################################################
plants.add(Tree(
name = "apple",
foliage = f"{UD}:apple_leaves",
log = f"{MC}:oak_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 5,
canopyShape = CA.BLOB,
canopyHeight = 3,
canopyRadius = 2
))
plants.add(Tree(
name = "bayberry",
foliage = f"{UD}:bayberry_leaves",
log = f"{MC}:oak_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 1,
trunkHeightMax = 1,
canopyShape = CA.BUSH,
canopyHeight = 2,
canopyRadius = 2
))
plants.add(Tree(
name = "durian",
foliage = f"{UD}:durian_leaves",
log = f"{MC}:jungle_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 12,
trunkHeightMax = 25,
canopyShape = CA.FANCY,
canopyHeight = 6,
canopyRadius = 4
))
plants.add(Tree(
name = "fig",
foliage = f"{UD}:fig_leaves",
log = f"{MC}:acacia_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 5,
canopyShape = CA.BLOB,
canopyHeight = 3,
canopyRadius = 2
))
plants.add(Tree(
name = "hawberry",
foliage = f"{UD}:hawberry_leaves",
log = f"{MC}:oak_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 2,
trunkHeightMax = 7,
canopyShape = CA.BLOB,
canopyHeight = 3,
canopyRadius = 2
))
plants.add(Tree(
name = "lychee",
foliage = f"{UD}:lychee_leaves",
log = f"{MC}:jungle_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 7,
canopyShape = CA.BLOB,
canopyHeight = 3,
canopyRadius = 2
))
plants.add(Tree(
name = "mango",
foliage = f"{UD}:mango_leaves",
log = f"{MC}:jungle_log",
trunkShape = TR.FORKING,
trunkHeightMin = 10,
trunkHeightMax = 15,
canopyShape = CA.ACACIA,
canopyHeight = 5,
canopyRadius = 4
))
plants.add(Tree(
name = "mangosteen",
foliage = f"{UD}:mangosteen_leaves",
log = f"{MC}:jungle_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 12,
canopyShape = CA.BLOB,
canopyHeight = 3,
canopyRadius = 3
))
plants.add(Tree(
name = "orange",
foliage = f"{UD}:orange_leaves",
log = f"{MC}:acacia_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 5,
canopyShape = CA.BLOB,
canopyHeight = 2,
canopyRadius = 1
))
plants.add(Tree(
name = "peach",
foliage = f"{UD}:peach_leaves",
log = f"{MC}:cherry_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 1,
trunkHeightMax = 2,
canopyShape = CA.BLOB,
canopyHeight = 2,
canopyRadius = 1
))
plants.add(Tree(
name = "pear",
foliage = f"{UD}:pear_leaves",
log = f"{MC}:birch_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 6,
trunkHeightMax = 10,
canopyShape = CA.PINE,
canopyHeight = 4,
canopyRadius = 2
))
plants.add(Tree(
name = "persimmon",
foliage = f"{UD}:persimmon_leaves",
log = f"{MC}:dark_oak_log",
trunkShape = TR.STRAIGHT,
trunkHeightMin = 3,
trunkHeightMax = 9,
canopyShape = CA.BLOB,
canopyHeight = 4,
canopyRadius = 2
))
@@ -0,0 +1,7 @@
import mcpacker.pack.mysteriousisland.addplants
# Class ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,446 @@
from mcpacker.model.core.altitude import Altitude
from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF
from mcpacker.model.core.flora.plantspawn import PlantSpawn
from mcpacker.model.core.resourceid import ResourceId
from mcpacker.model.modpack import ModPack
import mcpacker.model.core.altitude as AL
import mcpacker.model.core.ecology.flora as FL
import mcpacker.model.core.ecology.geology as GE
import mcpacker.model.core.ecology.heat as HE
import mcpacker.model.core.ecology.humidity as HU
import mcpacker.model.core.ecology.soil as SO
import mcpacker.model.core.ecology.water as WA
import mcpacker.model.core.scarcity as SC
# Functions ########################################################################################
def addPlantSpawns(pack:ModPack):
plants = pack.world.plants
spawns = pack.world.plantSpawns
# Crop Patches #############################################################
spawns.add(PlantSpawn(
plant = plants["athelas"],
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilters = BF([FL.CANOPY, HE.TEMPERATE]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["beetroot"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.FOREST, HE.BOREAL, SO.ACIDIC]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["bellpepper"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.CLEARING, HE.TROPICAL, HU.WET, WA.INLAND]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["blueberry"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.within(FL.FOREST, FL.FIELD), HE.BOREAL]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["brownmushroom"],
altitude = AL.span(AL.SOIL, AL.ALPINE),
biomeFilters = [
BF(
[(FL.CANOPY, FL.FOREST), (HE.TEMPERATE, HE.BOREAL), (SO.LOAMY, SO.CLAYEY)],
[WA.OCEAN]
),
BF([HU.WET], [HE.FROZEN, WA.OCEAN, WA.RIVER]),
BF([SO.FUNGAL]),
],
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["cabbage"],
altitude = AL.HILLS,
biomeFilters = BF([(HE.SUBTROPICAL, HE.TEMPERATE), SO.SANDY, WA.COAST]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["carrot"],
altitude = AL.LOWLANDS,
biomeFilters = BF(
[(FL.FOREST, FL.CLEARING), HE.TEMPERATE, SO.LOAMY],
[ResourceId.parse("flower_forest")],
),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["coffee"],
altitude = AL.span(AL.HILLS, AL.ALPINE),
biomeFilters = BF([FL.CANOPY, HE.TROPICAL, HU.WET]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["corn"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.FIELD, HE.SUBTROPICAL, (SO.LOAMY, SO.SANDY)]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["cotton"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.FIELD, HE.SUBTROPICAL, HU.DRY, (SO.LOAMY, SO.SANDY)]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["currant"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.within(FL.FOREST, FL.FIELD), (HE.BOREAL, HE.FROZEN)]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["cranberry"],
altitude = AL.DUNES,
biomeFilters = BF([HU.WET, SO.PEATY]),
scarcity = SC.UNCOMMON,
))
# NOTE: Due to a bug in Supplementaries, flax can *only* be planted on sand, despite the actual
# plant requiring an entirely different soil. Therefore, we're imaginging *this* so-called
# "flax" as a fiberous, desert-dwelling cousin.
spawns.add(PlantSpawn(
plant = plants["flax"],
altitude = AL.DUNES,
biomeFilters = BF([FL.BARREN, HU.DRY, SO.SANDY]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["hamimelon"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.FIELD, HE.SUBTROPICAL, HU.DRY, (SO.LOAMY, SO.SANDY)]),
scarcity = SC.RARE,
))
spawns.add(PlantSpawn(
plant = plants["hemp"],
altitude = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilters = BF(
[FL.FIELD, HE.TEMPERATE, HU.DAMP, SO.LOAMY],
[ResourceId.parse("sunflower_plains")]
),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["lemon"],
altitude = AL.UPLANDS,
biomeFilters = BF([FL.FIELD, HE.SUBTROPICAL, HU.DRY]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["melon"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.CLEARING, HE.TROPICAL, HU.WET], [SO.FUNGAL]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["onion"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([FL.FOREST, HE.TEMPERATE, HU.DAMP, SO.ACIDIC]),
scarcity = SC.SPARSE,
))
# NOTE: Due to a bug in Fruits Delight, pineapple can *only* be planted on sand: despite this
# in now way reflecting the plant's actual ecology. As such, we have to imagine these as
# a more cactus-like cousin of actual pineapples.
spawns.add(PlantSpawn(
plant = plants["pineapple"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.BARREN, HE.TROPICAL, HU.DRY, SO.SANDY]),
scarcity = SC.SPARSE,
# TODO: add sand as substrate in addplants.py
))
spawns.add(PlantSpawn(
plant = plants["potato"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([FL.FOREST, HE.BOREAL, HU.DAMP, SO.ACIDIC]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["pumpkin"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.FIELD, HE.TEMPERATE, SO.LOAMY]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["redmushroom"],
altitude = AL.span(AL.SOIL, AL.ALPINE),
biomeFilters = [
BF([(FL.CANOPY, FL.FOREST), (HE.TEMPERATE, HE.BOREAL), (SO.LOAMY, SO.CLAYEY)]),
BF([HU.WET], [HE.FROZEN, WA.OCEAN, WA.RIVER]),
BF([SO.FUNGAL]),
],
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["rice"],
altitude = AL.SURFACE,
biomeFilters = BF([(HE.SUBTROPICAL, HE.TEMPERATE), (WA.RIVER, WA.SWAMP)]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["sugarcane"],
altitude = AL.DUNES,
biomeFilters = BF([(HE.TROPICAL, HE.TEMPERATE), (WA.RIVER, WA.SWAMP)]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["sunflower"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([ResourceId.parse("sunflower_plains")]),
scarcity = SC.CARPET,
))
spawns.add(PlantSpawn(
plant = plants["tomato"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([FL.CLEARING, HE.TROPICAL, HU.WET], [SO.FUNGAL]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["wheat"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.FIELD, HE.TEMPERATE, HU.DAMP, SO.LOAMY]),
scarcity = SC.COMMON,
))
# Flower Patches ###########################################################
spawns.add(PlantSpawn(
plant = plants["allium"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([FL.FOREST, HE.TEMPERATE, HU.DAMP, SO.ACIDIC]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["azurebluet"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.FIELD, (HE.TEMPERATE, HE.BOREAL), HU.DAMP, (SO.LOAMY, SO.PEATY)]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["blueorchid"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.CANOPY, HE.TROPICAL, HU.WET]),
scarcity = SC.RARE,
))
spawns.add(PlantSpawn(
plant = plants["cornflower"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.FIELD, HE.TEMPERATE, (SO.LOAMY, SO.PEATY)]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["daisy"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.FIELD, (HE.TEMPERATE, HE.BOREAL)]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["dandelion"],
altitude = AL.span(AL.DUNES, AL.HILLS),
biomeFilters = BF(
[(FL.CLEARING, FL.FIELD)],
[HE.FROZEN, HU.WET, SO.FUNGAL, SO.ROCKY, ResourceId.parse("flower_forest")]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["lilac"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.FOREST, HE.TEMPERATE, HU.DAMP, SO.LOAMY]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["lily"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.FOREST, (HE.TEMPERATE, HE.BOREAL), HU.DAMP, SO.ACIDIC]),
scarcity = SC.RARE,
))
spawns.add(PlantSpawn(
plant = plants["peony"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.CLEARING, HE.TEMPERATE, HU.DAMP, SO.ROCKY]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["poppy"],
altitude = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilters = BF(
[FL.FIELD, (HE.SUBTROPICAL, HE.TEMPERATE), (HU.DRY, HU.DAMP)],
[SO.FUNGAL]
),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["rose_black"],
altitude = AL.HILLS,
biomeFilters = BF([FL.CANOPY, HE.TEMPERATE]),
scarcity = SC.RARE,
))
spawns.add(PlantSpawn(
plant = plants["rose_bush"],
altitude = AL.span(AL.UPLANDS, AL.ALPINE),
biomeFilters = BF([FL.FOREST, (HE.TEMPERATE, HE.BOREAL), SO.LOAMY]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["tulip_orange"],
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilters = BF([ResourceId.parse("flower_forest")]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["tulip_pink"],
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilters = BF([ResourceId.parse("flower_forest")]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["tulip_red"],
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilters = BF([ResourceId.parse("flower_forest")]),
scarcity = SC.COMMON,
))
spawns.add(PlantSpawn(
plant = plants["tulip_white"],
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilters = BF([ResourceId.parse("flower_forest")]),
scarcity = SC.UNCOMMON,
))
# Trees ####################################################################
spawns.add(PlantSpawn(
plant = plants["apple"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF(
[(FL.FOREST, FL.CLEARING), HE.TEMPERATE, SO.LOAMY],
[ResourceId.parse("flower_forest")],
),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["bayberry"],
altitude = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilters = BF([HE.TEMPERATE, (SO.ROCKY, SO.SANDY), WA.COAST]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["durian"],
altitude = AL.HILLS,
biomeFilters = BF([FL.within(FL.CANOPY, FL.CLEARING), HE.TROPICAL, HU.WET, SO.ACIDIC]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["fig"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([HE.SUBTROPICAL, HU.DRY, SO.SANDY], [FL.BARREN]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["hawberry"],
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilters = BF([(FL.FOREST, FL.CLEARING), HE.TEMPERATE, (SO.ACIDIC, SO.LOAMY)]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["lychee"],
altitude = AL.UPLANDS,
biomeFilters = BF([FL.CLEARING, HE.TROPICAL, HU.WET], [SO.FUNGAL]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["mango"],
altitude = AL.LOWLANDS,
biomeFilters = BF(
[FL.within(FL.CANOPY, FL.CLEARING), HE.TROPICAL, (HU.DAMP, HU.WET), SO.ACIDIC]
),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["mangosteen"],
altitude = AL.UPLANDS,
biomeFilters = BF([FL.CANOPY, HE.TROPICAL, HU.WET, SO.ACIDIC]),
scarcity = SC.UNUSUAL,
))
spawns.add(PlantSpawn(
plant = plants["orange"],
altitude = AL.LOWLANDS,
biomeFilters = BF([FL.FIELD, HE.SUBTROPICAL, HU.DRY]),
scarcity = SC.SPARSE,
))
spawns.add(PlantSpawn(
plant = plants["peach"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.CLEARING, HE.TEMPERATE, HU.DAMP, SO.ROCKY]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["pear"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.CLEARING, HE.TEMPERATE, HU.DAMP, (SO.ACIDIC, SO.LOAMY)]),
scarcity = SC.UNCOMMON,
))
spawns.add(PlantSpawn(
plant = plants["persimmon"],
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([FL.FOREST, HE.TEMPERATE, SO.LOAMY]),
scarcity = SC.UNCOMMON,
))
@@ -0,0 +1,7 @@
import mcpacker.pack.mysteriousisland.addplantspawns
# Class ############################################################################################
def test_syntax():
pass
@@ -9,6 +9,8 @@ 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
from mcpacker.pack.mysteriousisland.addplants import addPlants
from mcpacker.pack.mysteriousisland.addplantspawns import addPlantSpawns
# Constants ########################################################################################
@@ -22,6 +24,8 @@ def buildModPack():
pack.augment(addBlocks)
pack.augment(addMinerals)
pack.augment(addDeposits)
pack.augment(addPlants)
pack.augment(addPlantSpawns)
pack.augment(addMobs)
pack.augment(addMobSpawns)
pack.augment(addDisabledFeatures)
+1 -1
View File
@@ -1,5 +1,5 @@
from mcpacker.pack.mysteriousisland.modpack import buildModPack
from mcpacker.ui.runner import Runner
from mcpacker.ui.runner import Runner
import sys
+2
View File
@@ -2,6 +2,7 @@ from mcpacker.format.report.biomereport import BiomeReport
from mcpacker.format.report.depositreport import DepositReport
from mcpacker.format.report.mineralreport import MineralReport
from mcpacker.format.report.mobspawnreport import MobSpawnReport
from mcpacker.format.report.plantspawnreport import PlantSpawnReport
from mcpacker.model.modpack import ModPack
from mcpacker.write.compositewriter import CompositeWriter
from mcpacker.write.datapack.depositwriter import DepositWriter
@@ -61,6 +62,7 @@ class Runner:
ReportWriter(p, DepositReport, o, "deposits.txt"),
ReportWriter(p, MineralReport, o, "minerals.txt"),
ReportWriter(p, MobSpawnReport, o, "mobspawns.txt"),
ReportWriter(p, PlantSpawnReport, o, "plantspawns.txt"),
]).write()
def _command_writeModPack(self):
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.write.compositewriter
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.write.datapack.depositwriter
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.write.datapack.disablefeaturewriter
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.write.datapack.disablespawnwriter
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,8 @@
import mcpacker.write.largeoredeposits.depositwriter
# Tests ############################################################################################
def test_syntax():
pass
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.write.packmetawriter
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,7 @@
import mcpacker.write.resourcepack.blockstatewriter
# Tests ############################################################################################
def test_syntax():
pass
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.write.staticwriter
# Tests ############################################################################################
def test_syntax():
pass
+7
View File
@@ -0,0 +1,7 @@
import mcpacker.write.zipwriter
# Tests ############################################################################################
def test_syntax():
pass