Checkpoint initial implementation

This commit is contained in:
Andrew Miner
2025-10-06 17:41:18 -06:00
parent 773e0a3d85
commit a8b6e6b15e
106 changed files with 3012 additions and 0 deletions
View File
View File
+74
View File
@@ -0,0 +1,74 @@
# Class ############################################################################################
class Altitude:
"""
A range of world heights from a bottom to a top.
"""
def __init__(self, name:str, bottom:int, top:int):
self.name = name
self.bottom = bottom
self.top = top
def __eq__(self, other) -> bool:
if type(self) != type(other): return False
if self.bottom != other.bottom: return False
if self.top != other.top: return False
return True
def __hash__(self) -> int:
return hash((self.bottom, self.top))
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"{self.name} <{self.bottom} to {self.top}>"
# Constants ########################################################################################
# Aboveground
SKY = Altitude("sky", 284, 316)
SUMMIT = Altitude("summit", 252, 284)
PEAKS = Altitude("peaks", 222, 252)
CRAGS = Altitude("crags", 190, 222)
ALPINE = Altitude("alpine", 156, 190)
HILLS = Altitude("hills", 124, 156)
UPLANDS = Altitude("uplands", 92, 124)
LOWLANDS = Altitude("lowlands", 70, 92)
DUNES = Altitude("dunes", 62, 70)
# Transition
EVAPORATES = Altitude("evaporates", 60, 64)
ANYWHERE = Altitude("anywhere", -64, 320)
# Underground
SOIL = Altitude("soil", 48, 62)
SUBSTRATE = Altitude("substrate", 32, 48)
OVERBURDEN = Altitude("overburden", 0, 32)
CRUST = Altitude("crust", -32, 32)
MANTLE = Altitude("mantle", -54, -32)
PLUTONIC = Altitude("plutonic", -64, -54)
# Underwater
SURFACE = Altitude("surface", 58, 62)
SHALLOWS = Altitude("shallows", 46, 58)
DEEPS = Altitude("deeps", 0, 46)
ABYSS = Altitude("abyss", -32, 0)
# Groups
OVERGROUND = (DUNES, LOWLANDS, UPLANDS, HILLS, ALPINE, CRAGS, PEAKS, SUMMIT, SKY)
UNDERGROUND = (SOIL, SUBSTRATE, OVERBURDEN, CRUST, MANTLE, PLUTONIC)
UNDERWATER = (SURFACE, SHALLOWS, DEEPS, ABYSS)
# Helper Functions #################################################################################
def span(*altitudes):
if not altitudes: return ANYWHERE
result = Altitude("", ANYWHERE.top, ANYWHERE.bottom)
for altitude in altitudes:
result.bottom = min(result.bottom, altitude.bottom)
result.top = max(result.top, altitude.top)
return result
+18
View File
@@ -0,0 +1,18 @@
from pytest import fixture
import tungston.core.altitude as A
# Fixtures #########################################################################################
@fixture(name="merged")
def mergeRange():
yield A.span(A.UPLANDS, A.LOWLANDS)
# Tests ############################################################################################
def test_span(merged):
assert merged.bottom == A.LOWLANDS.bottom
assert merged.top == A.UPLANDS.top
View File
+70
View File
@@ -0,0 +1,70 @@
from tungston.core.ecology.biometrait import BiomeTrait
from tungston.core.ecology.flora import Flora
from tungston.core.ecology.geology import Geology
from tungston.core.ecology.heat import Heat
from tungston.core.ecology.humidity import Humidity
from tungston.core.ecology.soil import Soil
from tungston.core.ecology.water import Water
####################################################################################################
class Biome(object):
"""
A region of the world defined by a unique combination of geology, topography, and ecology.
"""
def __init__(
self,
city:str,
gameId:str,
flora:Flora,
geology:Geology,
heat:Heat,
humidity:Humidity,
soil:Soil,
water:Water,
):
self.city = city
self.gameId = gameId
self.flora = flora
self.geology = geology
self.heat = heat
self.humidity = humidity
self.soil = soil
self.water = water
def __eq__(self, other) -> bool:
if type(self) != type(other): return False
if self.biomeId != other.biomeId: return False
if self.city != other.city: return False
return True
def __hash__(self) -> int:
return hash((self.biomeId, self.city))
def __str__(self) -> str:
return f"{self.city}<{self.gameId}>"
def __repr__(self) -> str:
return "".join([str(p) for p in [
str(self), "{",
repr(self.flora), ", ",
repr(self.geology), ", ",
repr(self.heat), ", ",
repr(self.humidity), ", ",
repr(self.soil), ", ",
repr(self.water),
"}"
]])
def traits(self) -> set[BiomeTrait]:
return set([
self.flora,
self.geology,
self.heat,
self.humidity,
self.soil,
self.water,
])
+25
View File
@@ -0,0 +1,25 @@
from pytest import fixture
from tungston.core.ecology.biome import Biome
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="desert")
def createDesert():
return Biome(
"phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
)
# Tests ############################################################################################
def test_createBiome(desert):
assert desert.city == "phoenix"
assert desert.soil == S.SANDY
+25
View File
@@ -0,0 +1,25 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomefilter import BiomeFilter
# Classes ##########################################################################################
class BiomeCatalog:
"""
A comprehensive list of all available biomes in the modpack.
"""
def __init__(self, biomes):
self.biomes = sorted(biomes, key=lambda b: b.city)
def all(self) -> list[Biome]:
return list(self.biomes)
def matching(self, biomeFilter:BiomeFilter) -> list[Biome]:
result = []
for biome in self.biomes:
if biomeFilter.accepts(biome):
result.append(biome)
return result
@@ -0,0 +1,46 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomecatalog import BiomeCatalog
from tungston.core.ecology.biomefilter import BiomeFilter
from pytest import fixture
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="jungles")
def createJungleFilter():
yield BiomeFilter([U.WET, E.TROPICAL, F.within(F.CANOPY, F.CLEARING)])
@fixture(name="catalog")
def createCatalog():
yield BiomeCatalog([
Biome("dallas", "minecraft:savanna",
F.FIELD, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("kansascity", "minecraft:plains",
F.FIELD, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("mobile", "minecraft:swamp",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.PEATY, W.SWAMP
),
Biome("phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("portland", "minecraft:forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("singapore", "minecraft:jungle",
F.CANOPY, G.SEDIMENTARY, E.TROPICAL, U.WET, S.ACIDIC, W.INLAND
),
])
# Tests ############################################################################################
def test_findJungles(catalog, jungles):
assert [b.city for b in catalog.matching(jungles)] == ["singapore"]
+57
View File
@@ -0,0 +1,57 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class BiomeFilter:
"""
A description of which biomes may be considered for a given purpose.
This class works by allowing *both* allowed and prohibited traits.
The list of allowed traits may contain either individual trait objects, or a list of such
objects. When an individual trait is given, only biomes with that exact trait are permitted.
When a list of traits is given, biomes containing any of the listed traits are permitted. To
put it another way, each individual item in the required list is an "OR" filter, and the results
of the entire list are "AND"ed together.
The list of prohibited traits only permits individual traits, but multiple traits of the same
sort may be given.
The filter only accepts biomes which pass *both* lists. That is, it must possess *all* the
required traits while simultaneously not possessing *any* of the prohibited ones.
"""
def __init__(
self,
required:list[BiomeTrait|list[BiomeTrait]]=None,
prohibited:list[BiomeTrait]=None,
):
self.required = required or []
self.prohibited = prohibited or []
def __repr__(self) -> str:
return f"BiomeFilter([{repr(self.required)}], [{repr(self.prohibited)}])"
def accepts(self, biome: Biome) -> bool:
biomeTraits = biome.traits()
for condition in self.required:
if isinstance(condition, BiomeTrait):
trait = condition
if trait not in biomeTraits: return False
else:
traitOptions = condition
foundMatch = False
for trait in traitOptions:
if trait in biomeTraits:
foundMatch = True
break
if not foundMatch: return False
for prohibitedTrait in self.prohibited:
if prohibitedTrait in biomeTraits: return False
return True
+61
View File
@@ -0,0 +1,61 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomefilter import BiomeFilter
from pytest import fixture
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Fixtures #########################################################################################
@fixture(name="barren")
def createBarrenFilter():
yield BiomeFilter([F.BARREN])
@fixture(name="barrenNotSandy")
def createBarrenNotSandFilter():
yield BiomeFilter([F.BARREN], [S.SANDY])
@fixture(name="desert")
def createDesertBiome():
yield Biome(
"phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
)
@fixture(name="fertile")
def createFertileFilter():
yield BiomeFilter([(S.LOAMY, S.PEATY)])
@fixture(name="forest")
def createForestBiome():
yield Biome(
"portland", "minecraft:forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
)
@fixture(name="notDry")
def createNotDryFilter():
yield BiomeFilter([], [U.DRY])
# Tests ############################################################################################
def test_prohibitsSingleTrait(notDry, desert, forest):
assert notDry.accepts(forest)
assert not notDry.accepts(desert)
def test_requireSingleTrait(barren, desert, forest):
assert barren.accepts(desert)
assert not barren.accepts(forest)
def test_requireOptions(fertile, desert, forest):
assert fertile.accepts(forest)
assert not fertile.accepts(desert)
def test_vetoed(barrenNotSandy, desert):
assert not barrenNotSandy.accepts(desert)
+49
View File
@@ -0,0 +1,49 @@
# Class ############################################################################################
class BiomeTrait:
"""
Any of the many characteristics which uniquely define a biome.
"""
def __init__(self, name:str):
self.name = name
def __eq__(self, other) -> bool:
if type(self).__name__ != type(other).__name__: return False
if self.name != other.name: return False
return True
def __hash__(self) -> int:
return hash((type(self).__name__, self.name))
def __str__(self):
return self.name
def __repr__(self) -> str:
return f"{type(self).__name__}<{self.name}>"
# Helper Functions #################################################################################
def within(allTraits:list[BiomeTrait], start:BiomeTrait, end:BiomeTrait) -> list[BiomeTrait]:
if not allTraits: return []
start = start if start else allTraits[0]
end = end if end else allTraits[-1]
minIndex = 0
maxIndex = len(allTraits) - 1
for index, trait in enumerate(allTraits):
if trait == start:
minIndex = index
elif trait == end:
maxIndex = index
if minIndex > maxIndex:
minIndex, maxIndex = maxIndex, minIndex
result = []
for index in range(minIndex, maxIndex+1):
result.append(allTraits[index])
return result
+58
View File
@@ -0,0 +1,58 @@
from tungston.core.ecology.biometrait import BiomeTrait
from pytest import fixture
import tungston.core.ecology.biometrait as biomeTrait
# Fixtures #########################################################################################
@fixture(name="blue")
def defineBlue():
yield BiomeTrait("blue")
@fixture(name="green")
def defineGreen():
yield BiomeTrait("green")
@fixture(name="yellow")
def defineYellow():
yield BiomeTrait("yellow")
@fixture(name="orange")
def defineOrange():
yield BiomeTrait("orange")
@fixture(name="red")
def defineRed():
yield BiomeTrait("red")
@fixture(name="traitMap")
def createTraitMap(green, blue):
yield {
green: "emerald",
blue: "sapphire"
}
@fixture(name="traitList")
def createTraitList(green, blue, yellow, orange, red):
yield [blue, green, yellow, orange, red]
# Tests ############################################################################################
def test_eq(green, blue):
assert green == BiomeTrait("green")
assert green != blue
def test_hash(green, blue, traitMap):
assert traitMap[green] == "emerald"
assert traitMap[blue] == "sapphire"
def test_repr(green):
assert repr(green) == "BiomeTrait<green>"
def test_str(green):
assert str(green) == "green"
def test_within(traitList, green, yellow, orange):
assert biomeTrait.within(traitList, green, orange) == [green, yellow, orange]
+28
View File
@@ -0,0 +1,28 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Flora(BiomeTrait):
"""
Describes how densely the foiliage covers a biome.
"""
pass
# Constants ########################################################################################
CANOPY = Flora("canopy")
FOREST = Flora("forest")
CLEARING = Flora("clearing")
FIELD = Flora("field")
BARREN = Flora("barren")
ALL = [CANOPY, FOREST, CLEARING, FIELD, BARREN]
# Helpers ##########################################################################################
def within(start:Flora, end:Flora) -> list[Flora]:
return biomeTrait.within(ALL, start, end)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.flora as flora
# Tests ############################################################################################
def test_within():
assert flora.within(flora.FOREST, flora.FIELD) == [flora.FOREST, flora.CLEARING, flora.FIELD]
+19
View File
@@ -0,0 +1,19 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Geology(BiomeTrait):
"""
The natural of the rock strata in a biome.
"""
pass
# Constants ########################################################################################
IGNEOUS = Geology("igneous")
METAMORPHIC = Geology("metamorphic")
SEDIMENTARY = Geology("sedimentary")
ALL = [IGNEOUS, METAMORPHIC, SEDIMENTARY]
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.geology as geology
# Tests ############################################################################################
def test_syntax():
pass
+33
View File
@@ -0,0 +1,33 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Heat(BiomeTrait):
"""
The general range of ambient temperatures in a biome (in °F).
"""
def __init__(self, name, low:int, high:int):
super().__init__(name)
self.low = low
self.high = high
# Constants ########################################################################################
TROPICAL = Heat("tropical", 75, 88)
SUBTROPICAL = Heat("subtropical", 58, 82)
TEMPERATE = Heat("temperate", 36, 66)
BOREAL = Heat("boreal", 10, 54)
FROZEN = Heat("frozen", -20, 32)
ALL = [TROPICAL, SUBTROPICAL, TEMPERATE, BOREAL, FROZEN]
# Helpers ##########################################################################################
def within(start:Heat, end:Heat) -> list[Heat]:
return biomeTrait.within(ALL, start, end)
+13
View File
@@ -0,0 +1,13 @@
from pytest import fixture
import tungston.core.ecology.heat as heat
# Tests ############################################################################################
def test_within():
assert (
heat.within(heat.SUBTROPICAL, heat.BOREAL)
==
[heat.SUBTROPICAL, heat.TEMPERATE, heat.BOREAL]
)
+26
View File
@@ -0,0 +1,26 @@
from tungston.core.ecology.biometrait import BiomeTrait
import tungston.core.ecology.biometrait as biomeTrait
# Class ############################################################################################
class Humidity(BiomeTrait):
"""
The general level of humidity present in the air.
"""
pass
# Constants ########################################################################################
WET = Humidity("wet")
DAMP = Humidity("damp")
DRY = Humidity("dry")
ALL = [WET, DAMP, DRY]
# Helpers ##########################################################################################
def within(start:Humidity, end:Humidity) -> list[Humidity]:
return biomeTrait.within(ALL, start, end)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.humidity as humidity
# Tests ############################################################################################
def test_within():
assert humidity.within(humidity.DAMP, humidity.DRY) == [humidity.DAMP, humidity.DRY]
+23
View File
@@ -0,0 +1,23 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Soil(BiomeTrait):
"""
The nature of the soil within a certain region.
"""
pass
# Constants ########################################################################################
ACIDIC = Soil("acidic")
CLAYEY = Soil("clayey")
FUNGAL = Soil("fungal")
LOAMY = Soil("loamy")
PEATY = Soil("peaty")
ROCKY = Soil("rocky")
SANDY = Soil("sandy")
ALL = [ACIDIC, CLAYEY, FUNGAL, LOAMY, PEATY, ROCKY, SANDY]
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.soil as soil
# Tests ############################################################################################
def test_syntax():
pass
+21
View File
@@ -0,0 +1,21 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Water(BiomeTrait):
"""
The kind of large body of water which dominates a biome.
"""
pass
# Constants ########################################################################################
RIVER = Water("river")
SWAMP = Water("swamp")
OCEAN = Water("ocean")
COAST = Water("coast")
INLAND = Water("inland")
ALL = (RIVER, SWAMP, OCEAN, COAST, INLAND)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.ecology.water as water
# Tests ############################################################################################
def test_syntax():
pass
View File
+30
View File
@@ -0,0 +1,30 @@
# Class ############################################################################################
class Active:
"""
The time of day when a creature is normally most active.
"""
def __init__(self, name: str, start:int, end:int):
self.name = name
self.start = start
self.end = end
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Active<{self.name}>{{start:{self.start}, end:{self.end}}}"
# Constants ########################################################################################
DAY = Active("day", 0, 12000)
NIGHT = Active("night", 13000, 23000)
SUNRISE = Active("sunrise", 23000, 24000)
SUNSET = Active("sunset", 12000, 13000)
ANY = (SUNRISE, DAY, SUNSET, NIGHT)
DIURNAL = (DAY)
NOCTURNAL = (NIGHT)
CREPUSCULAR = (SUNRISE, SUNSET)
+9
View File
@@ -0,0 +1,9 @@
from pytest import fixture
import tungston.core.fauna.active as active
# Tests ############################################################################################
def test_syntax():
pass
+50
View File
@@ -0,0 +1,50 @@
# Class ############################################################################################
class Group:
"""
How many individuals are commonly present when encountering a creature.
"""
def __init__(self, name, smallest, largest):
self.name = name
self.smallest = smallest
self.largest = largest
def __eq__(self, other) -> bool:
if type(other) != type(self): return False
if other.largest != self.largest: return False
if other.smallest != self.smallest: return False
return True
def __hash__(self) -> int:
return hash((self.smallest, self.largest))
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return str(self) + f"<{self.smallest} to {self.largest}>"
# Constants ########################################################################################
SOLO = Group("solo", 1, 1)
PAIR = Group("pair", 2, 2)
FAMILY = Group("family", 2, 4)
TROUP = Group("troup", 3, 6)
HERD = Group("herd", 4, 8)
ALL = [SOLO, PAIR, FAMILY, TROUP, HERD]
# Helper Functions #################################################################################
def merge(*groups):
if not groups: return SOLO
result = Group(f"", HERD.largest, SOLO.smallest)
for group in groups:
result.smallest = min(result.smallest, group.smallest)
result.largest = max(result.largest, group.largest)
return result
+17
View File
@@ -0,0 +1,17 @@
from pytest import fixture
import tungston.core.fauna.group as group
# Fixtures #########################################################################################
@fixture(name="atomicFamily")
def createAtomicFamily():
yield group.merge(group.PAIR, group.FAMILY)
# Tests ############################################################################################
def test_merge(atomicFamily):
assert atomicFamily.smallest == 2
assert atomicFamily.largest == 4
+27
View File
@@ -0,0 +1,27 @@
from tungston.core.ecology.biometrait import BiomeTrait
# Class ############################################################################################
class Location:
"""
Where a creature is most likely to be encountered.
"""
def __init__(self, name):
self.name = name
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Location<{self.name}>"
# Constants ########################################################################################
OUTSIDE = Location("outside")
CAVE = Location("cave")
WATER = Location("water")
ALL = [OUTSIDE, CAVE, WATER]
+36
View File
@@ -0,0 +1,36 @@
from tungston.core.fauna.active import Active
import tungston.core.fauna.active as AC
# Class ############################################################################################
class Mob:
"""
A creature which may appear in the game world.
"""
def __init__(self, name:str, gameId:str, active:tuple[Active]=AC.DIURNAL):
self.name = name
self.gameId = gameId
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:
if type(self) != type(other): return False
if self.gameId != other.gameId: return False
return True
def __hash__(self) -> int:
return hash(self.gameId)
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"{self.name}<{self.gameId}>{{active:{self.active}}}"
+39
View File
@@ -0,0 +1,39 @@
from tungston.core.fauna.mob import Mob
from pytest import fixture
import tungston.core.fauna.active as AC
# Fixtures #########################################################################################
@fixture(name="squid")
def createSquid():
yield Mob("squid", "minecraft:squid", AC.ANY)
@fixture(name="cow")
def createCow():
yield Mob("cow", "minecraft:cow", AC.DIURNAL)
@fixture(name="mobMap")
def createMobMap(cow, squid):
yield {
cow: "beef",
squid: "calamari"
}
# Tests ############################################################################################
def test_eq(squid):
assert squid == Mob("squid", "minecraft:squid")
assert squid != Mob("squid", "animalsplus:squid")
def test_hash(cow, squid, mobMap):
assert mobMap[cow] == "beef"
assert mobMap[squid] == "calamari"
def test_str(squid):
assert str(squid) == "squid"
def test_repr(cow):
assert repr(cow) == "cow<minecraft:cow>{active:(Active<day>{start:0, end:12000},)}"
+16
View File
@@ -0,0 +1,16 @@
from tungston.core.fauna.mob import Mob
# Class ############################################################################################
class MobCatalog:
def __init__(self, mobs):
self.mobs = mobs
def findByName(self, name):
for mob in self.mobs:
if mob.name == name:
return mob
return None
+15
View File
@@ -0,0 +1,15 @@
from tungston.core.habitat import Habitat
from tungston.core.fauna.mob import Mob
from tungston.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
+43
View File
@@ -0,0 +1,43 @@
from pytest import fixture
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.fauna.mob import Mob
from tungston.core.fauna.mobplacement import MobPlacement
from tungston.core.habitat import Habitat
import tungston.core.ecology.flora as F
import tungston.core.ecology.heat as E
# Fixtures #########################################################################################
@fixture(name="cow")
def createCow():
yield Mob("cow", "minecraft:cow")
@fixture(name="fields")
def createFieldsHabitat():
yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE]))
@fixture(name="placement")
def createMobPlacement(cow, fields):
yield MobPlacement(cow, fields)
# Tests ############################################################################################
def test_cowsInFields(placement):
assert str(placement) == (
"Placement{" +
"habitats: [" +
"Habitat{" +
"altitude: [anywhere <-64 to 320>], " +
"biomeFilter: BiomeFilter([[Flora<field>, Heat<temperate>]], [[]]), " +
"seasons: [Season<spring>, Season<summer>, Season<autumn>, Season<winter>], " +
"group: solo<1 to 1>, " +
"location: Location<outside>, " +
"scarcity: Scarcity<sparse>" +
"}" +
"]" +
"}"
)
View File
+33
View File
@@ -0,0 +1,33 @@
import math
# Class ############################################################################################
class Bulk:
def __init__(self, name:str, smallest:int, largest:int):
self.name = name
self.smallest = smallest
self.largest = largest
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Bulk<{self.name}>{{smallest: {self.smallest}, largest: {self.largest}}}"
def scale(self, factor) -> "Bulk":
return Bulk(
self.name,
math.floor(self.smallest * factor),
math.floor(self.largest * factor)
)
# Constants ########################################################################################
SMALL = Bulk("tiny", 250, 500)
MEDIUM = Bulk("small", 500, 1000)
LARGE = Bulk("small", 1000, 2000)
ALL = [SMALL, MEDIUM, LARGE]
+20
View File
@@ -0,0 +1,20 @@
from pytest import fixture
from tungston.core.geology.bulk import Bulk
# Fixture ##########################################################################################
@fixture(name="bulk")
def createBulk():
return Bulk("chunk", 64, 128)
@fixture(name="scaledBulk")
def scaleBulk(bulk):
yield bulk.scale(2.0)
# Fixture ##########################################################################################
def test_repr(bulk, scaledBulk):
assert repr(bulk) == "Bulk<chunk>{smallest: 64, largest: 128}"
assert repr(scaledBulk) == "Bulk<chunk>{smallest: 128, largest: 256}"
+22
View File
@@ -0,0 +1,22 @@
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.geology.bulk import Bulk
from tungston.core.geology.mineral import Mineral
from tungston.core.scarcity import Scarcity
import tungston.core.scarcity as scarcity
# Class ############################################################################################
class Deposit:
def __init__(
self,
name:str,
scarcity:Scarcity=scarcity.SPARSE,
biomeFilter:BiomeFilter|None=None,
):
self.name = name
self.biomeFilter = biomeFilter or BiomeFilter()
self.scarcity = scarcity
@@ -0,0 +1,43 @@
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.geology.bulk import Bulk
from tungston.core.geology.deposit import Deposit
from tungston.core.geology.inclusion import Inclusion
from tungston.core.geology.proportion import Proportion
from tungston.core.scarcity import Scarcity
import tungston.core.geology.bulk as BU
import tungston.core.geology.proportion as PR
import tungston.core.scarcity as SC
# Class ############################################################################################
class MetalDeposit(Deposit):
def __init__(
self,
name:str,
inclusions:tuple[Inclusion],
bulk:Bulk=BU.MEDIUM,
proportion:Proportion=PR.BODY,
biomeFilter:BiomeFilter=None,
scarcity:Scarcity=SC.SPARSE,
):
super().__init__(name, scarcity, biomeFilter)
self.inclusions = inclusions
self.bulk = bulk
self.proportion = proportion
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return "".join([str(p) for p in [
"MetalDeposit<", self.name, ">{",
"scarcity: ", repr(self.scarcity), ", ",
"biomeFilter: ", self.biomeFilter, ", ",
"inclusions: [", ", ".join([repr(m) for m in self.inclusions]), "], ",
"bulk: ", repr(self.bulk), ", ",
"proportion: ", repr(self.proportion),
"}"
]])
@@ -0,0 +1,55 @@
from pytest import fixture
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.geology.deposit.metaldeposit import MetalDeposit
from tungston.core.geology.inclusion import Inclusion
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.replacement import Replacement
import tungston.core.ecology.flora as FL
import tungston.core.geology.bulk as BU
import tungston.core.geology.proportion as PR
import tungston.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 = "bifiron",
biomeFilter = BiomeFilter([FL.FOREST]),
bulk = BU.LARGE,
inclusions = [Inclusion(iron, 60), Inclusion(quartz, 40)],
proportion = PR.LENS,
scarcity = SC.COMMON,
)
# Tests ############################################################################################
def test_repr(bifIron):
assert repr(bifIron) == (
"MetalDeposit<bifiron>{" +
"scarcity: Scarcity<common>, " +
"biomeFilter: BiomeFilter([[Flora<forest>]], [[]]), " +
"inclusions: [" +
"Inclusion{mineral: iron, weight: 60}, " +
"Inclusion{mineral: quartz, weight: 40}" +
"], " +
"bulk: Bulk<small>{smallest: 1000, largest: 2000}, " +
"proportion: Proportion<lens>{ratio: 0.4}" +
"}"
)
+27
View File
@@ -0,0 +1,27 @@
from tungston.core.geology.mineralcatalog import MineralCatalog
from tungston.core.geology.deposit import Deposit
from typing import Iterator
# Class ############################################################################################
class DepositCatalog:
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)
@@ -0,0 +1,53 @@
from pytest import fixture
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.geology.deposit import Deposit
from tungston.core.geology.deposit.metaldeposit import MetalDeposit
from tungston.core.geology.depositcatalog import DepositCatalog
from tungston.core.geology.inclusion import Inclusion
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.replacement import Replacement
import tungston.core.ecology.flora as FL
import tungston.core.geology.bulk as BU
import tungston.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 ############################################################################################
def test_all(catalog):
assert [m.name for m in catalog.all()] == ["bif_iron"]
def test_get(catalog):
assert catalog.get("bif_iron").name == "bif_iron"
+24
View File
@@ -0,0 +1,24 @@
from tungston.core.geology.mineral import Mineral
# Class ############################################################################################
class Inclusion:
def __init__(self, mineral:Mineral, weight:int=100):
self.mineral = mineral
self.weight = weight
def __str__(self) -> str:
if self.weight == 100:
return self.mineral.name
return f"{self.mineral.name} ({self.weight}%)"
def __repr__(self) -> str:
return "".join([str(p) for p in [
"Inclusion{",
"mineral: ", self.mineral.name, ", ",
"weight: ", self.weight,
"}"
]])
+24
View File
@@ -0,0 +1,24 @@
from pytest import fixture
from tungston.core.geology.inclusion import Inclusion
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.replacement import Replacement
# Fixtures #########################################################################################I
@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="inclusion")
def createInclusion(iron):
yield Inclusion(iron, 75)
# Tests ############################################################################################I
def test_repr(inclusion):
assert repr(inclusion) == "Inclusion{mineral: iron, weight: 75}"
+32
View File
@@ -0,0 +1,32 @@
from tungston.core.geology.replacement import Replacement
from tungston.core.resourceid import ResourceId
# Class ############################################################################################
class Mineral:
def __init__(self, name:str, replacements:None|tuple[Replacement]=None):
self.name = name
self.replacements = replacements or []
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return "".join([str(p) for p in [
f"Mineral<{self.name}>", "{",
"replacements: [",
", ".join([str(r) for r in self.replacements]),
"]",
"}"
]])
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))
+28
View File
@@ -0,0 +1,28 @@
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.replacement import Replacement
from pytest import fixture
import tungston.core.geology.mineral as mineral
# Fixtures #########################################################################################
@fixture(name="iron")
def createIron():
yield Mineral("iron", [
Replacement.inStone("iron_ore"),
Replacement.inDeepslate("deepslate_iron_ore"),
])
# Tests ############################################################################################
def test_repr(iron):
assert repr(iron) == (
"Mineral<iron>{" +
"replacements: [" +
"#minecraft:stone_ore_replaceables => minecraft:iron_ore, " +
"#minecraft:deepslate_ore_replaceables => minecraft:deepslate_iron_ore" +
"]" +
"}"
)
+26
View File
@@ -0,0 +1,26 @@
from tungston.core.geology.mineral import Mineral
from typing import Iterator
# Class ############################################################################################
class MineralCatalog:
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)
@@ -0,0 +1,34 @@
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.mineralcatalog import MineralCatalog
from tungston.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 ############################################################################################
def test_all(catalog):
assert [m.name for m in catalog.all()] == ["copper", "iron"]
def test_get(catalog):
assert catalog.get("iron").name == "iron"
+34
View File
@@ -0,0 +1,34 @@
# Class ############################################################################################
class Proportion:
def __init__(self, name:str, ratio:float):
self.name = name
self.ratio = ratio
def __eq__(self, other) -> bool:
if type(self) != type(other): return False
if self.name != other.name: return False
return True
def __hash__(self) -> int:
return hash(self.name)
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Proportion<{self.name}>{{ratio: {self.ratio}}}"
# Constants ########################################################################################
BED = Proportion("bed", 0.1) # salt, nitrate, redbed, loam, bif iron, peat coal
LENS = Proportion("lens", 0.4) # bit.coal, aluminum, lapis, quartzite
LODE = Proportion("lode", 0.7) # au.quartz, mvt lead
BODY = Proportion("body", 1.0) # sed.iron
STOCK = Proportion("stock", 1.3) # tin
VENT = Proportion("vent", 1.6) # sulfur
PIPE = Proportion("pipe", 1.9) # por.copper
ALL = [BED, LENS, LODE, BODY, STOCK, VENT, PIPE]
+12
View File
@@ -0,0 +1,12 @@
from pytest import fixture
import tungston.core.geology.proportion as proportion
# Tests ############################################################################################
def test_str():
assert str(proportion.LENS) == "lens"
def test_repr():
assert repr(proportion.LENS) == "Proportion<lens>{ratio: 0.4}"
+40
View File
@@ -0,0 +1,40 @@
from tungston.core.resourceid import ResourceId
# Constants ########################################################################################
STONE_REPLACEABLES = "#minecraft:stone_ore_replaceables"
DEEPSLATE_REPLACEABLES = "#minecraft:deepslate_ore_replaceables"
# Class ############################################################################################
class Replacement:
@staticmethod
def inStone(target:str, weight:int=100):
return Replacement(STONE_REPLACEABLES, target, weight)
@staticmethod
def inDeepslate(target:str, weight:int=100):
return Replacement(DEEPSLATE_REPLACEABLES, target, weight)
def __init__(self, source:str, target:str, weight:int=100):
self.source = ResourceId.canonical(source)
self.target = ResourceId.canonical(target)
self.weight = weight
def __str__(self) -> str:
if self.weight == 100:
return f"{self.source} => {self.target}"
return f"{self.source} => {self.target} ({self.weight}%)"
def __repr__(self) -> str:
return "".join([str(p) for p in [
"Replacement{" +
"source: ", self.source, ", ",
"target: ", self.target, ", ",
"weight: ", self.weight,
"}"
]])
+28
View File
@@ -0,0 +1,28 @@
from pytest import fixture
from tungston.core.geology.replacement import Replacement
# Fixtures #########################################################################################
@fixture(name="replacement")
def createReplacement():
yield Replacement("#minecraft:stone", "minecraft:iron_ore")
@fixture(name="weightedReplacement")
def createWeightedReplacement():
yield Replacement("#minecraft:dirt", "minecraft:gravel", 25)
# Tests ############################################################################################
def test_repr(replacement, weightedReplacement):
assert repr(replacement) == (
"Replacement{source: #minecraft:stone, target: minecraft:iron_ore, weight: 100}"
)
assert repr(weightedReplacement) == (
"Replacement{source: #minecraft:dirt, target: minecraft:gravel, weight: 25}"
)
def test_str(replacement, weightedReplacement):
assert str(replacement) == "#minecraft:stone => minecraft:iron_ore"
assert str(weightedReplacement) == "#minecraft:dirt => minecraft:gravel (25%)"
+89
View File
@@ -0,0 +1,89 @@
from tungston.core.altitude import Altitude
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.fauna.group import Group
from tungston.core.fauna.location import Location
from tungston.core.scarcity import Scarcity
from tungston.core.season import Season
import tungston.core.altitude as A
import tungston.core.fauna.group as G
import tungston.core.fauna.location as L
import tungston.core.scarcity as C
import tungston.core.season as E
# Class ############################################################################################
class Habitat:
"""
A description of where and when various features may be present.
"""
def __init__(
self,
altitudes:tuple[Altitude]|Altitude=[A.ANYWHERE],
biomeFilter:BiomeFilter=None,
seasons:tuple[Season]=E.ALL,
group:Group=G.SOLO,
location:Location=L.OUTSIDE,
scarcity:Scarcity=C.SPARSE,
):
self.altitudes = (altitudes,) if isinstance(altitudes, Altitude) else altitudes
self.biomeFilter = biomeFilter or BiomeFilter()
self.seasons = (seasons,) if isinstance(seasons, Season) else seasons
self.group = group
self.location = location
self.scarcity = scarcity
self._source = None
def __str__(self) -> str:
return "".join(str(p) for p in [
self.altitude, "|",
self.biomeFilter, "|",
self.seasons, "|",
self.group, "|",
self.location, "|",
self.scarcity
])
def __repr__(self) -> str:
return "".join([str(p) for p in [
"Habitat{",
"altitude: [", ", ".join([repr(a) for a in self.altitudes]), "], ",
"biomeFilter: ", repr(self.biomeFilter), ", ",
"seasons: [", ", ".join([repr(s) for s in self.seasons]), "], ",
"group: ", repr(self.group), ", ",
"location: ", repr(self.location), ", ",
"scarcity: ", repr(self.scarcity),
"}"
]])
def derive(self, **kwargs):
kwargs = {
"altitudes": self.altitudes,
"biomeFilter": self.biomeFilter,
"seasons": self.seasons,
"group": self.group,
"location": self.location,
"scarcity": self.scarcity
} | kwargs
result = Habitat(**kwargs)
result._source = self
return result
def collect(self) -> "tuple[Habitat]":
result = []
current = self
while current:
result.append(current)
current = current._source
return tuple(reversed(result))
+45
View File
@@ -0,0 +1,45 @@
from pytest import fixture
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.habitat import Habitat
import tungston.core.ecology.flora as FL
import tungston.core.ecology.heat as HE
import tungston.core.season as SE
import tungston.core.scarcity as SC
# Fixtures #########################################################################################
@fixture(name="fields")
def createFieldsFilter():
yield BiomeFilter([FL.FIELD, HE.TEMPERATE])
@fixture(name="derivedHabitats")
def createDerivedHabitat(fields):
yield (
Habitat(biomeFilter=fields, seasons=SE.SUMMER, scarcity=SC.COMMON)
.derive(seasons=SE.AUTUMN, scarcity=SC.UNCOMMON)
.derive(seasons=SE.WINTER, scarcity=SC.ABSENT)
.collect()
)
@fixture(name="fields")
def createFieldsHabitat(fields):
yield Habitat(biomeFilter=fields)
# Tests ############################################################################################
def test_derive(derivedHabitats):
assert [h.scarcity for h in derivedHabitats] == [SC.COMMON, SC.UNCOMMON, SC.ABSENT]
def test_repr(fields):
assert repr(fields) == (
"Habitat{" +
"altitude: [anywhere <-64 to 320>], " +
"biomeFilter: BiomeFilter([[Flora<field>, Heat<temperate>]], [[]]), " +
"seasons: [Season<spring>, Season<summer>, Season<autumn>, Season<winter>], " +
"group: solo<1 to 1>, " +
"location: Location<outside>, " +
"scarcity: Scarcity<sparse>" +
"}"
)
+26
View File
@@ -0,0 +1,26 @@
from tungston.core.habitat import Habitat
# Class ############################################################################################
class Placement:
"""
Abstract base class for placing something into its various habitats.
"""
def __init__(self, habitats:tuple[Habitat]=None):
self.habitats = habitats
if not self.habitats:
self.habitats = ()
if isinstance(self.habitats, Habitat):
self.habitats = self.habitats.collect()
def __repr__(self) -> str:
return (
"Placement{" +
f"habitats: [{', '.join([repr(h) for h in self.habitats])}]" +
"}"
)
+38
View File
@@ -0,0 +1,38 @@
from pytest import fixture
from tungston.core.ecology.biomefilter import BiomeFilter
from tungston.core.habitat import Habitat
from tungston.core.placement import Placement
import tungston.core.ecology.flora as F
import tungston.core.ecology.heat as E
# Fixtures #########################################################################################
@fixture(name="fields")
def createFieldsHabitat():
yield Habitat(biomeFilter=BiomeFilter([F.FIELD, E.TEMPERATE]))
@fixture(name="placement")
def createPlacement(fields):
yield Placement([fields])
# Tests ############################################################################################
def test_repr(placement):
assert repr(placement) == (
"Placement{" +
"habitats: [" +
"Habitat{" +
"altitude: [anywhere <-64 to 320>], " +
"biomeFilter: BiomeFilter([[Flora<field>, Heat<temperate>]], [[]]), " +
"seasons: [Season<spring>, Season<summer>, Season<autumn>, Season<winter>], " +
"group: solo<1 to 1>, " +
"location: Location<outside>, " +
"scarcity: Scarcity<sparse>" +
"}" +
"]" +
"}"
)
+56
View File
@@ -0,0 +1,56 @@
from collections.abc import Callable
# Class ############################################################################################
class ResourceId:
@staticmethod
def alterName(text:str, doTransform:Callable[[str],str]) -> str:
resourceId = ResourceId.parse(text)
resourceId.name = doTransform(resourceId.name)
return str(resourceId)
@staticmethod
def canonical(text:str):
return str(ResourceId.parse(text))
@staticmethod
def parse(text:str):
isTag = False
if text.startswith("#"):
isTag = True
text = text[1:]
index = text.find(":")
if index > 0:
mod = text[0:index]
name = text[index+1:]
elif index == 0:
mod = "minecraft"
name = text[1:]
else:
mod = "minecraft"
name = text
return ResourceId(isTag, mod, name)
def __init__(self, isTag:bool, mod:str, name:str):
self.isTag = isTag
self.mod = mod
self.name = name
def __str__(self) -> str:
if not self.isTag:
return f"{self.mod}:{self.name}"
return f"#{self.mod}:{self.name}"
def __repr__(self) -> str:
return "".join([str(p) for p in [
"ResourceId{",
"isTag: ", ("True" if self.isTag else "False"), ", ",
"mod: ", self.mod, ", ",
"name: ", self.name,
"}"
]])
+16
View File
@@ -0,0 +1,16 @@
from tungston.core.resourceid import ResourceId
# Tests ############################################################################################
def test_singlePart():
assert str(ResourceId.parse("alpha")) == "minecraft:alpha"
def test_leadingSeparator():
assert str(ResourceId.parse(":bravo")) == "minecraft:bravo"
def test_fullResource():
assert str(ResourceId.parse("charlie:delta")) == "charlie:delta"
def test_fullTag():
assert str(ResourceId.parse("#charlie:delta")) == "#charlie:delta"
+27
View File
@@ -0,0 +1,27 @@
# Class ############################################################################################
class Scarcity:
"""
How frequently something appears within a given region.
"""
def __init__(self, name):
self.name = name
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Scarcity<{self.name}>"
# Constants ########################################################################################
ABSENT = Scarcity("absent")
RARE = Scarcity("rare")
UNUSUAL = Scarcity("unusual")
SPARSE = Scarcity("sparse")
UNCOMMON = Scarcity("uncommon")
COMMON = Scarcity("common")
CARPET = Scarcity("carpet")
ALL = [ABSENT, RARE, UNUSUAL, SPARSE, UNCOMMON, COMMON, CARPET]
+9
View File
@@ -0,0 +1,9 @@
from tungston.core.scarcity import Scarcity
from pytest import fixture
# Tests ############################################################################################
def test_syntax():
pass
+44
View File
@@ -0,0 +1,44 @@
# Class ############################################################################################
class Season:
"""
A time of year demonstrating different climate and activity among flora and fauna.
"""
def __init__(self, name):
self.name = name
def __str__(self) -> str:
return self.name
def __repr__(self) -> str:
return f"Season<{self.name}>"
# Constants ########################################################################################
SPRING = Season("spring")
SUMMER = Season("summer")
AUTUMN = Season("autumn")
WINTER = Season("winter")
ALL = [SPRING, SUMMER, AUTUMN, WINTER]
WET = [WINTER, SPRING]
DRY = [SUMMER, AUTUMN]
HOT = [SUMMER]
COOL = [SPRING, AUTUMN]
COLD = [WINTER]
# Constants ########################################################################################
def excluding(target:Season) -> list[Season]:
result = []
for season in ALL:
if season == target: continue
result.append(season)
return result
+16
View File
@@ -0,0 +1,16 @@
from pytest import fixture
import tungston.core.season as season
# Fixtures #########################################################################################
@fixture(name="notSummer")
def createNotSummerList():
yield season.excluding(season.SUMMER)
# Tests ############################################################################################
def test_excluding(notSummer):
assert ", ".join([str(s) for s in notSummer]) == "spring, autumn, winter"
+21
View File
@@ -0,0 +1,21 @@
from tungston.core.ecology.biomecatalog import BiomeCatalog
from tungston.core.fauna.mobcatalog import MobCatalog
from tungston.core.geology.mineralcatalog import MineralCatalog
from tungston.core.geology.depositcatalog import DepositCatalog
# Class ############################################################################################
class World:
def __init__(
self,
biomes:BiomeCatalog,
deposits:DepositCatalog,
minerals:MineralCatalog,
mobs:MobCatalog
):
self.biomes = biomes
self.deposits = deposits
self.minerals = minerals
self.mobs = mobs
+7
View File
@@ -0,0 +1,7 @@
from tungston.core.world import World
# Tests ############################################################################################
def test_syntax():
pass
+14
View File
@@ -0,0 +1,14 @@
import os
# Class ############################################################################################
class Datapack:
def __init__(self, path:str):
self.path = path
@property
def name(self) -> str:
return os.path.basename(self.path)
+18
View File
@@ -0,0 +1,18 @@
from typing import Any
# Class ############################################################################################
class BlockState:
def __init__(self, blockId:str, properties:dict[str,str]=None):
self.blockId = blockId
self.properties = properties
def asData(self) -> dict[str,Any]:
result = { "Name": self.blockId }
if self.properties:
result["Properties"] = self.properties
return result
@@ -0,0 +1,20 @@
from pytest import fixture
from tungston.generator.datapack.blockstate import BlockState
# Fixtures #########################################################################################
@fixture(name="state")
def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"})
# Tests ############################################################################################
def test_asData(state):
assert state.asData() == {
"Name": "minecraft:button",
"Properties": {
"waterlogged": "true"
}
}
@@ -0,0 +1,7 @@
# Class ############################################################################################
class BlockStateProvider:
def __init__(self, gameId:str):
self.gameId = gameId
@@ -0,0 +1,18 @@
from tungston.generator.datapack.blockstate import BlockState
from tungston.generator.datapack.blockstateprovider import BlockStateProvider
from typing import Any
# Class ############################################################################################
class SimpleStateProvider(BlockStateProvider):
def __init__(self, state:BlockState):
super().__init__("minecraft:simple_state_provider")
self.state = state
def asData(self) -> dict[str, Any]:
return {
"type": self.gameId,
"state": self.state.asData(),
}
@@ -0,0 +1,28 @@
from tungston.generator.datapack.blockstate import BlockState
from tungston.generator.datapack.blockstateprovider.simplestateprovider import SimpleStateProvider
from pytest import fixture
# Fixtures #########################################################################################
@fixture(name="state")
def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider")
def createProvider(state):
return SimpleStateProvider(state)
# Tests ############################################################################################
def test_asData(provider):
assert provider.asData() == {
"type": "minecraft:simple_state_provider",
"state": {
"Name": "minecraft:button",
"Properties": {
"waterlogged": "true"
}
}
}
@@ -0,0 +1,6 @@
# Class ############################################################################################
class ConfiguredFeature:
def __init__(self, gameId:str):
self.gameId = gameId
@@ -0,0 +1,31 @@
from tungston.generator.datapack.configuredfeature.configuredfeature import ConfiguredFeature
from typing import Any
# Class ############################################################################################
class RandomPatch(ConfiguredFeature):
def __init__(
self,
gameId:str,
feature:"PlacedFeature",
tries:int=128,
xzSpread:int=7,
ySpread:int=3,
):
super().__init__("minecraft:random_patch")
self.feature = feature
self.tries = tries
self.xzSpread = xzSpread
self.ySpread = ySpread
def asData(self) -> dict[str,Any]:
return {
"type": self.type,
"feature": self.feature.gameId,
"tries": self.tries,
"xz_spread": self.xySpread,
"y_spread": self.ySpread
}
@@ -0,0 +1,38 @@
from pytest import fixture
from tungston.generator.datapack.blockstate import BlockState
from tungston.generator.datapack.blockstateprovider.simplestateprovider import SimpleStateProvider
from tungston.generator.datapack.configuredfeature.simpleblock import SimpleBlock
# Fixtures #########################################################################################
@fixture(name="state")
def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider")
def createProvider(state):
return SimpleStateProvider(state)
@fixture(name="feature")
def createSimpleBlockFeature(provider):
return SimpleBlock(provider)
# Tests ############################################################################################
def test_asData(feature):
assert feature.asData() == {
"type": "minecraft:simple_block",
"config": {
"to_place": {
"type": "minecraft:simple_state_provider",
"state": {
"Name": "minecraft:button",
"Properties": {
"waterlogged": "true"
}
}
}
}
}
@@ -0,0 +1,20 @@
from tungston.generator.datapack.blockstateprovider import BlockStateProvider
from tungston.generator.datapack.configuredfeature import ConfiguredFeature
from typing import Any
# Class ############################################################################################
class SimpleBlock(ConfiguredFeature):
def __init__(self, toPlace:BlockStateProvider):
super().__init__("minecraft:simple_block")
self.toPlace = toPlace
def asData(self) -> dict[str, Any]:
return {
"type": self.gameId,
"config": {
"to_place": self.toPlace.asData()
}
}
@@ -0,0 +1,38 @@
from pytest import fixture
from tungston.generator.datapack.blockstate import BlockState
from tungston.generator.datapack.blockstateprovider.simplestateprovider import SimpleStateProvider
from tungston.generator.datapack.configuredfeature.simpleblock import SimpleBlock
# Fixtures #########################################################################################
@fixture(name="state")
def createBlockState():
yield BlockState("minecraft:button", {"waterlogged": "true"})
@fixture(name="provider")
def createProvider(state):
return SimpleStateProvider(state)
@fixture(name="feature")
def createSimpleBlockFeature(provider):
return SimpleBlock(provider)
# Tests ############################################################################################
def test_asData(feature):
assert feature.asData() == {
"type": "minecraft:simple_block",
"config": {
"to_place": {
"type": "minecraft:simple_state_provider",
"state": {
"Name": "minecraft:button",
"Properties": {
"waterlogged": "true"
}
}
}
}
}
@@ -0,0 +1,24 @@
# Class ############################################################################################
class HeightMapType:
"""
A cached record of the top block at all points in the world.
see: https://minecraft.wiki/w/Heightmap
"""
def __init__(self, gameId:str):
self.gameId = gameId
def asData(self) -> str:
return self.gameId
# Constants ########################################################################################
MOTION_BLOCKING = HeightMapType("MOTION_BLOCKING")
MOTION_BLOCKING_NO_LEAVES = HeightMapType("MOTION_BLOCKING_NO_LEAVES")
OCEAN_FLOOR = HeightMapType("OCEAN_FLOOR")
OCEAN_FLOOR_WG = HeightMapType("OCEAN_FLOOR_WG")
WORLD_SURFACE = HeightMapType("WORLD_SURFACE")
WORLD_SURFACE_WG = HeightMapType("WORLD_SURFACE_WG")
@@ -0,0 +1,7 @@
from tungston.generator.datapack.heightmaptype import HeightMapType
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,6 @@
# Class ############################################################################################
class PlacedFeature:
def __init__(self, gameId:str):
self.gameId = gameId
@@ -0,0 +1,6 @@
from tungston.generator.datapack.placedfeature import PlacedFeature
# Tests ############################################################################################
def test_syntax():
pass
@@ -0,0 +1,6 @@
# Class ############################################################################################
class Placement:
def __init__(self, gameId:str):
self.gameId = gameId
@@ -0,0 +1,13 @@
from tungston.generator.datapack.placement import Placement
from typing import Any
# Class ############################################################################################
class Biome(Placement):
def __init__(self):
super().__init__("minecraft:biome")
def asData(self) -> dict[str,Any]:
return { "type": self.gameId }
@@ -0,0 +1,18 @@
from pytest import fixture
from tungston.generator.datapack.placement.biome import Biome
# Fixtures #########################################################################################
@fixture(name="placement")
def createPlacement():
yield Biome()
# Tests ############################################################################################
def test_asData(placement):
assert placement.asData() == {
"type": "minecraft:biome",
}
@@ -0,0 +1,17 @@
from tungston.generator.datapack.placement import Placement
from tungston.generator.datapack.heightmaptype import HeightMapType
from typing import Any
# Class ############################################################################################
class HeightMap(Placement):
def __init__(self, heightMap:HeightMapType):
super().__init__("minecraft:heightmap")
self.heightMap = heightMap
def asData(self) -> dict[str,Any]:
return {
"type": self.gameId,
"heightmap": self.heightMap.asData()
}
@@ -0,0 +1,20 @@
from pytest import fixture
from tungston.generator.datapack.placement.heightmap import HeightMap
from tungston.generator.datapack.heightmaptype import WORLD_SURFACE
# Fixtures #########################################################################################
@fixture(name="placement")
def createPlacement():
yield HeightMap(WORLD_SURFACE)
# Tests ############################################################################################
def test_asData(placement):
assert placement.asData() == {
"type": "minecraft:heightmap",
"heightmap": "WORLD_SURFACE"
}
@@ -0,0 +1,13 @@
from tungston.generator.datapack.placement import Placement
from typing import Any
# Class ############################################################################################
class InSquare(Placement):
def __init__(self):
super().__init__("minecraft:in_square")
def asData(self) -> dict[str,Any]:
return { "type": self.gameId }
@@ -0,0 +1,18 @@
from pytest import fixture
from tungston.generator.datapack.placement.insquare import InSquare
# Fixtures #########################################################################################
@fixture(name="placement")
def createPlacement():
yield InSquare()
# Tests ############################################################################################
def test_asData(placement):
assert placement.asData() == {
"type": "minecraft:in_square",
}
@@ -0,0 +1,17 @@
from tungston.generator.datapack.placement import Placement
from typing import Any
# Class ############################################################################################
class RarityFilter(Placement):
def __init__(self, chance:int):
super().__init__("minecraft:rarity_filter")
self.chance = chance
def asData(self) -> dict[str,Any]:
return {
"type": self.gameId,
"chance": self.chance
}
@@ -0,0 +1,19 @@
from pytest import fixture
from tungston.generator.datapack.placement.rarityfilter import RarityFilter
# Fixtures #########################################################################################
@fixture(name="placement")
def createPlacement():
yield RarityFilter(4)
# Tests ############################################################################################
def test_asData(placement):
assert placement.asData() == {
"type": "minecraft:rarity_filter",
"chance": 4
}
@@ -0,0 +1,19 @@
from tungston.core.world import World
from tungston.generator.markdown.report import Report
# Class ############################################################################################
class MineralReport(Report):
def build(self):
for mineral in self.world.minerals.all():
self.line(f"# Mineral: {mineral.name}")
self.line()
self.indent()
for replacement in mineral.replacements:
self.line(str(replacement))
self.outdent()
self.line()
@@ -0,0 +1,55 @@
from pytest import fixture
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.mineralcatalog import MineralCatalog
from tungston.core.geology.replacement import Replacement
from tungston.core.world import World
from tungston.generator.markdown.mineralreport import MineralReport
import textwrap
# 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="minerals")
def createMineralCatalog(copper, iron):
yield MineralCatalog([copper, iron])
@fixture(name="world")
def createWorld(minerals):
yield World(None, None, minerals, None)
@fixture(name="report")
def createReport(world):
report = MineralReport(world)
report.build()
yield report
# Tests ############################################################################################
def test_report(report):
assert str(report) == textwrap.dedent("""
# Mineral: copper
#minecraft:stone_replaceables => minecraft:copper_ore
#minecraft:deepslate_replaceables => minecraft:deepslate_copper_ore
# Mineral: iron
#minecraft:stone_replaceables => minecraft:iron_ore
#minecraft:deepslate_replaceables => minecraft:deepslate_iron_ore
""").strip()
+70
View File
@@ -0,0 +1,70 @@
from collections.abc import Iterator
from tungston.core.world import World
# Constants ########################################################################################
INDENT = " "
# Class ############################################################################################
class Report:
def __init__(self, world:World):
self.world = world
self.reset()
def __str__(self) -> str:
return "\n".join(self._lines).strip()
def __repr__(self) -> str:
return (
"Report{" +
f"lines: {len(self._lines)} lines, " +
f"lineBuffer: {len(self._lineBuffer)} chunks, " +
f"indent: {self._indent}" +
"}"
)
def build(self):
raise NotImplementedError()
def reset(self) -> "Report":
self._lineBuffer = []
self._lines = []
self._indent = 0
return self
def asLines(self) -> Iterator[str]:
for line in self._lines:
yield line
# Helper Methods ###########################################################
def indent(self) -> "Report":
self._indent += 1
self._lineBuffer.insert(0, INDENT)
return self
def line(self, text:str="") -> "Report":
self.text(text)
self._lines.append("".join(self._lineBuffer))
self._lineBuffer = []
while len(self._lineBuffer) < self._indent:
self._lineBuffer.append(INDENT)
return self
def outdent(self) -> "Report":
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) -> "Report":
self._lineBuffer.append(str(text))
return self
@@ -0,0 +1,31 @@
from pytest import fixture
from tungston.generator.markdown.report import Report
# Fixtures #########################################################################################
@fixture(name="emptyReport")
def createEmptyReport():
return Report()
@fixture(name="report")
def createReport():
return (
Report(None)
.text("alpha")
.line("bravo")
.indent()
.line("charlie")
.indent()
.line("delta")
.outdent()
.line("echo")
)
# Tests ############################################################################################
def test_repr(report):
assert repr(report) == "Report{lines: 4 lines, lineBuffer: 1 chunks, indent: 1}"
def test_str(report):
assert str(report) == "alphabravo\n charlie\n delta\n echo"
@@ -0,0 +1,165 @@
from tungston.core.ecology.biome import Biome
from tungston.core.ecology.biomecatalog import BiomeCatalog
from tungston.core.ecology.biomefilter import BiomeFilter
import tungston.core.ecology.flora as F
import tungston.core.ecology.geology as G
import tungston.core.ecology.heat as E
import tungston.core.ecology.humidity as U
import tungston.core.ecology.soil as S
import tungston.core.ecology.water as W
# Constants ########################################################################################
CATALOG = BiomeCatalog([
Biome("aberdeen", "minecraft:windswept_gravelly_hills",
F.BARREN, G.METAMORPHIC, E.BOREAL, U.DAMP, S.ROCKY, W.INLAND
),
Biome("archangel", "minecraft:frozen_ocean",
F.BARREN, G.SEDIMENTARY, E.FROZEN, U.WET, S.SANDY, W.OCEAN
),
Biome("aspen", "minecraft:frozen_peaks",
F.BARREN, G.IGNEOUS, E.FROZEN, U.WET, S.ROCKY, W.INLAND
),
Biome("bombay", "minecraft:lukewarm_ocean",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.WET, S.SANDY, W.OCEAN
),
Biome("boston", "minecraft:cold_ocean",
F.BARREN, G.SEDIMENTARY, E.BOREAL, U.WET, S.CLAYEY, W.OCEAN
),
Biome("bryce", "minecraft:eroded_badlands",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.CLAYEY, W.INLAND
),
Biome("calcutta", "minecraft:mangrove_swamp",
F.FOREST, G.SEDIMENTARY, E.SUBTROPICAL, U.WET, S.CLAYEY, W.INLAND
),
Biome("cornwall", "minecraft:windswept_hills",
F.BARREN, G.METAMORPHIC, E.BOREAL, U.DAMP, S.ROCKY, W.INLAND
),
Biome("dallas", "minecraft:savanna",
F.FIELD, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("duluth", "minecraft:frozen_river",
F.BARREN, G.SEDIMENTARY, E.FROZEN, U.WET, S.SANDY, W.RIVER
),
Biome("durango", "minecraft:savanna_plateau",
F.FIELD, G.IGNEOUS, E.SUBTROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("freiburg", "minecraft:dark_forest",
F.CANOPY, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.CLAYEY, W.INLAND
),
Biome("glasgow", "minecraft:windswept_forest",
F.CLEARING, G.METAMORPHIC, E.BOREAL, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("haarlem", "minecraft:flower_forest",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("halifax", "minecraft:deep_cold_ocean",
F.BARREN, G.SEDIMENTARY, E.BOREAL, U.WET, S.SANDY, W.OCEAN
),
Biome("hammerfest", "minecraft:ice_spikes",
F.BARREN, G.METAMORPHIC, E.FROZEN, U.WET, S.ROCKY, W.INLAND
),
Biome("havana", "minecraft:deep_lukewarm_ocean",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.WET, S.SANDY, W.OCEAN
),
Biome("hilo", "minecraft:mushroom_fields",
F.CLEARING, G.IGNEOUS, E.SUBTROPICAL, U.WET, S.FUNGAL, W.INLAND
),
Biome("honolulu", "minecraft:deep_ocean",
F.BARREN, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.SANDY, W.OCEAN
),
Biome("innnesbruk", "minecraft:meadow",
F.FIELD, G.SEDIMENTARY, E.BOREAL, U.DAMP, S.PEATY, W.INLAND
),
Biome("irkutsk", "minecraft:taiga",
F.FOREST, G.METAMORPHIC, E.BOREAL, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("jackson", "minecraft:jagged_peaks",
F.BARREN, G.METAMORPHIC, E.BOREAL, U.DRY, S.ROCKY, W.INLAND
),
Biome("juneau", "minecraft:old_growth_spruce_taiga",
F.FOREST, G.METAMORPHIC, E.BOREAL, U.DAMP, S.PEATY, W.INLAND
),
Biome("kansascity", "minecraft:plains",
F.FIELD, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("kola", "minecraft:snowy_taiga",
F.BARREN, G.METAMORPHIC, E.FROZEN, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("kyoto", "minecraft:cherry_grove",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.ROCKY, W.INLAND
),
Biome("madras", "minecraft:sparse_jungle",
F.CLEARING, G.SEDIMENTARY, E.TROPICAL, U.WET, S.ACIDIC, W.INLAND
),
Biome("memphis", "minecraft:river",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.SANDY, W.RIVER
),
Biome("minsk", "minecraft:old_growth_birch_forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("moab", "minecraft:windswept_savanna",
F.FIELD, G.IGNEOUS, E.SUBTROPICAL, U.DRY, S.ROCKY, W.INLAND
),
Biome("mobile", "minecraft:swamp",
F.CLEARING, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.PEATY, W.SWAMP
),
Biome("moscow", "minecraft:snowy_plains",
F.FIELD, G.SEDIMENTARY, E.FROZEN, U.DAMP, S.LOAMY, W.INLAND
),
Biome("nassau", "minecraft:warm_ocean",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.WET, S.SANDY, W.COAST
),
Biome("nice", "minecraft:beach",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.DAMP, S.SANDY, W.COAST
),
Biome("nuuk", "minecraft:beach",
F.BARREN, G.SEDIMENTARY, E.FROZEN, U.DAMP, S.SANDY, W.COAST
),
Biome("perm", "minecraft:old_growth_pine_taiga",
F.FOREST, G.METAMORPHIC, E.BOREAL, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("phoenix", "minecraft:desert",
F.BARREN, G.SEDIMENTARY, E.TROPICAL, U.DRY, S.SANDY, W.INLAND
),
Biome("plymouth", "minecraft:stony_shore",
F.BARREN, G.METAMORPHIC, E.TEMPERATE, U.DAMP, S.ROCKY, W.COAST
),
Biome("portland", "minecraft:forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("quito", "minecraft:stony_peaks",
F.BARREN, G.IGNEOUS, E.BOREAL, U.DRY, S.ROCKY, W.INLAND
),
Biome("rangoon", "minecraft:bamboo_jungle",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.LOAMY, W.INLAND
),
Biome("sanfrancisco", "minecraft:ocean",
F.BARREN, G.SEDIMENTARY, E.TEMPERATE, U.WET, S.SANDY, W.OCEAN
),
Biome("santafe", "minecraft:wooded_badlands",
F.CLEARING, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.CLAYEY, W.INLAND
),
Biome("singapore", "minecraft:jungle",
F.CANOPY, G.SEDIMENTARY, E.TROPICAL, U.WET, S.ACIDIC, W.INLAND
),
Biome("tombstone", "minecraft:badlands",
F.BARREN, G.SEDIMENTARY, E.SUBTROPICAL, U.DRY, S.CLAYEY, W.INLAND
),
Biome("topeka", "minecraft:sunflower_plains",
F.FIELD, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.LOAMY, W.INLAND
),
Biome("tromso", "minecraft:deep_frozen_ocean",
F.BARREN, G.SEDIMENTARY, E.FROZEN, U.WET, S.SANDY, W.OCEAN
),
Biome("umea", "minecraft:grove",
F.CLEARING, G.METAMORPHIC, E.FROZEN, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("warsaw", "minecraft:birch_forest",
F.FOREST, G.SEDIMENTARY, E.TEMPERATE, U.DAMP, S.ACIDIC, W.INLAND
),
Biome("zurich", "minecraft:snowy_slopes",
F.BARREN, G.METAMORPHIC, E.FROZEN, U.DAMP, S.ROCKY, W.INLAND
),
])
@@ -0,0 +1,28 @@
from tungston.core.ecology.biomefilter import BiomeFilter as BF
from tungston.core.geology.depositcatalog import DepositCatalog
from tungston.core.geology.deposit.inclusion import Inclusion as I
from tungston.core.geology.deposit.metaldeposit import MetalDeposit
from tungston.modpack.mysteriousisland.mineralcatalog import CATALOG as M
import tungston.core.altitude as AL
import tungston.core.ecology.flora as FL
import tungston.core.ecology.geology as GE
import tungston.core.ecology.heat as HE
import tungston.core.ecology.humidity as HU
import tungston.core.ecology.soil as SO
import tungston.core.ecology.water as WA
import tungston.core.geology.bulk as BU
import tungston.core.scarcity as SC
# Catalog ##########################################################################################
CATALOG = C = DepositCatalog(minerals)
C.add(MetalDeposit(
name = "bif_iron",
biomeFilter = BF([GE.METAMORPHIC, (HE.BOREAL, HE.FROZEN), HU.DAMP]),
scarcity = SC.COMMON,
minerals = [I(M.get("iron"), 50), I(M.get("quartz"), 45), I(M.get("uranium"), 5)],
bulk = BU.LARGE,
proportion = 0.2,
))
@@ -0,0 +1,109 @@
from tungston.core.geology.mineral import Mineral
from tungston.core.geology.mineralcatalog import MineralCatalog
from tungston.core.geology.replacement import Replacement
# Constants ########################################################################################
IE = "immersiveengineering"
OQ = "overworldquartzore"
RC = "railcraft"
# Helpers ##########################################################################################
def makeMineral(name:str, blockId:str, deepslateBlockId:None|str=None) -> Mineral:
deepslateBlockId = deepslateBlockId if deepslateBlockId else blockId
return Mineral(name, [
R.inStone(blockId),
R.inDeepslate(blockId)
])
def makeOreMineral(name:str) -> Mineral:
return Mineral(name, [
R.inStone(f"{name}_ore"),
R.inDeepslate(f"deepslate_{name}_ore")
])
def makeImmersiveEngineeringOreMineral(name:str) -> Mineral:
return Mineral(name, [
R.inStone(f"{IE}:ore_{name}"),
R.inDeepslate("{IE}:deepslate_ore_{name}")
]),
def makeRailcraftOreMineral(name:str) -> Mineral:
return Mineral(name, [
R.inStone(f"{RC}:{name}_ore"),
R.inDeepslate("{RC}:deepslate_{name}_ore")
]),
# Catalog ##########################################################################################
CATALOG = C = MineralCatalog()
# Basic Ores
C.add(makeOreMineral("coal"))
C.add(makeOreMineral("copper"))
C.add(makeOreMineral("diamond"))
C.add(makeOreMineral("emerald"))
C.add(makeOreMineral("gold"))
C.add(makeOreMineral("iron"))
C.add(makeOreMineral("lapis"))
C.add(makeOreMineral("redstone"))
# Crystals
C.add(makeMineral("amethyst", "amethyst_block"))
C.add(makeMineral("glowstone", "glowstone"))
C.add(makeMineral("quartz", f"{OQ}:quartz_ore") f"{OQ}:deepslate_quartz_ore")
C.add(makeMineral("salt", "butcher:saltblock"))
# Earth, gravel, etc.
C.add(makeMineral("clay", "clay"))
C.add(makeMineral("coarsedirt", "coarse_dirt"))
C.add(makeMineral("dirt", "dirt"))
C.add(makeMineral("gravel", "gravel"))
C.add(makeMineral("loam", "farmersdelight:rich_soil"))
C.add(makeMineral("packedice", "packed_ice"))
C.add(makeMineral("peat", "kubejs:peat_block"))
C.add(makeMineral("redsand", "redsand"))
C.add(makeMineral("sand", "sand"))
C.add(makeMineral("soulsand", "soulsand"))
# Stone
C.add(makeMineral("andesite", "andesite"))
C.add(makeMineral("arkrose", "red_sandstone"))
C.add(makeMineral("basalt", "basalt"))
C.add(makeMineral("breccia", "cobblestone"))
C.add(makeMineral("chalk", "calcite"))
C.add(makeMineral("diorite", "diorite"))
C.add(makeMineral("dolostone", "end_stone"))
C.add(makeMineral("gneiss", "deepslate"))
C.add(makeMineral("granite", "granite"))
C.add(makeMineral("greywacke", "stone"))
C.add(makeMineral("komatite", "blackstone"))
C.add(makeMineral("limestone", "dripstone_block"))
C.add(makeMineral("magma", "magma_block"))
C.add(makeMineral("marble", f"{RC}:quarried_stone"))
C.add(makeMineral("netherite", "ancient_debris"))
C.add(makeMineral("obsidian", "obsidian"))
C.add(makeMineral("pumice", "netherrack"))
C.add(makeMineral("sandstone", "sandstone"))
C.add(makeMineral("tuff", "tuff"))
# Immersive Engineering Ores
C.add(makeImmersiveEngineeringOreMineral("aluminum"))
C.add(makeImmersiveEngineeringOreMineral("lead"))
C.add(makeImmersiveEngineeringOreMineral("nickel"))
C.add(makeImmersiveEngineeringOreMineral("silver"))
C.add(makeImmersiveEngineeringOreMineral("uranium"))
# Railcraft Ores
C.add(Mineral("saltpeter", [
Replacement("sand", f"{RC}:saltpeter_ore"),
Replacement("sandstone", f"{RC}:saltpeter_ore"),
]))
C.add(makeRailcraftOreMineral("sulfur"))
C.add(makeRailcraftOreMineral("tin"))
C.add(makeRailcraftOreMineral("zinc"))
@@ -0,0 +1,183 @@
from tungston.core.ecology.biomefilter import BiomeFilter as BF
from tungston.core.fauna.mob import Mob
from tungston.core.fauna.mobplacement import MobPlacement
from tungston.core.fauna.mobcatalog import MobCatalog
import tungston.core.active as AC
import tungston.core.altitude as AL
import tungston.core.ecology.flora as FL
import tungston.core.ecology.geology as GE
import tungston.core.ecology.heat as HE
import tungston.core.ecology.humidity as HU
import tungston.core.ecology.soil as SO
import tungston.core.ecology.water as WA
import tungston.core.fauna.group as GR
import tungston.core.fauna.location as LO
import tungston.core.scarcity as SC
import tungston.core.season as SE
# Constants ########################################################################################
CATALOG = MobCatalog([
MobPlacement(Mob("armadillo", "minecraft:armadillo", AC.NOCTURNAL),
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, SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON,
).derive(
altitude = AL.UPLANDS, scarcity = SC.UNUSUAL,
)
),
MobPlacement(Mob("black_bear", "bearminimum:black_bear"),
Habitat(
altitudes = 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, (HE.CANOPY, HE.FOREST)]),
seasons = SE.AUTUMN,
scarcity = SC.SPARSE
).derive(
seasons = [SE.SPRING, SE.SUMMER], scarcity = SC.UNUSUAL
).derive(
seasons = SE.WINTER, scarcity = SC.RARE
)
),
MobPlacement(Mob("blaze", "minecraft:blaze"),
Habitat(
altitudes = AL.PLUTONIC,
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
),
MobPlacement(Mob("bogged", "minecraft:bogged")),
MobPlacement(Mob("brown_bear", "bearminimum:brown_bear")
Habitat(
altitudes = 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
)
),
MobPlacement(Mob("bulwark", "immersiveengineering:bulwark")),
MobPlacement(Mob("camel", "minecraft:camel", AC.CREPUSCULAR),
Habitat(
altitudes = AL.span(AL.DUNES, AL.LOWLANDS),
biomeFilter = BF([HE.TROPICAL, HU.DRY, FL.BARREN, SO.SANDY]),
seasons = SE.WET,
group = GR.FAMILY,
scarcity = SC.UNUSUAL,
).derive(
seasons = SE.DRY, scarcity = SC.RARE
)
),
MobPlacement(Mob("cat", "minecraft:cat")),
MobPlacement(Mob("cave_spider", "minecraft:cave_spider"),
Habitat(
altitudes = AL.SPAN(AL.OVERBURDEN, AL.HILLS),
location = LO.CAVE,
group = GR.SOLO,
scarcity = SC.UNCOMMON
)
),
MobPlacement(Mob("chameleon", "cold_sweat:chameleon"),
Habitat(
altitudes = AL.span(AL.DUNES, AL.UPLANDS),
biomeFilters = BF([HE.TROPICAL, HU.WET, [FL.CANOPY, FL.FOREST]]),
seasons = SE.WET,
groups = GR.merge(GR.SOLO, GR.FAMILY),
scarcity = SC.COMMON,
).derive(
seasons = SE.DRY, scarcity = SC.UNCOMMON,
).derive(
biomeFilters = BF([HE.TROPICAL, HU.WET, FL.CLEARING]),
seasons = SE.WET,
scarcity = SC.UNCOMMON
).derive(
seasons = SE.DRY, scarcity = SC.SPARSE,
)
),
MobPlacement(Mob("chicken", "minecraft:chicken")
Habitat(
altitudes = AL.span(AL.LOWLANDS, AL.UPLANDS),
biomeFilters = BF([HE.TROPICAL, HU.WET, FL.within(FL.CANOPY, FL.CLEARING)]),
seasons = SE.SUMMER,
groups = GR.TROUP,
scarcity.COMMON,
).derive(
seasons = SE.excluding(SE.SUMMER), scarcity = SC.UNCOMMON
)
),
MobPlacement(Mob("cod", "minecraft:cod")),
MobPlacement(Mob("commando", "immersiveengineering:commando")),
MobPlacement(Mob("cow", "minecraft:cow")),
MobPlacement(Mob("crab", "crabbersdelight:crab")),
MobPlacement(Mob("creeper", "minecraft:creeper")),
MobPlacement(Mob("dolphin", "minecraft:dolphin")),
MobPlacement(Mob("donkey", "minecraft:donkey")),
MobPlacement(Mob("drowned", "minecraft:drowned")),
MobPlacement(Mob("enderman", "minecraft:enderman")),
MobPlacement(Mob("evoker", "minecraft:evoker")),
MobPlacement(Mob("fox", "minecraft:fox")),
MobPlacement(Mob("frog", "minecraft:frog")),
MobPlacement(Mob("fusilier", "immersiveengineering:fusilier")),
MobPlacement(Mob("glow_squid", "minecraft:glow_squid")),
MobPlacement(Mob("goat", "minecraft:goat")),
MobPlacement(Mob("hoglin", "minecraft:hoglin")),
MobPlacement(Mob("horse", "minecraft:horse")),
MobPlacement(Mob("husk", "minecraft:husk")),
MobPlacement(Mob("llama", "minecraft:llama")),
MobPlacement(Mob("magma_cube", "minecraft:magma_cube")),
MobPlacement(Mob("mooshroom", "minecraft:mooshroom")),
MobPlacement(Mob("mule", "minecraft:mule")),
MobPlacement(Mob("ocelot", "minecraft:ocelot")),
MobPlacement(Mob("panda", "minecraft:panda")),
MobPlacement(Mob("parrot", "minecraft:parrot")),
MobPlacement(Mob("pig", "minecraft:pig")),
MobPlacement(Mob("pillager", "minecraft:pillager")),
MobPlacement(Mob("polar_bear", "minecraft:polar_bear")),
MobPlacement(Mob("pufferfish", "minecraft:pufferfish")),
MobPlacement(Mob("rabbit", "minecraft:rabbit")),
MobPlacement(Mob("raccoon", "animalplus:raccoon")),
MobPlacement(Mob("ravager", "minecraft:ravager")),
MobPlacement(Mob("red_panda", "animalplus:red_panda")),
MobPlacement(Mob("salmon", "minecraft:salmon")),
MobPlacement(Mob("sheep", "minecraft:sheep")),
MobPlacement(Mob("skeleton", "minecraft:skeleton")),
MobPlacement(Mob("slime", "minecraft:slime")),
MobPlacement(Mob("spider", "minecraft:spider")),
MobPlacement(Mob("squid", "minecraft:squid")),
MobPlacement(Mob("tropical_fish", "minecraft:tropical_fish")),
MobPlacement(Mob("turtle", "minecraft:turtle")),
MobPlacement(Mob("vex", "minecraft:vex")),
MobPlacement(Mob("villager", "minecraft:villager")),
MobPlacement(Mob("vindicator", "minecraft:vindicator")),
MobPlacement(Mob("wandering_trader", "minecraft:wandering_trader")),
MobPlacement(Mob("warden", "minecraft:warden")),
MobPlacement(Mob("witch", "minecraft:witch")),
MobPlacement(Mob("wither_skeleton", "minecraft:wither_skeleton")),
MobPlacement(Mob("wither", "minecraft:wither")),
MobPlacement(Mob("wolf", "minecraft:wolf")),
MobPlacement(Mob("zoglin", "minecraft:zoglin")),
MobPlacement(Mob("zombie_villager", "minecraft:zombie_villager")),
MobPlacement(Mob("zombie", "minecraft:zombie")),
])

Some files were not shown because too many files have changed in this diff Show More