Add mypy; Consolidate catalog classes

This commit is contained in:
Andrew Miner
2025-10-08 21:55:10 -06:00
parent b96a456b03
commit 52a3fdc328
74 changed files with 1169 additions and 784 deletions
+22
View File
@@ -0,0 +1,22 @@
import subprocess
####################################################################################################
def test_typeCompliance():
command = [
"mypy",
#"--allow-untyped-defs",
#"--follow-imports", "skip",
#"--ignore-missing-imports",
#"--no-check-untyped-defs",
"--python-version", "3.10",
"--show-error-codes",
"mcpacker"
]
result = subprocess.run(command, capture_output=True, text=True)
print(result.stdout)
returncode = result.returncode
assert returncode == 0
+2 -1
View File
@@ -5,8 +5,9 @@ from os.path import join
class Locator: class Locator:
def __init__(self, basePath:str): def __init__(self, basePath:str, mod:str):
self.basePath = basePath self.basePath = basePath
self.mod = mod
def biomeModifier(self) -> str: def biomeModifier(self) -> str:
return join(self.basePath, "data", self.mod, "neoforge", "biome_modifier") return join(self.basePath, "data", self.mod, "neoforge", "biome_modifier")
View File
@@ -0,0 +1,4 @@
class SpawnerRuleEmitter:
def __init__(self):
pass
+1 -1
View File
@@ -10,7 +10,7 @@ class BiomeReport(Report):
super().__init__("biomes.md", pack) super().__init__("biomes.md", pack)
def build(self): def build(self):
for biome in self.pack.world.biomes.all(): 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()
+1 -1
View File
@@ -10,7 +10,7 @@ class MineralReport(Report):
super().__init__("minerals.md", pack) super().__init__("minerals.md", pack)
def build(self): def build(self):
for mineral in self.pack.world.minerals.all(): for mineral in self.pack.world.minerals:
self.line(f"# Mineral: {mineral.name}") self.line(f"# Mineral: {mineral.name}")
self.line() self.line()
+2 -2
View File
@@ -11,8 +11,8 @@ class MobReport(Report):
super().__init__("mobs.md", pack) super().__init__("mobs.md", pack)
def build(self): def build(self):
for placement in self.pack.world.mobs.all(): for placement in self.pack.world.mobs:
self.line(f"# Mob: {placement.mob.name} <{placement.mob.gameId}>") self.line(f"# Mob: {placement.gameId}")
self.line() self.line()
self.indent() self.indent()
+2 -2
View File
@@ -32,8 +32,8 @@ class Report:
raise NotImplementedError() raise NotImplementedError()
def reset(self) -> "Report": def reset(self) -> "Report":
self._lineBuffer = [] self._lineBuffer:list[str] = []
self._lines = [] self._lines:list[str] = []
self._indent = 0 self._indent = 0
return self return self
+24
View File
@@ -0,0 +1,24 @@
from json import dump
from json import dumps
from json import load
from json import loads
from typing import TypeAlias
# Type Support #####################################################################################
JsonBlob:TypeAlias = dict[str, "JsonBlob"] | list["JsonBlob"] | str | int | float | bool | None
# Functions ########################################################################################
def removeNoneValues(blob:JsonBlob) -> JsonBlob:
if not isinstance(blob, dict): return blob
for key in list(blob.keys()):
if blob[key] == None:
del blob[key]
else:
removeNoneValues(blob[key])
return blob
+74
View File
@@ -0,0 +1,74 @@
from collections.abc import Iterable
from typing import Any
from typing import Callable
from typing import Generic
from typing import Iterator
from typing import Protocol
from typing import TypeVar
# Type Support #####################################################################################
class HasGameId(Protocol):
@property
def gameId(self) -> str: ...
CatalogItem = TypeVar("CatalogItem", bound=HasGameId)
MapTarget = TypeVar("MapTarget")
# Class ############################################################################################
class Catalog(Generic[CatalogItem]):
def __init__(self, items:Iterable[CatalogItem]|None=None):
self._items:dict[str,CatalogItem] = {}
for item in (items or []):
self.add(item)
def __contains__(self, gameId:str) -> bool:
return gameId in self._items
def __delitem__(self, gameId:str):
del self._items[gameId]
def __eq__(self, other:Any) -> bool:
if type(self) != type(other): return False
if self._items != other._items: return False
return True
def __getitem__(self, gameId:str) -> CatalogItem:
return self._items[gameId]
def __iter__(self) -> Iterator[CatalogItem]:
for gameId in sorted([i.gameId for i in self._items.values()]):
yield self._items[gameId]
def __len__(self) -> int:
return len(self._items)
def __repr__(self) -> str:
return "".join(str(p) for p in [
self.__class__.__name__, "[",
", ".join(str(i) for i in self),
"]"
])
def add(self, item:CatalogItem) -> "Catalog[CatalogItem]":
if item.gameId in self._items:
raise Exception(f"Catalog already contains {item.gameId}")
self._items[item.gameId] = item
return self
def filter(self, isAllowed:Callable[[CatalogItem], bool]) -> Iterator[CatalogItem]:
for item in self:
if isAllowed(item):
yield item
def map(self, doTransform:Callable[[CatalogItem], MapTarget]) -> Iterator[MapTarget]:
for item in self:
yield doTransform(item)
+88
View File
@@ -0,0 +1,88 @@
from mcpacker.model.catalog import Catalog
from pytest import fixture
from typing import Any
# Helpers ##########################################################################################
class SampleItem:
def __init__(self, gameId:str):
self.gameId = gameId
def __eq__(self, other:Any):
return self.gameId == other.gameId
def __repr__(self) -> str:
return self.gameId
# Fixtures #########################################################################################
@fixture(name="empty")
def buildEmptyCatalog():
yield Catalog()
@fixture(name="full")
def buildFullCatalog():
yield Catalog([
SampleItem("alpha"),
SampleItem("bravo"),
SampleItem("charlie"),
SampleItem("delta"),
])
@fixture(name="almostFull")
def buildAlmostFullCatalog(full):
del full["bravo"]
yield full
@fixture(name="almostEmpty")
def buildAlmostEmptyCatalog(empty):
empty.add(SampleItem("echo"))
yield empty
@fixture(name="filtered")
def buildFilteredList(full):
yield list(full.filter(lambda x: x.gameId.endswith("a")))
@fixture(name="mapped")
def buildMappedList(full):
yield list(full.map(lambda x: x.gameId))
# Tests ############################################################################################
def test_add(almostEmpty):
assert "echo" in almostEmpty
def test_contains(empty, full):
assert "bravo" not in empty
assert "bravo" in full
def test_del(almostFull):
assert "bravo" not in almostFull
def test_eq():
assert Catalog([SampleItem("alpha")]) == Catalog([SampleItem("alpha")])
assert Catalog([SampleItem("alpha")]) != Catalog([SampleItem("bravo")])
def test_filter(filtered):
assert [a.gameId for a in filtered] == ["alpha", "delta"]
def test_getitem(full):
assert full["bravo"].gameId == "bravo"
def test_iter(full):
assert [s.gameId for s in full] == ["alpha", "bravo", "charlie", "delta"]
def test_len(empty, full):
assert len(empty) == 0
assert len(full) == 4
def test_map(mapped):
assert mapped == ["alpha", "bravo", "charlie", "delta"]
def test_repr(empty, full):
assert repr(empty) == "Catalog[]"
assert repr(full) == "Catalog[alpha, bravo, charlie, delta]"
+21
View File
@@ -0,0 +1,21 @@
# Class ############################################################################################
class Dimension:
def __init__(self, name):
self.name = name
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Dimension<{self.name}>"
# Constants ########################################################################################
OVERWORLD = Dimension("minecraft:overworld")
NETHER = Dimension("minecraft:nether")
END = Dimension("minecraft:end")
ALL = [OVERWORLD, NETHER, END]
@@ -1,4 +1,4 @@
import mcpacker.model.datapack.mod import mcpacker.model.core.dimension
# Tests ############################################################################################ # Tests ############################################################################################
+2 -2
View File
@@ -37,12 +37,12 @@ class Biome(object):
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.biomeId != other.biomeId: return False if self.gameId != other.gameId: return False
if self.city != other.city: return False if self.city != other.city: return False
return True return True
def __hash__(self) -> int: def __hash__(self) -> int:
return hash((self.biomeId, self.city)) return hash((self.gameId, self.city))
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.city}<{self.gameId}>" return f"{self.city}<{self.gameId}>"
+5 -23
View File
@@ -1,32 +1,14 @@
from collections.abc import Iterable from mcpacker.model.catalog import Catalog
from mcpacker.model.core.ecology.biome import Biome from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biomefilter import BiomeFilter from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from typing import Iterator
# Classes ########################################################################################## # Classes ##########################################################################################
class BiomeCatalog: class BiomeCatalog(Catalog[Biome]):
"""
A comprehensive list of all available biomes in the modpack.
"""
def __init__(self, biomes:Iterable[Biome]|None=None): def matching(self, biomeFilter:BiomeFilter) -> Iterator[Biome]:
self._biomes = {} for biome in self:
for biome in (biomes or []):
self.add(biome)
def add(self, biome:Biome) -> "BiomeCatalog":
if biome.gameId in self._biomes:
raise Exception(f"Catalog already contains {biome.gameId}")
self._biomes[biome.gameId] = biome
def all(self) -> Iterable[Biome]:
for gameId in sorted([b.gameId for b in self._biomes.values()]):
yield self._biomes[gameId]
def matching(self, biomeFilter:BiomeFilter) -> Iterable[Biome]:
for biome in self.all():
if biomeFilter.accepts(biome): if biomeFilter.accepts(biome):
yield biome yield biome
+3 -2
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.ecology.biome import Biome from mcpacker.model.core.ecology.biome import Biome
from mcpacker.model.core.ecology.biometrait import BiomeTrait from mcpacker.model.core.ecology.biometrait import BiomeTrait
@@ -25,8 +26,8 @@ class BiomeFilter:
def __init__( def __init__(
self, self,
required:list[BiomeTrait|list[BiomeTrait]]=None, required:Iterable[BiomeTrait|Iterable[BiomeTrait]]|None=None,
prohibited:list[BiomeTrait]=None, prohibited:Iterable[BiomeTrait]|None=None,
): ):
self.required = required or [] self.required = required or []
self.prohibited = prohibited or [] self.prohibited = prohibited or []
+13 -1
View File
@@ -1,3 +1,6 @@
from typing import TypeVar
# Class ############################################################################################ # Class ############################################################################################
class BiomeTrait: class BiomeTrait:
@@ -23,9 +26,18 @@ class BiomeTrait:
return f"{type(self).__name__}<{self.name}>" return f"{type(self).__name__}<{self.name}>"
# Type Support #####################################################################################
BiomeTraitSubclass = TypeVar("BiomeTraitSubclass", bound=BiomeTrait)
# Helper Functions ################################################################################# # Helper Functions #################################################################################
def within(allTraits:list[BiomeTrait], start:BiomeTrait, end:BiomeTrait) -> list[BiomeTrait]: def within(
allTraits:list[BiomeTraitSubclass],
start:BiomeTraitSubclass,
end:BiomeTraitSubclass
) -> list[BiomeTraitSubclass]:
if not allTraits: return [] if not allTraits: return []
start = start if start else allTraits[0] start = start if start else allTraits[0]
end = end if end else allTraits[-1] end = end if end else allTraits[-1]
+2 -1
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.ecology.biometrait import BiomeTrait from mcpacker.model.core.ecology.biometrait import BiomeTrait
import mcpacker.model.core.ecology.biometrait as biomeTrait import mcpacker.model.core.ecology.biometrait as biomeTrait
@@ -23,5 +24,5 @@ ALL = [WET, DAMP, DRY]
# Helpers ########################################################################################## # Helpers ##########################################################################################
def within(start:Humidity, end:Humidity) -> list[Humidity]: def within(start:Humidity, end:Humidity) -> Iterable[Humidity]:
return biomeTrait.within(ALL, start, end) return biomeTrait.within(ALL, start, end)
+6 -1
View File
@@ -24,7 +24,12 @@ NIGHT = Active("night", 13000, 23000)
SUNRISE = Active("sunrise", 23000, 24000) SUNRISE = Active("sunrise", 23000, 24000)
SUNSET = Active("sunset", 12000, 13000) SUNSET = Active("sunset", 12000, 13000)
ANY = (SUNRISE, DAY, SUNSET, NIGHT) ANY = Active("any", 0, 24000)
RAINY = Active("rainy", 0, 24000)
STORMY = Active("stormy", 0, 24000)
MIDNIGHT = Active("midnight", 18000, 19000)
ALL = (SUNRISE, DAY, SUNSET, NIGHT)
DIURNAL = (DAY) DIURNAL = (DAY)
NOCTURNAL = (NIGHT) NOCTURNAL = (NIGHT)
CREPUSCULAR = (SUNRISE, SUNSET) CREPUSCULAR = (SUNRISE, SUNSET)
+4 -4
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.fauna.active import Active from mcpacker.model.core.fauna.active import Active
import mcpacker.model.core.fauna.active as AC import mcpacker.model.core.fauna.active as AC
@@ -10,8 +11,7 @@ class Mob:
A creature which may appear in the game world. A creature which may appear in the game world.
""" """
def __init__(self, name:str, gameId:str, active:tuple[Active]=AC.DIURNAL): def __init__(self, gameId:str, active:Active|Iterable[Active]=AC.DIURNAL):
self.name = name
self.gameId = gameId self.gameId = gameId
self.active = active self.active = active
@@ -30,7 +30,7 @@ class Mob:
return hash(self.gameId) return hash(self.gameId)
def __str__(self) -> str: def __str__(self) -> str:
return self.name return self.gameId
def __repr__(self) -> str: def __repr__(self) -> str:
return f"{self.name}<{self.gameId}>{{active:{self.active}}}" return f"Mob<{self.gameId}>{{active:{self.active}}}"
+6 -6
View File
@@ -8,11 +8,11 @@ import mcpacker.model.core.fauna.active as AC
@fixture(name="squid") @fixture(name="squid")
def createSquid(): def createSquid():
yield Mob("squid", "minecraft:squid", AC.ANY) yield Mob("minecraft:squid", AC.ANY)
@fixture(name="cow") @fixture(name="cow")
def createCow(): def createCow():
yield Mob("cow", "minecraft:cow", AC.DIURNAL) yield Mob("minecraft:cow", AC.DIURNAL)
@fixture(name="mobMap") @fixture(name="mobMap")
def createMobMap(cow, squid): def createMobMap(cow, squid):
@@ -25,15 +25,15 @@ def createMobMap(cow, squid):
# Tests ############################################################################################ # Tests ############################################################################################
def test_eq(squid): def test_eq(squid):
assert squid == Mob("squid", "minecraft:squid") assert squid == Mob("minecraft:squid")
assert squid != Mob("squid", "animalsplus:squid") assert squid != Mob("animalsplus:squid")
def test_hash(cow, squid, mobMap): def test_hash(cow, squid, mobMap):
assert mobMap[cow] == "beef" assert mobMap[cow] == "beef"
assert mobMap[squid] == "calamari" assert mobMap[squid] == "calamari"
def test_str(squid): def test_str(squid):
assert str(squid) == "squid" assert str(squid) == "minecraft:squid"
def test_repr(cow): def test_repr(cow):
assert repr(cow) == "cow<minecraft:cow>{active:(Active<day>{start:0, end:12000},)}" assert repr(cow) == "Mob<minecraft:cow>{active:(Active<day>{start:0, end:12000},)}"
+5 -23
View File
@@ -1,26 +1,8 @@
from collections.abc import Iterable from mcpacker.model.catalog import Catalog
from mcpacker.model.core.fauna.mobplacement import MobPlacement from mcpacker.model.core.fauna.mob import Mob
# Class ############################################################################################ # Classes ##########################################################################################
class MobCatalog: class MobCatalog(Catalog[Mob]):
pass
def __init__(self, mobs:Iterable[MobPlacement]|None=None):
self._mobs = {}
for mob in (mobs or []):
self.add(mob)
def add(self, placement:MobPlacement) -> "MobCatalog":
if placement.mob.name in self._mobs:
raise Exception("Catalog already has an entry for {mob.name}")
self._mobs[placement.mob.name] = placement
def all(self) -> Iterable[MobPlacement]:
for placement in self._mobs.values():
yield placement
def get(self, name:str) -> MobPlacement:
return self._mobs.get(name, None)
-15
View File
@@ -1,15 +0,0 @@
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.placement import Placement
# Class ############################################################################################
class MobPlacement(Placement):
"""
A description of where a creature should appear in the world.
"""
def __init__(self, mob:Mob, habitats:list[Habitat]=None):
super().__init__(habitats)
self.mob = mob
+20
View File
@@ -0,0 +1,20 @@
from collections.abc import Iterable
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.spawn import Spawn
# Class ############################################################################################
class MobSpawn(Spawn):
"""
A description of where a creature should appear in the world.
"""
def __init__(self, mob:Mob, habitats:Iterable[Habitat]|Habitat|None=None):
super().__init__(habitats)
self.mob = mob
@property
def gameId(self) -> str:
return self.mob.gameId
@@ -1,6 +1,6 @@
from mcpacker.model.core.ecology.biomefilter import BiomeFilter from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.fauna.mob import Mob from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.fauna.mobplacement import MobPlacement from mcpacker.model.core.fauna.mobspawn import MobSpawn
from mcpacker.model.core.habitat import Habitat from mcpacker.model.core.habitat import Habitat
from pytest import fixture from pytest import fixture
@@ -18,16 +18,16 @@ def createCow():
def createFieldsHabitat(): def createFieldsHabitat():
yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE])) yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE]))
@fixture(name="placement") @fixture(name="spawn")
def createMobPlacement(cow, fields): def createMobSpawn(cow, fields):
yield MobPlacement(cow, fields) yield MobSpawn(cow, fields)
# Tests ############################################################################################ # Tests ############################################################################################
def test_cowsInFields(placement): def test_cowsInFields(spawn):
assert str(placement) == ( assert str(spawn) == (
"Placement{" + "Spawn{" +
"habitats: [" + "habitats: [" +
"Habitat{" + "Habitat{" +
"altitude: anywhere <-64 to 320>, " + "altitude: anywhere <-64 to 320>, " +
@@ -0,0 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.fauna.mobspawn import MobSpawn
# Classes ##########################################################################################
class MobSpawnCatalog(Catalog[MobSpawn]):
pass
@@ -0,0 +1,8 @@
import mcpacker.model.core.fauna.mobspawncatalog
# Tests ############################################################################################
def test_syntax():
pass
@@ -17,6 +17,7 @@ class Deposit:
biomeFilter:BiomeFilter|None=None, biomeFilter:BiomeFilter|None=None,
): ):
self.name = name self.name = name
self.gameId = name
self.biomeFilter = biomeFilter or BiomeFilter() self.biomeFilter = biomeFilter or BiomeFilter()
self.scarcity = scarcity self.scarcity = scarcity
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.ecology.biomefilter import BiomeFilter from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.geology.bulk import Bulk from mcpacker.model.core.geology.bulk import Bulk
from mcpacker.model.core.geology.deposit import Deposit from mcpacker.model.core.geology.deposit import Deposit
@@ -17,10 +18,10 @@ class MetalDeposit(Deposit):
def __init__( def __init__(
self, self,
name:str, name:str,
inclusions:tuple[Inclusion], inclusions:Iterable[Inclusion],
bulk:Bulk=BU.MEDIUM, bulk:Bulk=BU.MEDIUM,
proportion:Proportion=PR.BODY, proportion:Proportion=PR.BODY,
biomeFilter:BiomeFilter=None, biomeFilter:BiomeFilter|None=None,
scarcity:Scarcity=SC.SPARSE, scarcity:Scarcity=SC.SPARSE,
): ):
super().__init__(name, scarcity, biomeFilter) super().__init__(name, scarcity, biomeFilter)
+4 -23
View File
@@ -1,27 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.geology.deposit import Deposit from mcpacker.model.core.geology.deposit import Deposit
from mcpacker.model.core.geology.mineralcatalog import MineralCatalog
from typing import Iterator
# Class ############################################################################################ # Classes ##########################################################################################
class DepositCatalog: class DepositCatalog(Catalog[Deposit]):
pass
def __init__(self, deposits:None|tuple[Deposit]=None):
self._deposits = {}
for deposit in (deposits or []):
self.add(deposit)
def add(self, deposit:Deposit) -> "DepositCatalog":
if deposit.name in self._deposits:
raise Exception("Catalog already has an entry for {deposit.name}")
self._deposits[deposit.name] = deposit
def all(self) -> Iterator[Deposit]:
for deposit in self._deposits.values():
yield deposit
def get(self, name:str) -> Deposit|None:
return self._deposits.get(name, None)
@@ -1,53 +1,7 @@
from mcpacker.model.core.ecology.biomefilter import BiomeFilter import mcpacker.model.core.geology.depositcatalog
from mcpacker.model.core.geology.deposit import Deposit
from mcpacker.model.core.geology.deposit.metaldeposit import MetalDeposit
from mcpacker.model.core.geology.depositcatalog import DepositCatalog
from mcpacker.model.core.geology.inclusion import Inclusion
from mcpacker.model.core.geology.mineral import Mineral
from mcpacker.model.core.geology.replacement import Replacement
from pytest import fixture
import mcpacker.model.core.ecology.flora as FL
import mcpacker.model.core.geology.bulk as BU
import mcpacker.model.core.scarcity as SC
# Fixtures #########################################################################################
@fixture(name="quartz")
def createQuartz():
yield Mineral("quartz", [
Replacement("#minecraft:stone_replaceables", "minecraft:quartz_ore"),
Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_quartz_ore")
])
@fixture(name="iron")
def createIron():
yield Mineral("iron", [
Replacement("#minecraft:stone_replaceables", "minecraft:iron_ore"),
Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_iron_ore")
])
@fixture(name="bifiron")
def createBifIron(iron, quartz):
yield MetalDeposit(
name = "bif_iron",
scarcity = SC.COMMON,
biomeFilter = BiomeFilter([FL.FOREST]),
inclusions = [Inclusion(iron, 60), Inclusion(quartz, 40)],
bulk = BU.LARGE,
proportion = 0.5,
)
@fixture(name="catalog")
def createCatalog(bifiron):
yield DepositCatalog([bifiron])
# Tests ############################################################################################ # Tests ############################################################################################
def test_all(catalog): def test_syntax():
assert [m.name for m in catalog.all()] == ["bif_iron"] pass
def test_get(catalog):
assert catalog.get("bif_iron").name == "bif_iron"
+4 -11
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.geology.replacement import Replacement from mcpacker.model.core.geology.replacement import Replacement
from mcpacker.model.core.resourceid import ResourceId from mcpacker.model.core.resourceid import ResourceId
@@ -6,9 +7,10 @@ from mcpacker.model.core.resourceid import ResourceId
class Mineral: class Mineral:
def __init__(self, name:str, replacements:None|tuple[Replacement]=None): def __init__(self, name:str, replacements:Iterable[Replacement]|None=None):
self.name = name self.name = name
self.replacements = replacements or [] self.gameId = name
self.replacements = list(replacements or [])
def __str__(self) -> str: def __str__(self) -> str:
return self.name return self.name
@@ -21,12 +23,3 @@ class Mineral:
"]", "]",
"}" "}"
]]) ]])
def addStoneReplacement(self, blockId:str) -> "Mineral":
blockId = ResourceId.canonical(blockId)
self.replacements.append(Replacement(STONE_REPLACEABLES, blockId))
return self
def addDeepslateReplacement(self, blockId:str) -> "Mineral":
blockId = ResourceId.canonical(blockId)
self.replacements.append(Replacement(DEEPSLATE_REPLACEABLES, blockId))
+4 -22
View File
@@ -1,26 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.geology.mineral import Mineral from mcpacker.model.core.geology.mineral import Mineral
from typing import Iterator
# Class ############################################################################################ # Classes ##########################################################################################
class MineralCatalog: class MineralCatalog(Catalog[Mineral]):
pass
def __init__(self, minerals:tuple[Mineral]=None):
self._minerals = {}
for mineral in (minerals or []):
self.add(mineral)
def add(self, mineral:Mineral) -> "MineralCatalog":
if mineral.name in self._minerals:
raise Exception(f"Catalog already contains an entry for {mineral.name}")
self._minerals[mineral.name] = mineral
def all(self) -> Iterator[Mineral]:
for mineral in self._minerals.values():
yield mineral
def get(self, name:str) -> Mineral|None:
return self._minerals.get(name, None)
@@ -1,34 +1,7 @@
from mcpacker.model.core.geology.mineral import Mineral import mcpacker.model.core.geology.mineralcatalog
from mcpacker.model.core.geology.mineralcatalog import MineralCatalog
from mcpacker.model.core.geology.replacement import Replacement
from pytest import fixture
# Fixtures #########################################################################################
@fixture(name="copper")
def createCopper():
yield Mineral("copper", [
Replacement("#minecraft:stone_replaceables", "minecraft:copper_ore"),
Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_copper_ore")
])
@fixture(name="iron")
def createIron():
yield Mineral("iron", [
Replacement("#minecraft:stone_replaceables", "minecraft:iron_ore"),
Replacement("#minecraft:deepslate_replaceables", "minecraft:deepslate_iron_ore")
])
@fixture(name="catalog")
def createCatalog(copper, iron):
yield MineralCatalog([copper, iron])
# Tests ############################################################################################ # Tests ############################################################################################
def test_all(catalog): def test_syntax():
assert [m.name for m in catalog.all()] == ["copper", "iron"] pass
def test_get(catalog):
assert catalog.get("iron").name == "iron"
+11 -11
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.altitude import Altitude from mcpacker.model.core.altitude import Altitude
from mcpacker.model.core.ecology.biomefilter import BiomeFilter from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.fauna.group import Group from mcpacker.model.core.fauna.group import Group
@@ -23,8 +24,8 @@ class Habitat:
self, self,
altitude:Altitude=A.ANYWHERE, altitude:Altitude=A.ANYWHERE,
biomeFilter:BiomeFilter=None, biomeFilter:BiomeFilter|None=None,
seasons:tuple[Season]=E.ALL, seasons:Iterable[Season]|Season=E.ALL,
group:Group=G.SOLO, group:Group=G.SOLO,
location:Location=L.OUTSIDE, location:Location=L.OUTSIDE,
@@ -32,7 +33,7 @@ class Habitat:
): ):
self.altitude = altitude self.altitude = altitude
self.biomeFilter = biomeFilter or BiomeFilter() self.biomeFilter = biomeFilter or BiomeFilter()
self.seasons = (seasons,) if isinstance(seasons, Season) else seasons self.seasons = [seasons] if isinstance(seasons, Season) else seasons
self.group = group self.group = group
self.location = location self.location = location
@@ -42,7 +43,7 @@ class Habitat:
def __str__(self) -> str: def __str__(self) -> str:
return "".join([str(p) for p in [ return "".join([str(p) for p in [
", ".join(self.altitude), "|", self.altitude, "|",
self.biomeFilter, "|", self.biomeFilter, "|",
", ".join([str(s) for s in self.seasons]), "|", ", ".join([str(s) for s in self.seasons]), "|",
self.group, "|", self.group, "|",
@@ -77,13 +78,12 @@ class Habitat:
return result return result
def collect(self) -> "tuple[Habitat]": def collect(self) -> "Iterable[Habitat]":
result = [] stack:list[Habitat] = []
current:Habitat|None = self
current = self
while current: while current:
result.append(current) stack.append(current)
current = current._source current = current._source
return tuple(reversed(result)) while stack:
yield stack.pop()
+3 -2
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.material.loottable import LootTable from mcpacker.model.core.material.loottable import LootTable
from mcpacker.model.core.material.soundtype import SoundType from mcpacker.model.core.material.soundtype import SoundType
from mcpacker.model.core.resourceid import ResourceId from mcpacker.model.core.resourceid import ResourceId
@@ -12,11 +13,11 @@ class Block:
def __init__( def __init__(
self, self,
name:str, name:str,
gameId:ResourceId, gameId:str,
loot:LootTable, loot:LootTable,
requiresTool:bool=False, requiresTool:bool=False,
soundType:SoundType=ST.STONE, soundType:SoundType=ST.STONE,
tags:list[str]=None, tags:Iterable[str]|None=None,
): ):
self.gameId = gameId self.gameId = gameId
self.loot = loot self.loot = loot
+4 -26
View File
@@ -1,30 +1,8 @@
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.material.block import Block from mcpacker.model.core.material.block import Block
from typing import Iterator
# Class ############################################################################################ # Classes ##########################################################################################
class BlockCatalog:
def __init__(self, blocks:tuple[Block]=None):
self._blocks = {}
for block in (blocks or []):
self.add(block)
def __len__(self) -> int:
return len(self._blocks)
def add(self, block:Block) -> "BlockCatalog":
if block.name in self._blocks:
raise Exception(f"Catalog already contains an entry for {block.name}")
self._blocks[block.name] = block
def all(self) -> Iterator[Block]:
for block in self._blocks.values():
yield block
def get(self, name:str) -> Block|None:
return self._blocks.get(name, None)
class BlockCatalog(Catalog[Block]):
pass
+1 -4
View File
@@ -5,8 +5,5 @@ from mcpacker.model.core.resourceid import ResourceId
class Item: class Item:
def __init__(self, gameId:ResourceId): def __init__(self, gameId:str):
self.gameId = gameId self.gameId = gameId
if not isinstance(self.gameId, ResourceId):
self.gameId = ResourceId.parse(str(self.gameId))
+5 -2
View File
@@ -1,12 +1,14 @@
from collections.abc import Iterable
from mcpacker.model.catalog import Catalog
from mcpacker.model.core.material.item import Item from mcpacker.model.core.material.item import Item
from typing import Iterator from typing import Iterator
# Class ############################################################################################ # Class ############################################################################################
class ItemCatalog: class ItemCatalog(Catalog[Item]):
def __init__(self, items:tuple[Item]=None): def __init__(self, items:Iterable[Item]|None=None):
self._items = {} self._items = {}
for item in (items or []): for item in (items or []):
@@ -17,6 +19,7 @@ class ItemCatalog:
raise Exception(f"Catalog already contains an entry for {item.gameId}") raise Exception(f"Catalog already contains an entry for {item.gameId}")
self._items[item.gameId] = item self._items[item.gameId] = item
return self
def all(self) -> Iterator[Item]: def all(self) -> Iterator[Item]:
for item in self._items.values(): for item in self._items.values():
+6 -1
View File
@@ -5,6 +5,11 @@ from mcpacker.model.core.material.item import Item
class Loot: class Loot:
@staticmethod
def of(item:Item|None, maxCount:int=1, minCount:int=1, weight:int=1) -> "Loot|None":
if not item: return None
return Loot(item, maxCount, minCount, weight)
def __init__(self, item:Item, maxCount:int=1, minCount:int=1, weight:int=1): def __init__(self, item:Item, maxCount:int=1, minCount:int=1, weight:int=1):
self.item = item self.item = item
self.maxCount = maxCount self.maxCount = maxCount
@@ -21,4 +26,4 @@ class Loot:
]]) ]])
def __str__(self) -> str: def __str__(self) -> str:
return f"{str(item)} ({self.minCount}..{self.maxCount} @ {self.weight})" return f"{str(self.item)} ({self.minCount}..{self.maxCount} @ {self.weight})"
+6 -2
View File
@@ -1,3 +1,4 @@
from collections.abc import Iterable
from mcpacker.model.core.material.loot import Loot from mcpacker.model.core.material.loot import Loot
@@ -5,5 +6,8 @@ from mcpacker.model.core.material.loot import Loot
class LootTable: class LootTable:
def __init__(self, items:list[Loot]): def __init__(self, items:Iterable[Loot]|Loot|None):
self.items = items if isinstance(items, Loot):
items = [items]
self.items = items or []
@@ -1,26 +1,24 @@
from collections.abc import Iterable
from mcpacker.model.core.habitat import Habitat from mcpacker.model.core.habitat import Habitat
# Class ############################################################################################ # Class ############################################################################################
class Placement: class Spawn:
""" """
Abstract base class for placing something into its various habitats. Abstract base class for placing something into its various habitats.
""" """
def __init__(self, habitats:tuple[Habitat]=None): def __init__(self, habitats:Iterable[Habitat]|Habitat|None=None):
self.habitats = habitats if isinstance(habitats, Habitat):
habitats = habitats.collect()
if not self.habitats: self.habitats = habitats or []
self.habitats = ()
if isinstance(self.habitats, Habitat):
self.habitats = self.habitats.collect()
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return (
"Placement{" + "Spawn{" +
f"habitats: [{', '.join([repr(h) for h in self.habitats])}]" + f"habitats: [{', '.join([repr(h) for h in self.habitats])}]" +
"}" "}"
) )
@@ -1,6 +1,6 @@
from mcpacker.model.core.ecology.biomefilter import BiomeFilter from mcpacker.model.core.ecology.biomefilter import BiomeFilter
from mcpacker.model.core.habitat import Habitat from mcpacker.model.core.habitat import Habitat
from mcpacker.model.core.placement import Placement from mcpacker.model.core.spawn import Spawn
from pytest import fixture from pytest import fixture
import mcpacker.model.core.ecology.flora as F import mcpacker.model.core.ecology.flora as F
@@ -13,16 +13,16 @@ import mcpacker.model.core.ecology.heat as E
def createFieldsHabitat(): def createFieldsHabitat():
yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE])) yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE]))
@fixture(name="placement") @fixture(name="spawn")
def createPlacement(fields): def createSpawn(fields):
yield Placement([fields]) yield Spawn([fields])
# Tests ############################################################################################ # Tests ############################################################################################
def test_repr(placement): def test_repr(spawn):
assert repr(placement) == ( assert repr(spawn) == (
"Placement{" + "Spawn{" +
"habitats: [" + "habitats: [" +
"Habitat{" + "Habitat{" +
"altitude: anywhere <-64 to 320>, " + "altitude: anywhere <-64 to 320>, " +
+3
View File
@@ -1,5 +1,6 @@
from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog from mcpacker.model.core.ecology.biomecatalog import BiomeCatalog
from mcpacker.model.core.fauna.mobcatalog import MobCatalog from mcpacker.model.core.fauna.mobcatalog import MobCatalog
from mcpacker.model.core.fauna.mobspawncatalog import MobSpawnCatalog
from mcpacker.model.core.geology.depositcatalog import DepositCatalog from mcpacker.model.core.geology.depositcatalog import DepositCatalog
from mcpacker.model.core.geology.mineralcatalog import MineralCatalog from mcpacker.model.core.geology.mineralcatalog import MineralCatalog
from mcpacker.model.core.material.blockcatalog import BlockCatalog from mcpacker.model.core.material.blockcatalog import BlockCatalog
@@ -18,6 +19,7 @@ class World:
items:ItemCatalog|None=None, items:ItemCatalog|None=None,
minerals:MineralCatalog|None=None, minerals:MineralCatalog|None=None,
mobs:MobCatalog|None=None, mobs:MobCatalog|None=None,
mobSpawns:MobSpawnCatalog|None=None
): ):
self.biomes = biomes or BiomeCatalog() self.biomes = biomes or BiomeCatalog()
self.blocks = blocks or BlockCatalog() self.blocks = blocks or BlockCatalog()
@@ -25,3 +27,4 @@ class World:
self.items = items or ItemCatalog() self.items = items or ItemCatalog()
self.minerals = minerals or MineralCatalog() self.minerals = minerals or MineralCatalog()
self.mobs = mobs or MobCatalog() self.mobs = mobs or MobCatalog()
self.mobSpawns = mobSpawns or MobSpawnCatalog()
+13 -12
View File
@@ -1,39 +1,40 @@
from collections.abc import Iterable from collections.abc import Iterable
from mcpacker.model.datapack.mod import Mod from mcpacker.model.datapack.moddata import ModData
# Class ############################################################################################ # Class ############################################################################################
class DataPack: class DataPack:
def __init__(self, name:str, mods:Iterable[Mod]|None=None): def __init__(self, name:str, mods:Iterable[ModData]|None=None):
self.name = name self.name = name
self._mods = {} self._mods:dict[str,ModData] = {}
self._defaultMod = None self._defaultMod:ModData|None = None
for mod in (mods or []): for mod in (mods or []):
self.add(mod) self.add(mod)
def add(self, mod:Mod) -> "Datapack": def add(self, mod:ModData) -> "DataPack":
if not self._defaultMod: if not self._defaultMod:
self._defaultMod = mod self._defaultMod = mod
self._mods[mod.name] = mod self._mods[mod.name] = mod
return self return self
def get(self, modName:str) -> Mod: def get(self, name:str) -> ModData|None:
return self._mods.get(modName, None) return self._mods.get(name, None)
@property @property
def defaultMod(self) -> Mod: def defaultMod(self) -> ModData|None:
return self._defaultMod return self._defaultMod
@defaultMod.setter @defaultMod.setter
def setDefaultMod(self, mod:Mod) -> "Datapack": def defaultMod(self, mod:ModData):
existingMod = self.get(mod.name) if mod:
if not existingMod: existingModData = self.get(mod.name)
if not existingModData:
self.add(mod) self.add(mod)
elif existingMod != mod: elif existingModData != mod:
raise Exception(f"Datapack already has a mod named {mod.name}") raise Exception(f"Datapack already has a mod named {mod.name}")
self._defaultMod = mod self._defaultMod = mod
+5 -3
View File
@@ -1,16 +1,18 @@
from mcpacker.json import JsonBlob
from typing import Any from typing import Any
from typing import cast
# Class ############################################################################################ # Class ############################################################################################
class BlockState: class BlockState:
def __init__(self, blockId:str, properties:dict[str,str]=None): def __init__(self, blockId:str, properties:JsonBlob|None=None):
self.blockId = blockId self.blockId = blockId
self.properties = properties self.properties = properties
def asData(self) -> dict[str,Any]: def asJsonBlob(self) -> JsonBlob:
result = { "Name": self.blockId } result = cast(dict[str,JsonBlob], { "Name": self.blockId })
if self.properties: if self.properties:
result["Properties"] = self.properties result["Properties"] = self.properties
+2 -2
View File
@@ -11,8 +11,8 @@ def createBlockState():
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(state): def test_asData(state:BlockState):
assert state.asData() == { assert state.asJsonBlob() == {
"Name": "minecraft:button", "Name": "minecraft:button",
"Properties": { "Properties": {
"waterlogged": "true" "waterlogged": "true"
@@ -1,3 +1,6 @@
from mcpacker.json import JsonBlob
# Class ############################################################################################ # Class ############################################################################################
class BlockStateProvider: class BlockStateProvider:
@@ -5,3 +8,5 @@ class BlockStateProvider:
def __init__(self, gameId:str): def __init__(self, gameId:str):
self.gameId = gameId self.gameId = gameId
def asJsonBlob(self) -> JsonBlob:
raise NotImplementedError()
@@ -1,3 +1,4 @@
from mcpacker.json import JsonBlob
from mcpacker.model.datapack.blockstate import BlockState from mcpacker.model.datapack.blockstate import BlockState
from mcpacker.model.datapack.blockstateprovider import BlockStateProvider from mcpacker.model.datapack.blockstateprovider import BlockStateProvider
from typing import Any from typing import Any
@@ -11,8 +12,8 @@ class SimpleStateProvider(BlockStateProvider):
super().__init__("minecraft:simple_state_provider") super().__init__("minecraft:simple_state_provider")
self.state = state self.state = state
def asData(self) -> dict[str, Any]: def asJsonBlob(self) -> JsonBlob:
return { return {
"type": self.gameId, "type": self.gameId,
"state": self.state.asData(), "state": self.state.asJsonBlob(),
} }
@@ -10,14 +10,14 @@ def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"}) yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider") @fixture(name="provider")
def createProvider(state): def createProvider(state:BlockState):
return SimpleStateProvider(state) return SimpleStateProvider(state)
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(provider): def test_asData(provider:SimpleStateProvider):
assert provider.asData() == { assert provider.asJsonBlob() == {
"type": "minecraft:simple_state_provider", "type": "minecraft:simple_state_provider",
"state": { "state": {
"Name": "minecraft:button", "Name": "minecraft:button",
@@ -1,5 +1,9 @@
from mcpacker.model.datapack.configuredfeature import ConfiguredFeature from mcpacker.model.datapack.configuredfeature import ConfiguredFeature
from typing import Any from typing import Any
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mcpacker.model.datapack.placedfeature import PlacedFeature
# Class ############################################################################################ # Class ############################################################################################
@@ -9,7 +13,7 @@ class RandomPatch(ConfiguredFeature):
def __init__( def __init__(
self, self,
gameId:str, gameId:str,
feature:"PlacedFeature", feature:PlacedFeature,
tries:int=128, tries:int=128,
xzSpread:int=7, xzSpread:int=7,
ySpread:int=3, ySpread:int=3,
@@ -23,9 +27,9 @@ class RandomPatch(ConfiguredFeature):
def asData(self) -> dict[str,Any]: def asData(self) -> dict[str,Any]:
return { return {
"type": self.type, "type": self.gameId,
"feature": self.feature.gameId, "feature": self.feature.gameId,
"tries": self.tries, "tries": self.tries,
"xz_spread": self.xySpread, "xz_spread": self.xzSpread,
"y_spread": self.ySpread "y_spread": self.ySpread
} }
@@ -11,18 +11,18 @@ def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"}) yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider") @fixture(name="provider")
def createProvider(state): def createProvider(state:BlockState):
return SimpleStateProvider(state) return SimpleStateProvider(state)
@fixture(name="feature") @fixture(name="feature")
def createSimpleBlockFeature(provider): def createSimpleBlockFeature(provider:SimpleStateProvider):
return SimpleBlock(provider) return SimpleBlock(provider)
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(feature): def test_asData(feature:SimpleBlock):
assert feature.asData() == { assert feature.asJsonBlob() == {
"type": "minecraft:simple_block", "type": "minecraft:simple_block",
"config": { "config": {
"to_place": { "to_place": {
@@ -1,3 +1,4 @@
from mcpacker.json import JsonBlob
from mcpacker.model.datapack.blockstateprovider import BlockStateProvider from mcpacker.model.datapack.blockstateprovider import BlockStateProvider
from mcpacker.model.datapack.configuredfeature import ConfiguredFeature from mcpacker.model.datapack.configuredfeature import ConfiguredFeature
from typing import Any from typing import Any
@@ -11,10 +12,10 @@ class SimpleBlock(ConfiguredFeature):
super().__init__("minecraft:simple_block") super().__init__("minecraft:simple_block")
self.toPlace = toPlace self.toPlace = toPlace
def asData(self) -> dict[str, Any]: def asJsonBlob(self) -> JsonBlob:
return { return {
"type": self.gameId, "type": self.gameId,
"config": { "config": {
"to_place": self.toPlace.asData() "to_place": self.toPlace.asJsonBlob()
} }
} }
@@ -11,18 +11,18 @@ def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"}) yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider") @fixture(name="provider")
def createProvider(state): def createProvider(state:BlockState):
return SimpleStateProvider(state) return SimpleStateProvider(state)
@fixture(name="feature") @fixture(name="feature")
def createSimpleBlockFeature(provider): def createSimpleBlockFeature(provider:SimpleStateProvider):
return SimpleBlock(provider) return SimpleBlock(provider)
# Tests ############################################################################################ # Tests ############################################################################################
def test_asData(feature): def test_asData(feature:SimpleBlock):
assert feature.asData() == { assert feature.asJsonBlob() == {
"type": "minecraft:simple_block", "type": "minecraft:simple_block",
"config": { "config": {
"to_place": { "to_place": {
-17
View File
@@ -1,17 +0,0 @@
# Class ############################################################################################
class Mod:
def __init__(self):
self.biomeModifiers = []
self.configuredFeatures = []
self.functions = []
self.functionTags = []
self.lootModifiers = []
self.lootTables = []
self.placedFeatures = []
self.recipes = []
self.structures = []
self.structureSets = []
self.tags = []
self.templatePools = []
+23
View File
@@ -0,0 +1,23 @@
from mcpacker.model.datapack.configuredfeature import ConfiguredFeature
from mcpacker.model.datapack.placedfeature import PlacedFeature
from typing import Any
# Class ############################################################################################
class ModData:
def __init__(self, name:str):
self.name = name
self.biomeModifiers:list[Any] = []
self.configuredFeatures:list[ConfiguredFeature] = []
self.functions:list[Any] = []
self.functionTags:list[Any] = []
self.lootModifiers:list[Any] = []
self.lootTables:list[Any] = []
self.placedFeatures:list[PlacedFeature] = []
self.recipes:list[Any] = []
self.structures:list[Any] = []
self.structureSets:list[Any] = []
self.tags:list[Any] = []
self.templatePools:list[Any] = []
@@ -1,8 +1,7 @@
import mcpacker.model.resourcepack.mod import mcpacker.model.datapack.moddata
# Tests ############################################################################################ # Tests ############################################################################################
def test_syntax(): def test_syntax():
pass pass
+38
View File
@@ -0,0 +1,38 @@
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(),
})
@@ -0,0 +1,44 @@
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,
})
+41
View File
@@ -0,0 +1,41 @@
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(),
}
+1
View File
@@ -29,3 +29,4 @@ class ModPack:
def augment(self, doAugment:"Callable[[ModPack], None]") -> "ModPack": def augment(self, doAugment:"Callable[[ModPack], None]") -> "ModPack":
doAugment(self) doAugment(self)
return self
+10 -9
View File
@@ -1,35 +1,36 @@
from collections.abc import Iterable from collections.abc import Iterable
from mcpacker.model.resourcepack.mod import Mod from mcpacker.model.resourcepack.modresource import ModResource
# Class ############################################################################################ # Class ############################################################################################
class ResourcePack: class ResourcePack:
def __init__(self, name:str, mods:Iterable[Mod]|None=None): def __init__(self, name:str, mods:Iterable[ModResource]|None=None):
self.name = name self.name = name
self._mods = {} self._mods:dict[str,ModResource] = {}
self._defaultMod = None self._defaultMod:ModResource|None = None
for mod in (mods or []): for mod in (mods or []):
self.add(mod) self.add(mod)
def add(self, mod:Mod) -> "Resourcepack": def add(self, mod:ModResource) -> "ResourcePack":
if not self._defaultMod: if not self._defaultMod:
self._defaultMod = mod self._defaultMod = mod
self._mods[mod.name] = mod self._mods[mod.name] = mod
return self return self
def get(self, modName:str) -> Mod: def get(self, name:str) -> ModResource|None:
return self._mods.get(modName, None) return self._mods.get(name, None)
@property @property
def defaultMod(self) -> Mod: def defaultMod(self) -> ModResource|None:
return self._defaultMod return self._defaultMod
@defaultMod.setter @defaultMod.setter
def setDefaultMod(self, mod:Mod) -> "Resourcepack": def defaultMod(self, mod:ModResource):
if mod:
existingMod = self.get(mod.name) existingMod = self.get(mod.name)
if not existingMod: if not existingMod:
self.add(mod) self.add(mod)
+1 -1
View File
@@ -7,7 +7,7 @@ class Kind:
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.name != othere.name: return False if self.name != other.name: return False
return True return True
def __repr__(self) -> str: def __repr__(self) -> str:
-8
View File
@@ -1,8 +0,0 @@
# Class ############################################################################################
class Mod:
def __init__(self):
self.blockStates = []
self.models = []
self.textures = []
@@ -0,0 +1,9 @@
# Class ############################################################################################
class ModResource:
def __init__(self, name:str):
self.name = name
self.blockStates:list[str] = []
self.models:list[str] = []
self.textures:list[str] = []
@@ -0,0 +1,8 @@
import mcpacker.model.resourcepack.modresource
# Tests ############################################################################################
def test_syntax():
pass
+1 -1
View File
@@ -16,7 +16,7 @@ def addBlocks(pack:ModPack):
blocks.add(Block( blocks.add(Block(
gameId = "kubejs:peat_block", gameId = "kubejs:peat_block",
loot = LootTable(Loot(items.get("kubejs:peat_chunk"), 2, 9)), loot = LootTable(Loot.of(items.get("kubejs:peat_chunk"), 2, 9)),
name = "Peat Block", name = "Peat Block",
soundType = SO.DIRT, soundType = SO.DIRT,
tags = ["minecraft:mineable/shovel"], tags = ["minecraft:mineable/shovel"],
@@ -11,6 +11,7 @@ import mcpacker.model.core.ecology.humidity as HU
import mcpacker.model.core.ecology.soil as SO import mcpacker.model.core.ecology.soil as SO
import mcpacker.model.core.ecology.water as WA import mcpacker.model.core.ecology.water as WA
import mcpacker.model.core.geology.bulk as BU import mcpacker.model.core.geology.bulk as BU
import mcpacker.model.core.geology.proportion as PR
import mcpacker.model.core.scarcity as SC import mcpacker.model.core.scarcity as SC
# Catalog ########################################################################################## # Catalog ##########################################################################################
@@ -24,10 +25,10 @@ def addDeposits(pack:ModPack):
scarcity = SC.COMMON, scarcity = SC.COMMON,
biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]), biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]),
inclusions = [ inclusions = [
I(minerals.get("iron"), 50), I(minerals["iron"], 50),
I(minerals.get("quartz"), 45), I(minerals["quartz"], 45),
I(minerals.get("uranium"), 5) I(minerals["uranium"], 5)
], ],
bulk = BU.LARGE, bulk = BU.LARGE,
proportion = 0.2, proportion = PR.BED,
)) ))
+64 -366
View File
@@ -1,22 +1,7 @@
from mcpacker.model.core.ecology.biomefilter import BiomeFilter as BF
from mcpacker.model.core.fauna.mob import Mob from mcpacker.model.core.fauna.mob import Mob
from mcpacker.model.core.fauna.mobcatalog import MobCatalog
from mcpacker.model.core.fauna.mobplacement import MobPlacement
from mcpacker.model.core.habitat import Habitat
from mcpacker.model.modpack import ModPack 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.fauna.active as AC 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 ######################################################################################## # Constants ########################################################################################
@@ -24,354 +9,67 @@ import mcpacker.model.core.season as SE
def addMobs(pack:ModPack): def addMobs(pack:ModPack):
mobs = pack.world.mobs mobs = pack.world.mobs
mobs.add( mobs.add(Mob("animalplus:raccoon", AC.NOCTURNAL))
MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL), mobs.add(Mob("animalplus:red_panda", AC.CREPUSCULAR))
Habitat( mobs.add(Mob("bearminimum:black_bear", AC.CREPUSCULAR))
altitude = AL.LOWLANDS, mobs.add(Mob("bearminimum:brown_bear", AC.CREPUSCULAR))
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY]), mobs.add(Mob("cold_sweat:chameleon", AC.DIURNAL))
seasons = SE.SUMMER, mobs.add(Mob("crabbersdelight:crab", AC.CREPUSCULAR))
group = GR.merge(GR.SOLO, GR.PAIR), mobs.add(Mob("immersiveengineering:bulwark"))
scarcity = SC.COMMON mobs.add(Mob("immersiveengineering:commando"))
).derive( mobs.add(Mob("immersiveengineering:fusilier"))
altitude = AL.UPLANDS, scarcity = SC.SPARSE, mobs.add(Mob("minecraft:armadillo", AC.NOCTURNAL))
).derive( mobs.add(Mob("minecraft:blaze", AC.ANY))
altitude = AL.LOWLANDS, seasons = SE.exclude(SE.SUMMER), scarcity = SC.UNCOMMON, mobs.add(Mob("minecraft:bogged", AC.MIDNIGHT))
).derive( mobs.add(Mob("minecraft:camel", AC.CREPUSCULAR))
altitude = AL.UPLANDS, scarcity = SC.UNUSUAL, mobs.add(Mob("minecraft:cat", AC.CREPUSCULAR))
) mobs.add(Mob("minecraft:cave_spider", AC.NOCTURNAL))
) mobs.add(Mob("minecraft:chicken", AC.DIURNAL))
) mobs.add(Mob("minecraft:cod", AC.DIURNAL))
mobs.add(Mob("minecraft:cow", AC.DIURNAL))
mobs.add( mobs.add(Mob("minecraft:creeper", AC.STORMY))
MobPlacement(Mob("black_bear", "bearminimum:black_bear"), mobs.add(Mob("minecraft:dolphin", AC.DIURNAL))
Habitat( mobs.add(Mob("minecraft:donkey", AC.DIURNAL))
altitude = AL.span(AL.LOWLANDS, AL.ALPINE), mobs.add(Mob("minecraft:drowned", AC.MIDNIGHT))
biomeFilter = BF([HE.TEMPERATE, FL.FOREST]), mobs.add(Mob("minecraft:enderman"))
seasons = SE.AUTUMN, mobs.add(Mob("minecraft:evoker"))
group = GR.merge(GR.SOLO, GR.FAMILY), mobs.add(Mob("minecraft:fox", AC.CREPUSCULAR))
scarcity = SC.UNCOMMON, mobs.add(Mob("minecraft:frog", AC.CREPUSCULAR))
).derive( mobs.add(Mob("minecraft:glow_squid", AC.CREPUSCULAR))
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.SPARSE mobs.add(Mob("minecraft:goat", AC.DIURNAL))
).derive( mobs.add(Mob("minecraft:hoglin"))
seasons = SE.WINTER, scarcity = SC.UNUSUAL mobs.add(Mob("minecraft:horse", AC.DIURNAL))
).derive( mobs.add(Mob("minecraft:husk", AC.MIDNIGHT))
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), mobs.add(Mob("minecraft:llama", AC.DIURNAL))
seasons = SE.AUTUMN, mobs.add(Mob("minecraft:magma_cube", AC.ANY))
scarcity = SC.SPARSE mobs.add(Mob("minecraft:mooshroom", AC.DIURNAL))
).derive( mobs.add(Mob("minecraft:mule", AC.DIURNAL))
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL mobs.add(Mob("minecraft:ocelot", AC.NOCTURNAL))
).derive( mobs.add(Mob("minecraft:panda", AC.CREPUSCULAR))
seasons = SE.WINTER, scarcity = SC.RARE mobs.add(Mob("minecraft:parrot", AC.DIURNAL))
) mobs.add(Mob("minecraft:pig", AC.DIURNAL))
) mobs.add(Mob("minecraft:pillager"))
) mobs.add(Mob("minecraft:polar_bear", AC.CREPUSCULAR))
mobs.add(Mob("minecraft:pufferfish", AC.DIURNAL))
mobs.add( mobs.add(Mob("minecraft:rabbit", AC.CREPUSCULAR))
MobPlacement(Mob("blaze", "minecraft:blaze"), mobs.add(Mob("minecraft:ravager"))
Habitat( mobs.add(Mob("minecraft:salmon", AC.DIURNAL))
altitude = AL.PLUTONIC, mobs.add(Mob("minecraft:sheep", AC.DIURNAL))
location = LO.CAVE, mobs.add(Mob("minecraft:skeleton"))
group = GR.SOLO, mobs.add(Mob("minecraft:slime", AC.RAINY))
scarcity = SC.UNCOMMON mobs.add(Mob("minecraft:spider", AC.NOCTURNAL))
) mobs.add(Mob("minecraft:squid", AC.CREPUSCULAR))
) mobs.add(Mob("minecraft:tropical_fish", AC.DIURNAL))
) mobs.add(Mob("minecraft:turtle", AC.NOCTURNAL))
mobs.add(Mob("minecraft:vex"))
mobs.add( mobs.add(Mob("minecraft:villager"))
MobPlacement(Mob("bogged", "minecraft:bogged")) mobs.add(Mob("minecraft:vindicator"))
) mobs.add(Mob("minecraft:wandering_trader"))
mobs.add(Mob("minecraft:warden"))
mobs.add( mobs.add(Mob("minecraft:witch"))
MobPlacement(Mob("brown_bear", "bearminimum:brown_bear"), mobs.add(Mob("minecraft:wither_skeleton"))
Habitat( mobs.add(Mob("minecraft:wither"))
altitude = AL.span(AL.LOWLANDS, AL.ALPINE), mobs.add(Mob("minecraft:wolf", AC.NOCTURNAL))
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]), mobs.add(Mob("minecraft:zoglin"))
seasons = SE.AUTUMN, mobs.add(Mob("minecraft:zombie_villager", AC.MIDNIGHT))
group = GR.SOLO, mobs.add(Mob("minecraft:zombie"))
scarcity = SC.SPARSE
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL
).derive(
seasons = SE.WINTER, scarcity = SC.RARE
)
)
)
mobs.add(
MobPlacement(Mob("bulwark", "immersiveengineering:bulwark"))
)
mobs.add(
MobPlacement(Mob("camel", "minecraft:camel", AC.CREPUSCULAR),
Habitat(
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]),
seasons = SE.DRY,
group = GR.FAMILY,
scarcity = SC.UNUSUAL,
).derive(
seasons = SE.WET, scarcity = SC.RARE
)
)
)
mobs.add(
MobPlacement(Mob("cat", "minecraft:cat"))
)
mobs.add(
MobPlacement(Mob("cave_spider", "minecraft:cave_spider"),
Habitat(
altitude = AL.span(AL.OVERBURDEN, AL.HILLS),
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
)
)
mobs.add(
MobPlacement(Mob("chameleon", "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,
).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,
)
)
)
mobs.add(
MobPlacement(Mob("chicken", "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
)
)
)
mobs.add(
MobPlacement(Mob("cod", "minecraft:cod"))
)
mobs.add(
MobPlacement(Mob("commando", "immersiveengineering:commando"))
)
mobs.add(
MobPlacement(Mob("cow", "minecraft:cow"))
)
mobs.add(
MobPlacement(Mob("crab", "crabbersdelight:crab"))
)
mobs.add(
MobPlacement(Mob("creeper", "minecraft:creeper"))
)
mobs.add(
MobPlacement(Mob("dolphin", "minecraft:dolphin"))
)
mobs.add(
MobPlacement(Mob("donkey", "minecraft:donkey"))
)
mobs.add(
MobPlacement(Mob("drowned", "minecraft:drowned"))
)
mobs.add(
MobPlacement(Mob("enderman", "minecraft:enderman"))
)
mobs.add(
MobPlacement(Mob("evoker", "minecraft:evoker"))
)
mobs.add(
MobPlacement(Mob("fox", "minecraft:fox"))
)
mobs.add(
MobPlacement(Mob("frog", "minecraft:frog"))
)
mobs.add(
MobPlacement(Mob("fusilier", "immersiveengineering:fusilier"))
)
mobs.add(
MobPlacement(Mob("glow_squid", "minecraft:glow_squid"))
)
mobs.add(
MobPlacement(Mob("goat", "minecraft:goat"))
)
mobs.add(
MobPlacement(Mob("hoglin", "minecraft:hoglin"))
)
mobs.add(
MobPlacement(Mob("horse", "minecraft:horse"))
)
mobs.add(
MobPlacement(Mob("husk", "minecraft:husk"))
)
mobs.add(
MobPlacement(Mob("llama", "minecraft:llama"))
)
mobs.add(
MobPlacement(Mob("magma_cube", "minecraft:magma_cube"))
)
mobs.add(
MobPlacement(Mob("mooshroom", "minecraft:mooshroom"))
)
mobs.add(
MobPlacement(Mob("mule", "minecraft:mule"))
)
mobs.add(
MobPlacement(Mob("ocelot", "minecraft:ocelot"))
)
mobs.add(
MobPlacement(Mob("panda", "minecraft:panda"))
)
mobs.add(
MobPlacement(Mob("parrot", "minecraft:parrot"))
)
mobs.add(
MobPlacement(Mob("pig", "minecraft:pig"))
)
mobs.add(
MobPlacement(Mob("pillager", "minecraft:pillager"))
)
mobs.add(
MobPlacement(Mob("polar_bear", "minecraft:polar_bear"))
)
mobs.add(
MobPlacement(Mob("pufferfish", "minecraft:pufferfish"))
)
mobs.add(
MobPlacement(Mob("rabbit", "minecraft:rabbit"))
)
mobs.add(
MobPlacement(Mob("raccoon", "animalplus:raccoon"))
)
mobs.add(
MobPlacement(Mob("ravager", "minecraft:ravager"))
)
mobs.add(
MobPlacement(Mob("red_panda", "animalplus:red_panda"))
)
mobs.add(
MobPlacement(Mob("salmon", "minecraft:salmon"))
)
mobs.add(
MobPlacement(Mob("sheep", "minecraft:sheep"))
)
mobs.add(
MobPlacement(Mob("skeleton", "minecraft:skeleton"))
)
mobs.add(
MobPlacement(Mob("slime", "minecraft:slime"))
)
mobs.add(
MobPlacement(Mob("spider", "minecraft:spider"))
)
mobs.add(
MobPlacement(Mob("squid", "minecraft:squid"))
)
mobs.add(
MobPlacement(Mob("tropical_fish", "minecraft:tropical_fish"))
)
mobs.add(
MobPlacement(Mob("turtle", "minecraft:turtle"))
)
mobs.add(
MobPlacement(Mob("vex", "minecraft:vex"))
)
mobs.add(
MobPlacement(Mob("villager", "minecraft:villager"))
)
mobs.add(
MobPlacement(Mob("vindicator", "minecraft:vindicator"))
)
mobs.add(
MobPlacement(Mob("wandering_trader", "minecraft:wandering_trader"))
)
mobs.add(
MobPlacement(Mob("warden", "minecraft:warden"))
)
mobs.add(
MobPlacement(Mob("witch", "minecraft:witch"))
)
mobs.add(
MobPlacement(Mob("wither_skeleton", "minecraft:wither_skeleton"))
)
mobs.add(
MobPlacement(Mob("wither", "minecraft:wither"))
)
mobs.add(
MobPlacement(Mob("wolf", "minecraft:wolf"))
)
mobs.add(
MobPlacement(Mob("zoglin", "minecraft:zoglin"))
)
mobs.add(
MobPlacement(Mob("zombie_villager", "minecraft:zombie_villager"))
)
mobs.add(
MobPlacement(Mob("zombie", "minecraft:zombie"))
)
@@ -0,0 +1,411 @@
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
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
# Constants ########################################################################################
def addMobs(pack:ModPack):
mobs = pack.world.mobs
spawns = pack.world.mobSpawns
spawns.add(
MobSpawn(mobs["animalplus:raccoon"])
)
spawns.add(
MobSpawn(mobs["animalplus:red_panda"])
)
spawns.add(
MobSpawn(mobs["bearminimum:black_bear"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.ALPINE),
biomeFilter = BF([HE.TEMPERATE, FL.FOREST]),
seasons = SE.AUTUMN,
group = GR.merge(GR.SOLO, GR.FAMILY),
scarcity = SC.UNCOMMON,
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.SPARSE
).derive(
seasons = SE.WINTER, scarcity = SC.UNUSUAL
).derive(
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]),
seasons = SE.AUTUMN,
scarcity = SC.SPARSE
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL
).derive(
seasons = SE.WINTER, scarcity = SC.RARE
)
)
)
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
).derive(
altitude = AL.UPLANDS, scarcity = SC.SPARSE,
).derive(
altitude = AL.LOWLANDS, seasons = SE.exclude(SE.SUMMER), scarcity = SC.UNCOMMON,
).derive(
altitude = AL.UPLANDS, scarcity = SC.UNUSUAL,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:blaze"],
Habitat(
altitude = AL.PLUTONIC,
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),
biomeFilter = BF([HE.BOREAL, (FL.CANOPY, FL.FOREST)]),
seasons = SE.AUTUMN,
group = GR.SOLO,
scarcity = SC.SPARSE
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL
).derive(
seasons = SE.WINTER, scarcity = SC.RARE
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:camel"],
Habitat(
altitude = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]),
seasons = SE.DRY,
group = GR.FAMILY,
scarcity = SC.UNUSUAL,
).derive(
seasons = SE.WET, scarcity = SC.RARE
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:cave_spider"],
Habitat(
altitude = AL.span(AL.OVERBURDEN, AL.HILLS),
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
)
)
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,
).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,
)
)
)
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,
).derive(
seasons = SE.exclude(SE.SUMMER),
scarcity = SC.UNCOMMON
)
)
)
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,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:cow"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilter = BF(
[
HE.within(HE.SUBTROPICAL, HE.BOREAL),
[HU.DAMP, HU.DRY],
FL.FIELD,
], [
SO.FUNGAL
]
),
seasons = [SE.SPRING, SE.SUMMER],
group = GR.HERD,
scarcity = SC.COMMON,
).derive(
altitude = AL.LOWLANDS,
seasons = [SE.AUTUMN, SE.WINTER],
groups = GR.TROUP,
scarcity = SC.SPARSE,
)
)
)
spawns.add(
MobSpawn(mobs["crabbersdelight:crab"],
Habitat(
altitude = AL.DUNES,
biomeFilter = BF([WA.COAST, [HE.TROPICAL, HE.SUBTROPICAL]]),
seasons = SE.ALL,
group = GR.SOLO,
scarcity = SC.COMMON,
).derive(
biomeFilter = BF([WA.COAST, [HE.TEMPERATE, HE.BOREAL]]),
scarcity = SC.UNCOMMON,
)
)
)
spawns.add(
MobSpawn(mobs["minecraft:dolphin"],
Habitat(
altitude = AL.span(AL.SURFACE, AL.DEEPS),
biomeFilter = BF([WA.OCEAN, [HE.SUBTROPICAL, HE.TEMPERATE]]),
location = LO.WATER,
seasons = SE.SUMMER,
group = GR.FAMILY,
scarcity = SC.UNCOMMON,
).derive(
seasons = SE.exclude(SE.SUMMER),
scarcity = SC.SPARSE,
)
)
)
spawns.add(MobSpawn(mobs["minecraft:donkey"],
Habitat(
altitude = AL.span(AL.UPLANDS, AL.HILLS),
biomeFilter = BF([HE.SUBTROPICAL, HU.DRY, FL.FIELD]),
seasons = [SE.SUMMER, SE.AUTUMN],
group = GR.FAMILY,
scarcity = SC.UNCOMMON,
).derive(
seasons = [SE.WINTER, SE.SPRING],
scarcity = SC.SPARSE,
)
))
spawns.add(MobSpawn(mobs["minecraft:fox"],
Habitat(
altitude = AL.span(AL.LOWLANDS, AL.HILLS),
biomeFilter = BF([HE.within(HE.TEMPERATE, HE.FROZEN), FL.FOREST]),
seasons = [SE.SPRING],
group = GR.FAMILY,
scarcity = SC.UNCOMMON,
).derive(
seasons = SE.exclude(SE.SPRING),
group = GR.SOLO,
scarcity = SC.SPARSE,
)
))
spawns.add(
MobSpawn(mobs["minecraft:frog"])
)
spawns.add(
MobSpawn(mobs["minecraft:glow_squid"])
)
spawns.add(
MobSpawn(mobs["minecraft:goat"])
)
spawns.add(
MobSpawn(mobs["minecraft:horse"])
)
spawns.add(
MobSpawn(mobs["minecraft:husk"])
)
spawns.add(
MobSpawn(mobs["minecraft:llama"])
)
spawns.add(
MobSpawn(mobs["minecraft:magma_cube"])
)
spawns.add(
MobSpawn(mobs["minecraft:mooshroom"])
)
spawns.add(
MobSpawn(mobs["minecraft:mule"])
)
spawns.add(
MobSpawn(mobs["minecraft:ocelot"])
)
spawns.add(
MobSpawn(mobs["minecraft:panda"])
)
spawns.add(
MobSpawn(mobs["minecraft:parrot"])
)
spawns.add(
MobSpawn(mobs["minecraft:pig"])
)
spawns.add(
MobSpawn(mobs["minecraft:polar_bear"])
)
spawns.add(
MobSpawn(mobs["minecraft:pufferfish"])
)
spawns.add(
MobSpawn(mobs["minecraft:rabbit"])
)
spawns.add(
MobSpawn(mobs["minecraft:salmon"])
)
spawns.add(
MobSpawn(mobs["minecraft:sheep"])
)
spawns.add(
MobSpawn(mobs["minecraft:skeleton"])
)
spawns.add(
MobSpawn(mobs["minecraft:slime"])
)
spawns.add(
MobSpawn(mobs["minecraft:spider"])
)
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"])
)
@@ -0,0 +1,7 @@
import mcpacker.pack.mysteriousisland.addmobspawns
# Class ############################################################################################
def test_syntax():
pass
+2 -2
View File
@@ -27,7 +27,7 @@ class Runner:
def run(self, argv:list[str]): def run(self, argv:list[str]):
if len(sys.argv) < 2: if len(sys.argv) < 2:
abort("Please provide a command name") self.abort("Please provide a command name")
commandName = "_command_" + argv[1] commandName = "_command_" + argv[1]
for name, doCommand in inspect.getmembers(self): for name, doCommand in inspect.getmembers(self):
@@ -35,7 +35,7 @@ class Runner:
doCommand(*argv[2:]) doCommand(*argv[2:])
sys.exit(0) sys.exit(0)
abort("No command named: " + argv[1]) self.abort("No command named: " + argv[1])
# Commands ################################################################# # Commands #################################################################
+3
View File
@@ -1,8 +1,11 @@
exceptiongroup==1.3.0 exceptiongroup==1.3.0
iniconfig==2.1.0 iniconfig==2.1.0
jedi==0.19.2 jedi==0.19.2
mypy==1.18.2
mypy_extensions==1.1.0
packaging==25.0 packaging==25.0
parso==0.8.4 parso==0.8.4
pathspec==0.12.1
pluggy==1.6.0 pluggy==1.6.0
Pygments==2.19.2 Pygments==2.19.2
pytest==8.4.2 pytest==8.4.2