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
+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"