Consolidate writer logic to a single package
This commit is contained in:
@@ -1,12 +0,0 @@
|
|||||||
from mcpacker.model.core.world import World
|
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
|
||||||
|
|
||||||
class Writer:
|
|
||||||
|
|
||||||
def __init__(self, world:World):
|
|
||||||
self.world = world
|
|
||||||
|
|
||||||
def write(self):
|
|
||||||
raise NotImplementedError()
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import mcpacker.emit.datapack.writer
|
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
|
||||||
|
|
||||||
def test_syntax():
|
|
||||||
pass
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
class SpawnerRuleEmitter:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import mcpacker.emit.markdown.mobreport
|
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
|
||||||
|
|
||||||
def test_syntax():
|
|
||||||
pass
|
|
||||||
|
|
||||||
+38
-3
@@ -5,6 +5,11 @@ from json import loads
|
|||||||
from typing import TypeAlias
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
|
||||||
|
# Constants ########################################################################################
|
||||||
|
|
||||||
|
INDENT = " "
|
||||||
|
|
||||||
|
|
||||||
# Type Support #####################################################################################
|
# Type Support #####################################################################################
|
||||||
|
|
||||||
JsonBlob:TypeAlias = dict[str, "JsonBlob"] | list["JsonBlob"] | str | int | float | bool | None
|
JsonBlob:TypeAlias = dict[str, "JsonBlob"] | list["JsonBlob"] | str | int | float | bool | None
|
||||||
@@ -13,12 +18,42 @@ JsonBlob:TypeAlias = dict[str, "JsonBlob"] | list["JsonBlob"] | str | int | floa
|
|||||||
# Functions ########################################################################################
|
# Functions ########################################################################################
|
||||||
|
|
||||||
def removeNoneValues(blob:JsonBlob) -> JsonBlob:
|
def removeNoneValues(blob:JsonBlob) -> JsonBlob:
|
||||||
if not isinstance(blob, dict): return blob
|
if isinstance(blob, dict):
|
||||||
|
|
||||||
for key in list(blob.keys()):
|
for key in list(blob.keys()):
|
||||||
if blob[key] == None:
|
if blob[key] == None:
|
||||||
del blob[key]
|
del blob[key]
|
||||||
else:
|
else:
|
||||||
removeNoneValues(blob[key])
|
blob[key] = removeNoneValues(blob[key])
|
||||||
|
|
||||||
|
if isinstance(blob, list):
|
||||||
|
result:list[JsonBlob] = []
|
||||||
|
for value in blob:
|
||||||
|
if value != None:
|
||||||
|
result.append(removeNoneValues(value))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
return blob
|
||||||
|
|
||||||
|
def removeEmptyObjects(blob:JsonBlob) -> JsonBlob:
|
||||||
|
if isinstance(blob, dict):
|
||||||
|
for key in list(blob.keys()):
|
||||||
|
value = blob[key]
|
||||||
|
if isinstance(value, dict):
|
||||||
|
if len(value) == 0:
|
||||||
|
del blob[key]
|
||||||
|
else:
|
||||||
|
blob[key] = removeEmptyObjects(value)
|
||||||
|
|
||||||
|
return blob
|
||||||
|
|
||||||
|
if isinstance(blob, list):
|
||||||
|
result:list[JsonBlob] = []
|
||||||
|
for value in blob:
|
||||||
|
if isinstance(value, dict):
|
||||||
|
if len(value) > 0:
|
||||||
|
result.append(removeEmptyObjects(value))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
return blob
|
return blob
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from mcpacker.json import JsonBlob
|
||||||
|
from pytest import fixture
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
import mcpacker.json as json
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="blob")
|
||||||
|
def createBlob():
|
||||||
|
yield {
|
||||||
|
"alpha": "a",
|
||||||
|
"bravo": 12,
|
||||||
|
"charlie": True,
|
||||||
|
"delta": [
|
||||||
|
"foxtrot",
|
||||||
|
13,
|
||||||
|
False,
|
||||||
|
[ "golf" ],
|
||||||
|
{ "hotel": "india" },
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
"juliette": {
|
||||||
|
"kilo": "lima",
|
||||||
|
"mike": {},
|
||||||
|
"november": None
|
||||||
|
},
|
||||||
|
"oscar": None,
|
||||||
|
"papa": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
@fixture(name="noNone")
|
||||||
|
def removeNoneValues(blob:JsonBlob):
|
||||||
|
yield json.removeNoneValues(blob)
|
||||||
|
|
||||||
|
@fixture(name="noEmpty")
|
||||||
|
def remmoveEmptyObjects(blob:JsonBlob):
|
||||||
|
yield json.removeEmptyObjects(blob)
|
||||||
|
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_removeNoneValues(noNone:JsonBlob):
|
||||||
|
assert len(cast(dict[str,list[str]], noNone)["delta"]) == 5
|
||||||
|
assert "november" not in cast(dict[str,dict[str,JsonBlob]], noNone)["juliette"]
|
||||||
|
assert "oscar" not in cast(dict[str,JsonBlob], noNone)
|
||||||
|
|
||||||
|
def test_removeEmptyObjects(noEmpty:JsonBlob):
|
||||||
|
assert "mike" not in cast(dict[str,dict[str,JsonBlob]], noEmpty)["juliette"]
|
||||||
|
assert "papa" in cast(dict[str,JsonBlob], noEmpty)
|
||||||
@@ -7,8 +7,4 @@ from typing import Iterator
|
|||||||
# Classes ##########################################################################################
|
# Classes ##########################################################################################
|
||||||
|
|
||||||
class BiomeCatalog(Catalog[Biome]):
|
class BiomeCatalog(Catalog[Biome]):
|
||||||
|
pass
|
||||||
def matching(self, biomeFilter:BiomeFilter) -> Iterator[Biome]:
|
|
||||||
for biome in self:
|
|
||||||
if biomeFilter.accepts(biome):
|
|
||||||
yield biome
|
|
||||||
|
|||||||
@@ -43,4 +43,4 @@ def createCatalog():
|
|||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
|
|
||||||
def test_findJungles(catalog, jungles):
|
def test_findJungles(catalog, jungles):
|
||||||
assert [b.city for b in catalog.matching(jungles)] == ["singapore"]
|
assert [b.city for b in catalog.filter(lambda b: jungles.accepts(b))] == ["singapore"]
|
||||||
|
|||||||
@@ -12,15 +12,12 @@ class Mob:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, gameId:str, active:Active|Iterable[Active]=AC.DIURNAL):
|
def __init__(self, gameId:str, active:Active|Iterable[Active]=AC.DIURNAL):
|
||||||
|
if isinstance(active, Active):
|
||||||
|
active = [active]
|
||||||
|
|
||||||
self.gameId = gameId
|
self.gameId = gameId
|
||||||
self.active = active
|
self.active = active
|
||||||
|
|
||||||
if not self.active:
|
|
||||||
self.active = AC.DIURNAL
|
|
||||||
|
|
||||||
if isinstance(self.active, Active):
|
|
||||||
self.active = (self.active,)
|
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
def __eq__(self, other) -> bool:
|
||||||
if type(self) != type(other): return False
|
if type(self) != type(other): return False
|
||||||
if self.gameId != other.gameId: return False
|
if self.gameId != other.gameId: return False
|
||||||
|
|||||||
@@ -36,4 +36,4 @@ def test_str(squid):
|
|||||||
assert str(squid) == "minecraft:squid"
|
assert str(squid) == "minecraft:squid"
|
||||||
|
|
||||||
def test_repr(cow):
|
def test_repr(cow):
|
||||||
assert repr(cow) == "Mob<minecraft:cow>{active:(Active<day>{start:0, end:12000},)}"
|
assert repr(cow) == "Mob<minecraft:cow>{active:[Active<day>{start:0, end:12000}]}"
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
from mcpacker.json import JsonBlob
|
|
||||||
from mcpacker.model.incontrol.extracondition import ExtraCondition
|
|
||||||
from mcpacker.model.core.dimension import Dimension
|
|
||||||
|
|
||||||
import mcpacker.json as json
|
|
||||||
import mcpacker.model.core.altitude as A
|
|
||||||
import mcpacker.model.core.dimension as D
|
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
|
||||||
|
|
||||||
class Condition:
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
dimension:Dimension=D.OVERWORLD,
|
|
||||||
heightMin:int|None=None,
|
|
||||||
heightMax:int|None=None,
|
|
||||||
thisMax:int|None=None,
|
|
||||||
inWater:bool|None=None,
|
|
||||||
andCondition:ExtraCondition|None=None,
|
|
||||||
):
|
|
||||||
self.dimension = dimension
|
|
||||||
self.heightMin = heightMin
|
|
||||||
self.heightMax = heightMax
|
|
||||||
self.thisMax = thisMax
|
|
||||||
self.inWater = inWater
|
|
||||||
self.andCondition = andCondition
|
|
||||||
|
|
||||||
def asJsonBlob(self) -> JsonBlob:
|
|
||||||
return json.removeNoneValues({
|
|
||||||
"dimension": self.dimension.name,
|
|
||||||
"heightmin": self.heightMin,
|
|
||||||
"heightmax": self.heightMax,
|
|
||||||
"maxthis": self.thisMax,
|
|
||||||
"inwater": self.inWater,
|
|
||||||
"and": None if not self.andCondition else self.andCondition.asJsonBlob(),
|
|
||||||
})
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
from collections.abc import Iterable
|
|
||||||
from mcpacker.json import JsonBlob
|
|
||||||
|
|
||||||
import mcpacker.json as json
|
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
|
||||||
|
|
||||||
class ExtraCondition:
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
autumn:bool|None=None,
|
|
||||||
biome:Iterable[str]|None=None,
|
|
||||||
cave:bool|None=None,
|
|
||||||
seeSky:bool|None=None,
|
|
||||||
spring:bool|None=None,
|
|
||||||
summer:bool|None=None,
|
|
||||||
timeMax:int|None=None,
|
|
||||||
timeMin:int|None=None,
|
|
||||||
winter:bool|None=None,
|
|
||||||
):
|
|
||||||
self.autumn = autumn
|
|
||||||
self.biome = biome
|
|
||||||
self.cave = cave
|
|
||||||
self.seeSky = seeSky
|
|
||||||
self.spring = spring
|
|
||||||
self.summer = summer
|
|
||||||
self.timeMax = timeMax
|
|
||||||
self.timeMin = timeMin
|
|
||||||
self.winter = winter
|
|
||||||
|
|
||||||
def asJsonBlob(self) -> JsonBlob:
|
|
||||||
return json.removeNoneValues({
|
|
||||||
"autumn": self.autumn,
|
|
||||||
"biome": None if not self.biome else "[" + ", ".join(self.biome) + "]",
|
|
||||||
"cave": self.cave,
|
|
||||||
"seesky": self.seeSky,
|
|
||||||
"spring": self.spring,
|
|
||||||
"summer": self.summer,
|
|
||||||
"maxtime": self.timeMax,
|
|
||||||
"mintime": self.timeMin,
|
|
||||||
"winter": self.winter,
|
|
||||||
})
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
from mcpacker.json import JsonBlob
|
|
||||||
from mcpacker.model.core.fauna.mobspawn import MobSpawn
|
|
||||||
from mcpacker.model.incontrol.condition import Condition
|
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
|
||||||
|
|
||||||
class SpawnerRule:
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
mobGameId:str,
|
|
||||||
condition:Condition,
|
|
||||||
amountMin:int=1,
|
|
||||||
amountMax:int=1,
|
|
||||||
rate:float=1.0,
|
|
||||||
attempts:int=1,
|
|
||||||
weight:int=1,
|
|
||||||
):
|
|
||||||
self.mobGameId = mobGameId
|
|
||||||
self.amountMin = amountMin
|
|
||||||
self.amountMax = amountMax
|
|
||||||
self.rate = rate
|
|
||||||
self.attempts = attempts
|
|
||||||
self.weight = weight
|
|
||||||
self.condition = condition
|
|
||||||
|
|
||||||
def asJsonBlob(self) -> JsonBlob:
|
|
||||||
return {
|
|
||||||
"mob": [self.mobGameId],
|
|
||||||
"amount": {
|
|
||||||
"minimum": self.amountMin,
|
|
||||||
"maximum": self.amountMax,
|
|
||||||
"groupdistance": 4,
|
|
||||||
},
|
|
||||||
"persecond": self.rate,
|
|
||||||
"attempts": self.attempts,
|
|
||||||
"weights": [self.weight],
|
|
||||||
"conditions": self.condition.asJsonBlob(),
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Constants ########################################################################################
|
||||||
|
|
||||||
|
TICK = 1
|
||||||
|
SEC = 20 * TICK
|
||||||
|
MIN = 60 * SEC
|
||||||
|
HOUR = 60 * MIN
|
||||||
|
DAY = 24 * HOUR
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import mcpacker.emit.modpack
|
import mcpacker.model.time
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
+21
-11
@@ -1,8 +1,11 @@
|
|||||||
from mcpacker.emit.markdown.reportwriter import ReportWriter
|
|
||||||
from mcpacker.emit.markdown.biomereport import BiomeReport
|
|
||||||
from mcpacker.emit.markdown.mineralreport import MineralReport
|
|
||||||
from mcpacker.emit.markdown.mobreport import MobReport
|
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.incontrol.spawnerwriter import SpawnerWriter
|
||||||
|
from mcpacker.write.markdown.biomereport import BiomeReport
|
||||||
|
from mcpacker.write.markdown.mineralreport import MineralReport
|
||||||
|
from mcpacker.write.markdown.mobspawnreport import MobSpawnReport
|
||||||
|
from mcpacker.write.markdown.reportwriter import ReportWriter
|
||||||
|
from mcpacker.write.writer import CompositeWriter
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
@@ -11,15 +14,16 @@ import sys
|
|||||||
|
|
||||||
# Constants ########################################################################################
|
# Constants ########################################################################################
|
||||||
|
|
||||||
OUTPUT_PATH = "output"
|
OUTPUT_PATH = Path("output")
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
# Class ############################################################################################
|
||||||
|
|
||||||
class Runner:
|
class Runner:
|
||||||
|
|
||||||
def __init__(self, pack:ModPack|None=None):
|
def __init__(self, pack:ModPack|None=None, outputDir:Path=OUTPUT_PATH):
|
||||||
self.pack = pack or ModPack("untitled")
|
self.pack = pack or ModPack("untitled")
|
||||||
|
self.outputDir = outputDir
|
||||||
|
|
||||||
def abort(self, message:str, status:int=-1):
|
def abort(self, message:str, status:int=-1):
|
||||||
print(message)
|
print(message)
|
||||||
@@ -40,9 +44,15 @@ class Runner:
|
|||||||
# Commands #################################################################
|
# Commands #################################################################
|
||||||
|
|
||||||
def _command_writeReports(self):
|
def _command_writeReports(self):
|
||||||
writer = ReportWriter([
|
writer = CompositeWriter(self.pack, self.outputDir, [
|
||||||
BiomeReport(self.pack),
|
BiomeReport,
|
||||||
MineralReport(self.pack),
|
MineralReport,
|
||||||
MobReport(self.pack),
|
MobSpawnReport,
|
||||||
])
|
])
|
||||||
writer.write(os.path.join(OUTPUT_PATH, self.pack.name, "markdown"))
|
writer.write()
|
||||||
|
|
||||||
|
def _command_writeModPack(self):
|
||||||
|
writer = CompositeWriter(self.pack, self.outputDir, [
|
||||||
|
SpawnerWriter,
|
||||||
|
])
|
||||||
|
writer.write()
|
||||||
|
|||||||
@@ -1,8 +1,99 @@
|
|||||||
import mcpacker.ui.runner
|
from mcpacker.model.core.ecology.biome import Biome
|
||||||
|
from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF
|
||||||
|
from mcpacker.model.core.fauna.mob import Mob
|
||||||
|
from mcpacker.model.core.fauna.mobspawn import MobSpawn
|
||||||
|
from mcpacker.model.core.geology.mineral import Mineral
|
||||||
|
from mcpacker.model.core.geology.replacement import Replacement
|
||||||
|
from mcpacker.model.core.habitat import Habitat
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.ui.runner import Runner
|
||||||
|
from mcpacker.write.incontrol.spawnerwriter import SpawnerWriter
|
||||||
|
from pathlib import Path
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
import mcpacker.json as json
|
||||||
|
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 textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="addBiomes")
|
||||||
|
def defineAddBiomes():
|
||||||
|
def addBiomes(pack:ModPack):
|
||||||
|
pack.world.biomes.add(Biome("singapore", "minecraft:jungle",
|
||||||
|
FL.CANOPY, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND
|
||||||
|
))
|
||||||
|
|
||||||
|
yield addBiomes
|
||||||
|
|
||||||
|
@fixture(name="addMobs")
|
||||||
|
def defineAddMobs():
|
||||||
|
def addMobs(pack:ModPack):
|
||||||
|
pack.world.mobs.add(Mob("minecraft:chicken", AC.DIURNAL))
|
||||||
|
|
||||||
|
yield addMobs
|
||||||
|
|
||||||
|
@fixture(name="addMobSpawns")
|
||||||
|
def defineAddMobSpawnss():
|
||||||
|
def addMobSpawns(pack:ModPack):
|
||||||
|
mobs = pack.world.mobs
|
||||||
|
spawns = pack.world.mobSpawns
|
||||||
|
|
||||||
|
pack.world.mobSpawns.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,
|
||||||
|
).derive(
|
||||||
|
seasons = SE.exclude(SE.SUMMER),
|
||||||
|
scarcity = SC.UNCOMMON
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
yield addMobSpawns
|
||||||
|
|
||||||
|
@fixture(name="pack")
|
||||||
|
def createPack(addBiomes, addMobs, addMobSpawns):
|
||||||
|
pack = ModPack("testModPack")
|
||||||
|
pack.augment(addBiomes)
|
||||||
|
pack.augment(addMobs)
|
||||||
|
pack.augment(addMobSpawns)
|
||||||
|
yield pack
|
||||||
|
|
||||||
|
@fixture(name="modPackRunner")
|
||||||
|
def createModPackRunner(tmp_path:Path):
|
||||||
|
runner = Runner(ModPack("testModPack"), tmp_path)
|
||||||
|
runner._command_writeModPack()
|
||||||
|
yield runner
|
||||||
|
|
||||||
|
@fixture(name="reportRunner")
|
||||||
|
def createReportRunner(tmp_path:Path):
|
||||||
|
runner = Runner(ModPack("testModPack"), tmp_path)
|
||||||
|
runner._command_writeReports()
|
||||||
|
yield runner
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
|
|
||||||
def test_syntax():
|
def test_writeModPack(tmp_path:Path, modPackRunner:Runner):
|
||||||
pass
|
assert (tmp_path/"testModPack"/"config"/"incontrol"/"spawner.json").exists()
|
||||||
|
|
||||||
|
def test_writeReports(tmp_path:Path, reportRunner:Runner):
|
||||||
|
assert (tmp_path/"testModPack"/"reports"/"biomes.md").exists()
|
||||||
|
assert (tmp_path/"testModPack"/"reports"/"minerals.md").exists()
|
||||||
|
assert (tmp_path/"testModPack"/"reports"/"mobspawns.md").exists()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import mcpacker.emit.datapack.locator
|
import mcpacker.write.datapack.locator
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# Constants ########################################################################################
|
||||||
|
|
||||||
|
INCONTROL_CONFIG_DIR = Path("config") / "incontrol"
|
||||||
|
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
from mcpacker.json import JsonBlob
|
||||||
|
from mcpacker.model.core.ecology.biomefilter import BiomeFilter
|
||||||
|
from mcpacker.model.core.fauna.active import Active
|
||||||
|
from mcpacker.model.core.fauna.mobspawn import MobSpawn
|
||||||
|
from mcpacker.model.core.habitat import Habitat
|
||||||
|
from mcpacker.model.core.scarcity import Scarcity
|
||||||
|
from mcpacker.model.core.season import Season
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.incontrol import INCONTROL_CONFIG_DIR
|
||||||
|
from mcpacker.write.writer import Writer
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import mcpacker.json as json
|
||||||
|
import mcpacker.model.core.dimension as DI
|
||||||
|
import mcpacker.model.core.fauna.location as LO
|
||||||
|
import mcpacker.model.core.scarcity as SC
|
||||||
|
import mcpacker.model.time as TI
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class SpawnerWriter(Writer):
|
||||||
|
|
||||||
|
def __init__(self, pack:ModPack, outputDir:Path):
|
||||||
|
super().__init__(pack, outputDir)
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
path = self.outputDir / self.pack.name / INCONTROL_CONFIG_DIR / "spawner.json"
|
||||||
|
path.parent.mkdir(parents=True)
|
||||||
|
path.write_text(json.dumps(self._makeAllRules(), indent=json.INDENT))
|
||||||
|
|
||||||
|
# Private Functions ########################################################
|
||||||
|
|
||||||
|
def _computeBiomeNames(self, biomeFilter:BiomeFilter) -> JsonBlob:
|
||||||
|
return list(
|
||||||
|
b.gameId for b in self.pack.world.biomes.filter(
|
||||||
|
lambda b: biomeFilter.accepts(b)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _computeSpawnRate(self, scarcity:Scarcity) -> float:
|
||||||
|
base = {
|
||||||
|
SC.ABSENT: 24 * TI.HOUR,
|
||||||
|
SC.RARE: 10 * TI.MIN,
|
||||||
|
SC.UNUSUAL: 5 * TI.MIN,
|
||||||
|
SC.SPARSE: 1 * TI.MIN,
|
||||||
|
SC.UNCOMMON: 15 * TI.SEC,
|
||||||
|
SC.COMMON: 5 * TI.SEC,
|
||||||
|
SC.CARPET: 1 * TI.SEC,
|
||||||
|
}[scarcity]
|
||||||
|
|
||||||
|
return 1.0 / (base / 20)
|
||||||
|
|
||||||
|
def _computeWeight(self, scarcity:Scarcity) -> int:
|
||||||
|
return {
|
||||||
|
SC.ABSENT: 0,
|
||||||
|
SC.RARE: 1,
|
||||||
|
SC.UNUSUAL: 2,
|
||||||
|
SC.SPARSE: 4,
|
||||||
|
SC.UNCOMMON: 8,
|
||||||
|
SC.COMMON: 16,
|
||||||
|
SC.CARPET: 32,
|
||||||
|
}[scarcity]
|
||||||
|
|
||||||
|
def _makeAndCondition(self, habitat:Habitat, season:Season, active:Active) -> JsonBlob:
|
||||||
|
return {
|
||||||
|
"biome": self._computeBiomeNames(habitat.biomeFilter),
|
||||||
|
season.name: True,
|
||||||
|
"seesky": True if LO.OUTSIDE == habitat.location else None,
|
||||||
|
"cave": True if LO.CAVE == habitat.location else None,
|
||||||
|
"mintime": active.start,
|
||||||
|
"maxtime": active.end,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _makeAllRules(self) -> JsonBlob:
|
||||||
|
result:list[JsonBlob] = []
|
||||||
|
|
||||||
|
for spawn in self.pack.world.mobSpawns:
|
||||||
|
for habitat in spawn.habitats:
|
||||||
|
for season in habitat.seasons:
|
||||||
|
for active in spawn.mob.active:
|
||||||
|
result.append(self._makeRule(spawn, habitat, season, active))
|
||||||
|
|
||||||
|
return json.removeEmptyObjects(json.removeNoneValues(result))
|
||||||
|
|
||||||
|
def _makeCondition(self, habitat:Habitat, season:Season, active:Active) -> JsonBlob:
|
||||||
|
return {
|
||||||
|
"dimension": DI.OVERWORLD.name,
|
||||||
|
"minheight": habitat.altitude.bottom,
|
||||||
|
"maxheight": habitat.altitude.top,
|
||||||
|
"maxthis": habitat.group.largest * 2,
|
||||||
|
"inwater": LO.WATER == habitat.location,
|
||||||
|
"and": self._makeAndCondition(habitat, season, active),
|
||||||
|
}
|
||||||
|
|
||||||
|
def _makeRule(self, spawn:MobSpawn, habitat:Habitat, season:Season, active:Active,) -> JsonBlob:
|
||||||
|
return {
|
||||||
|
"mob": spawn.mob.gameId,
|
||||||
|
"amount": {
|
||||||
|
"minimum": habitat.group.smallest,
|
||||||
|
"maximum": habitat.group.largest,
|
||||||
|
"groupdistance": 4,
|
||||||
|
},
|
||||||
|
"persecond": self._computeSpawnRate(habitat.scarcity),
|
||||||
|
"attempts": habitat.group.largest * 4,
|
||||||
|
"weights": [ self._computeWeight(habitat.scarcity) ],
|
||||||
|
"conditions": self._makeCondition(habitat, season, active),
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
from mcpacker.model.core.ecology.biome import Biome
|
||||||
|
from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF
|
||||||
|
from mcpacker.model.core.fauna.mob import Mob
|
||||||
|
from mcpacker.model.core.fauna.mobspawn import MobSpawn
|
||||||
|
from mcpacker.model.core.geology.mineral import Mineral
|
||||||
|
from mcpacker.model.core.geology.replacement import Replacement
|
||||||
|
from mcpacker.model.core.habitat import Habitat
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.incontrol.spawnerwriter import SpawnerWriter
|
||||||
|
from pathlib import Path
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
import mcpacker.json as json
|
||||||
|
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 textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="addBiomes")
|
||||||
|
def defineAddBiomes():
|
||||||
|
def addBiomes(pack:ModPack):
|
||||||
|
pack.world.biomes.add(Biome("singapore", "minecraft:jungle",
|
||||||
|
FL.CANOPY, GE.SEDIMENTARY, HE.TROPICAL, HU.WET, SO.ACIDIC, WA.INLAND
|
||||||
|
))
|
||||||
|
|
||||||
|
yield addBiomes
|
||||||
|
|
||||||
|
@fixture(name="addMobs")
|
||||||
|
def defineAddMobs():
|
||||||
|
def addMobs(pack:ModPack):
|
||||||
|
pack.world.mobs.add(Mob("minecraft:chicken", AC.DIURNAL))
|
||||||
|
|
||||||
|
yield addMobs
|
||||||
|
|
||||||
|
@fixture(name="addMobSpawns")
|
||||||
|
def defineAddMobSpawnss():
|
||||||
|
def addMobSpawns(pack:ModPack):
|
||||||
|
mobs = pack.world.mobs
|
||||||
|
spawns = pack.world.mobSpawns
|
||||||
|
|
||||||
|
pack.world.mobSpawns.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,
|
||||||
|
).derive(
|
||||||
|
seasons = SE.exclude(SE.SUMMER),
|
||||||
|
scarcity = SC.UNCOMMON
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
yield addMobSpawns
|
||||||
|
|
||||||
|
@fixture(name="pack")
|
||||||
|
def createPack(addBiomes, addMobs, addMobSpawns):
|
||||||
|
pack = ModPack("testModPack")
|
||||||
|
pack.augment(addBiomes)
|
||||||
|
pack.augment(addMobs)
|
||||||
|
pack.augment(addMobSpawns)
|
||||||
|
yield pack
|
||||||
|
|
||||||
|
@fixture(name="writer")
|
||||||
|
def createWriter(pack, tmp_path):
|
||||||
|
writer = SpawnerWriter(pack, tmp_path)
|
||||||
|
writer.write()
|
||||||
|
yield writer
|
||||||
|
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_write(writer:SpawnerWriter, tmp_path:Path):
|
||||||
|
path = tmp_path / "testModPack" / "config" / "incontrol" / "spawner.json"
|
||||||
|
text = path.read_text()
|
||||||
|
data = json.loads(text)
|
||||||
|
|
||||||
|
assert len(data) == 4
|
||||||
|
|
||||||
|
rule = data[0]
|
||||||
|
assert rule["mob"] == "minecraft:chicken"
|
||||||
|
assert rule["amount"]["maximum"] == 6
|
||||||
|
assert abs(rule["persecond"] - 0.2) < 0.001
|
||||||
|
assert rule["conditions"]["and"]["biome"] == ["minecraft:jungle"]
|
||||||
|
assert rule["conditions"]["and"]["summer"]
|
||||||
|
|
||||||
|
rule = data[1]
|
||||||
|
assert abs(rule["persecond"] - 0.066) < 0.001
|
||||||
|
assert rule["conditions"]["and"]["spring"]
|
||||||
|
|
||||||
|
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
from mcpacker.emit.markdown.report import Report
|
from mcpacker.write.markdown.markdownwriter import MarkdownWriter
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
# Class ############################################################################################
|
||||||
|
|
||||||
class BiomeReport(Report):
|
class BiomeReport(MarkdownWriter):
|
||||||
|
|
||||||
def __init__(self, pack:ModPack):
|
def __init__(self, pack:ModPack, outputDir:Path):
|
||||||
super().__init__("biomes.md", pack)
|
super().__init__("biomes.md", pack, outputDir)
|
||||||
|
|
||||||
def build(self):
|
def compose(self):
|
||||||
for biome in self.pack.world.biomes:
|
for biome in self.pack.world.biomes:
|
||||||
self.line(f"# Biome: {biome.gameId} ({biome.city})")
|
self.line(f"# Biome: {biome.gameId} ({biome.city})")
|
||||||
self.line()
|
self.line()
|
||||||
+10
-8
@@ -1,4 +1,4 @@
|
|||||||
from mcpacker.emit.markdown.biomereport import BiomeReport
|
from mcpacker.write.markdown.biomereport import BiomeReport
|
||||||
from mcpacker.model.core.ecology.biome import Biome
|
from mcpacker.model.core.ecology.biome import Biome
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
@@ -33,20 +33,21 @@ def defineAddBiomes():
|
|||||||
|
|
||||||
@fixture(name="pack")
|
@fixture(name="pack")
|
||||||
def createPack(addBiomes):
|
def createPack(addBiomes):
|
||||||
pack = ModPack("test")
|
pack = ModPack("testModPack")
|
||||||
pack.augment(addBiomes)
|
pack.augment(addBiomes)
|
||||||
yield pack
|
yield pack
|
||||||
|
|
||||||
@fixture(name="report")
|
@fixture(name="report")
|
||||||
def createReport(pack):
|
def createReport(pack, tmp_path):
|
||||||
report = BiomeReport(pack)
|
report = BiomeReport(pack, tmp_path)
|
||||||
report.build()
|
report.write()
|
||||||
yield report
|
yield report
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
|
|
||||||
def test_report(report):
|
def test_report(tmp_path, report):
|
||||||
assert str(report) == textwrap.dedent("""
|
path = tmp_path / "testModPack" / "reports" / "biomes.md"
|
||||||
|
assert path.read_text() == textwrap.dedent("""
|
||||||
# Biome: minecraft:plains (kansascity)
|
# Biome: minecraft:plains (kansascity)
|
||||||
|
|
||||||
* Flora: field
|
* Flora: field
|
||||||
@@ -64,4 +65,5 @@ def test_report(report):
|
|||||||
* Humidity: dry
|
* Humidity: dry
|
||||||
* Soil: sandy
|
* Soil: sandy
|
||||||
* Water: inland
|
* Water: inland
|
||||||
""").strip()
|
|
||||||
|
""").lstrip()
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
from mcpacker.write.writer import Writer
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TextIO
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
# Constants ########################################################################################
|
||||||
|
|
||||||
|
INDENT = " "
|
||||||
|
REPORT_DIR_PATH = "reports"
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class MarkdownWriter(Writer):
|
||||||
|
|
||||||
|
def __init__(self, name:str, pack:ModPack, outputDir:Path):
|
||||||
|
super().__init__(pack, outputDir)
|
||||||
|
|
||||||
|
self._file:TextIO|None = None
|
||||||
|
self._name = name
|
||||||
|
self._indent = 0
|
||||||
|
self._lineBuffer:list[str] = []
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
path = self.outputDir / self.pack.name / REPORT_DIR_PATH / self._name
|
||||||
|
|
||||||
|
path.parent.mkdir(exist_ok=True, parents=True)
|
||||||
|
with path.open("w") as file:
|
||||||
|
try:
|
||||||
|
self._file = file
|
||||||
|
self.compose()
|
||||||
|
finally:
|
||||||
|
self._file = None
|
||||||
|
|
||||||
|
def compose(self) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
# Helper Methods ###########################################################
|
||||||
|
|
||||||
|
def indent(self) -> "MarkdownWriter":
|
||||||
|
self._indent += 1
|
||||||
|
self._lineBuffer.insert(0, INDENT)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def line(self, text:str="") -> "MarkdownWriter":
|
||||||
|
assert self._file != None
|
||||||
|
self.text(text)
|
||||||
|
|
||||||
|
self._file.write("".join(self._lineBuffer) + "\n")
|
||||||
|
self._lineBuffer = []
|
||||||
|
while len(self._lineBuffer) < self._indent:
|
||||||
|
self._lineBuffer.append(INDENT)
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def outdent(self) -> "MarkdownWriter":
|
||||||
|
self._indent = max(0, self._indent - 1)
|
||||||
|
|
||||||
|
if self._lineBuffer:
|
||||||
|
if self._lineBuffer[0] == INDENT:
|
||||||
|
self._lineBuffer.pop()
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def text(self, text:str) -> "MarkdownWriter":
|
||||||
|
self._lineBuffer.append(str(text))
|
||||||
|
return self
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.markdown.markdownwriter import MarkdownWriter
|
||||||
|
from pathlib import Path
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Helpers ##########################################################################################
|
||||||
|
|
||||||
|
class SampleWriter(MarkdownWriter):
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
(self.text("alpha")
|
||||||
|
.line("bravo")
|
||||||
|
.indent()
|
||||||
|
.line("charlie")
|
||||||
|
.indent()
|
||||||
|
.line("delta")
|
||||||
|
.outdent()
|
||||||
|
.line("echo")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="writer")
|
||||||
|
def createWriter(tmp_path:Path):
|
||||||
|
writer = SampleWriter("testReport.md", ModPack("testModPack"), tmp_path)
|
||||||
|
writer.write()
|
||||||
|
yield writer
|
||||||
|
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_write(tmp_path, writer):
|
||||||
|
path = tmp_path / "testModPack" / "reports" / "testReport.md"
|
||||||
|
assert path.read_text() == textwrap.dedent("""
|
||||||
|
alphabravo
|
||||||
|
charlie
|
||||||
|
delta
|
||||||
|
echo
|
||||||
|
""").lstrip()
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
from mcpacker.emit.markdown.report import Report
|
from mcpacker.write.markdown.markdownwriter import MarkdownWriter
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
# Class ############################################################################################
|
||||||
|
|
||||||
class MineralReport(Report):
|
class MineralReport(MarkdownWriter):
|
||||||
|
|
||||||
def __init__(self, pack:ModPack):
|
def __init__(self, pack:ModPack, outputDir:Path):
|
||||||
super().__init__("minerals.md", pack)
|
super().__init__("minerals.md", pack, outputDir)
|
||||||
|
|
||||||
def build(self):
|
def compose(self):
|
||||||
for mineral in self.pack.world.minerals:
|
for mineral in self.pack.world.minerals:
|
||||||
self.line(f"# Mineral: {mineral.name}")
|
self.line(f"# Mineral: {mineral.name}")
|
||||||
self.line()
|
self.line()
|
||||||
+11
-8
@@ -1,4 +1,4 @@
|
|||||||
from mcpacker.emit.markdown.mineralreport import MineralReport
|
from mcpacker.write.markdown.mineralreport import MineralReport
|
||||||
from mcpacker.model.core.geology.mineral import Mineral
|
from mcpacker.model.core.geology.mineral import Mineral
|
||||||
from mcpacker.model.core.geology.replacement import Replacement
|
from mcpacker.model.core.geology.replacement import Replacement
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
@@ -26,21 +26,23 @@ def defineAddMinerals():
|
|||||||
|
|
||||||
@fixture(name="pack")
|
@fixture(name="pack")
|
||||||
def createPack(addMinerals):
|
def createPack(addMinerals):
|
||||||
pack = ModPack("test")
|
pack = ModPack("testModPack")
|
||||||
pack.augment(addMinerals)
|
pack.augment(addMinerals)
|
||||||
yield pack
|
yield pack
|
||||||
|
|
||||||
@fixture(name="report")
|
@fixture(name="report")
|
||||||
def createReport(pack):
|
def createReport(pack, tmp_path):
|
||||||
report = MineralReport(pack)
|
report = MineralReport(pack, tmp_path)
|
||||||
report.build()
|
report.write()
|
||||||
yield report
|
yield report
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
|
|
||||||
def test_report(report):
|
def test_report(tmp_path, report):
|
||||||
assert str(report) == textwrap.dedent("""
|
path = tmp_path / "testModPack" / "reports" / "minerals.md"
|
||||||
|
|
||||||
|
assert path.read_text() == textwrap.dedent("""
|
||||||
# Mineral: copper
|
# Mineral: copper
|
||||||
|
|
||||||
* #minecraft:stone_replaceables => minecraft:copper_ore
|
* #minecraft:stone_replaceables => minecraft:copper_ore
|
||||||
@@ -50,4 +52,5 @@ def test_report(report):
|
|||||||
|
|
||||||
* #minecraft:stone_replaceables => minecraft:iron_ore
|
* #minecraft:stone_replaceables => minecraft:iron_ore
|
||||||
* #minecraft:deepslate_replaceables => minecraft:deepslate_iron_ore
|
* #minecraft:deepslate_replaceables => minecraft:deepslate_iron_ore
|
||||||
""").strip()
|
|
||||||
|
""").lstrip()
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
from mcpacker.emit.markdown.report import Report
|
|
||||||
from mcpacker.model.core.ecology.biometrait import BiomeTrait
|
from mcpacker.model.core.ecology.biometrait import BiomeTrait
|
||||||
from mcpacker.model.modpack import ModPack
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.markdown.markdownwriter import MarkdownWriter
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# Class ############################################################################################
|
# Class ############################################################################################
|
||||||
|
|
||||||
class MobReport(Report):
|
class MobSpawnReport(MarkdownWriter):
|
||||||
|
|
||||||
def __init__(self, pack:ModPack):
|
def __init__(self, pack:ModPack, outputDir:Path):
|
||||||
super().__init__("mobs.md", pack)
|
super().__init__("mobspawns.md", pack, outputDir)
|
||||||
|
|
||||||
def build(self):
|
def compose(self):
|
||||||
for placement in self.pack.world.mobs:
|
for spawn in self.pack.world.mobSpawns:
|
||||||
self.line(f"# Mob: {placement.gameId}")
|
self.line(f"# Mob: {spawn.gameId}")
|
||||||
self.line()
|
self.line()
|
||||||
|
|
||||||
self.indent()
|
self.indent()
|
||||||
for index, habitat in enumerate(placement.habitats, start=1):
|
for index, habitat in enumerate(spawn.habitats, start=1):
|
||||||
self.text("* habitat ").line(index)
|
self.text("* habitat ").line(index)
|
||||||
self.indent()
|
self.indent()
|
||||||
self.text("* altitude: ").line(habitat.altitude)
|
self.text("* altitude: ").line(habitat.altitude)
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF
|
||||||
|
from mcpacker.model.core.fauna.mob import Mob
|
||||||
|
from mcpacker.model.core.fauna.mobspawn import MobSpawn
|
||||||
|
from mcpacker.model.core.geology.mineral import Mineral
|
||||||
|
from mcpacker.model.core.geology.replacement import Replacement
|
||||||
|
from mcpacker.model.core.habitat import Habitat
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from mcpacker.write.markdown.mobspawnreport import MobSpawnReport
|
||||||
|
from pytest import fixture
|
||||||
|
|
||||||
|
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 textwrap
|
||||||
|
|
||||||
|
|
||||||
|
# Fixtures #########################################################################################
|
||||||
|
|
||||||
|
@fixture(name="addMobs")
|
||||||
|
def defineAddMobs():
|
||||||
|
def addMobs(pack:ModPack):
|
||||||
|
pack.world.mobs.add(Mob("minecraft:chicken", AC.DIURNAL))
|
||||||
|
|
||||||
|
yield addMobs
|
||||||
|
|
||||||
|
@fixture(name="addMobSpawns")
|
||||||
|
def defineAddMobSpawnss():
|
||||||
|
def addMobSpawns(pack:ModPack):
|
||||||
|
mobs = pack.world.mobs
|
||||||
|
spawns = pack.world.mobSpawns
|
||||||
|
|
||||||
|
pack.world.mobSpawns.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,
|
||||||
|
).derive(
|
||||||
|
seasons = SE.exclude(SE.SUMMER),
|
||||||
|
scarcity = SC.UNCOMMON
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
yield addMobSpawns
|
||||||
|
|
||||||
|
@fixture(name="pack")
|
||||||
|
def createPack(addMobs, addMobSpawns):
|
||||||
|
pack = ModPack("testModPack")
|
||||||
|
pack.augment(addMobs)
|
||||||
|
pack.augment(addMobSpawns)
|
||||||
|
yield pack
|
||||||
|
|
||||||
|
@fixture(name="report")
|
||||||
|
def createReport(pack, tmp_path):
|
||||||
|
report = MobSpawnReport(pack, tmp_path)
|
||||||
|
report.write()
|
||||||
|
yield report
|
||||||
|
|
||||||
|
# Tests ############################################################################################
|
||||||
|
|
||||||
|
def test_write(report, tmp_path):
|
||||||
|
path = tmp_path / "testModPack" / "reports" / "mobspawns.md"
|
||||||
|
assert path.read_text() == textwrap.dedent("""
|
||||||
|
# Mob: minecraft:chicken
|
||||||
|
|
||||||
|
* habitat 1
|
||||||
|
* altitude: lowlands-uplands
|
||||||
|
* biomeFilter:
|
||||||
|
* Heat: tropical
|
||||||
|
* Humidity: wet
|
||||||
|
* Flora: any of: canopy, forest, clearing
|
||||||
|
* seasons: summer
|
||||||
|
* group: troup
|
||||||
|
* location: outside
|
||||||
|
* scarcity: common
|
||||||
|
* habitat 2
|
||||||
|
* altitude: lowlands-uplands
|
||||||
|
* biomeFilter:
|
||||||
|
* Heat: tropical
|
||||||
|
* Humidity: wet
|
||||||
|
* Flora: any of: canopy, forest, clearing
|
||||||
|
* seasons: spring, autumn, winter
|
||||||
|
* group: troup
|
||||||
|
* location: outside
|
||||||
|
* scarcity: uncommon
|
||||||
|
|
||||||
|
""").lstrip()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from mcpacker.emit.markdown.report import Report
|
from mcpacker.write.markdown.report import Report
|
||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from mcpacker.emit.markdown.report import Report
|
from mcpacker.write.markdown.report import Report
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import mcpacker.emit.markdown.reportwriter
|
import mcpacker.write.markdown.reportwriter
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import mcpacker.emit.resourcepack
|
import mcpacker.write.resourcepack
|
||||||
|
|
||||||
|
|
||||||
# Tests ############################################################################################
|
# Tests ############################################################################################
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
from collections.abc import Iterable
|
||||||
|
from mcpacker.model.modpack import ModPack
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TypeVar
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
|
# Type Support #####################################################################################
|
||||||
|
|
||||||
|
WriterSubclass = TypeVar("WriterSubclass", bound="Writer")
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
|
||||||
|
def __init__(self, pack:ModPack, outputDir:Path):
|
||||||
|
self.pack = pack
|
||||||
|
self.outputDir = outputDir
|
||||||
|
|
||||||
|
def resetOutputDir(self):
|
||||||
|
if self.outputDir.exists():
|
||||||
|
shutil.rmtree(self.outputDir)
|
||||||
|
|
||||||
|
self.outputDir.mkdir(parents=True)
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
# Class ############################################################################################
|
||||||
|
|
||||||
|
class CompositeWriter(Writer):
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
pack:ModPack,
|
||||||
|
outputDir:Path,
|
||||||
|
writers:Iterable[type[WriterSubclass]]|None=None
|
||||||
|
):
|
||||||
|
super().__init__(pack, outputDir)
|
||||||
|
|
||||||
|
self._writers:list[Writer] = []
|
||||||
|
for writerClass in (writers or []):
|
||||||
|
self.add(writerClass)
|
||||||
|
|
||||||
|
def add(self, writerClass:type[WriterSubclass]):
|
||||||
|
self._writers.append(writerClass(self.pack, self.outputDir))
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
for writer in self._writers:
|
||||||
|
writer.write()
|
||||||
Reference in New Issue
Block a user