109 lines
4.1 KiB
Python
109 lines
4.1 KiB
Python
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),
|
|
}
|