Skip to content

Commit

Permalink
Implement book placement system
Browse files Browse the repository at this point in the history
  • Loading branch information
Niels-NTG committed Jun 8, 2024
1 parent 428708e commit d3db8af
Show file tree
Hide file tree
Showing 11 changed files with 482 additions and 67 deletions.
35 changes: 33 additions & 2 deletions LibraryFloor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
class LibraryFloor:

allStateSpace: Dict[ivec3, OrderedSet[StructureRotation]]
allLockedTiles: dict[ivec3, bool]
allLockedTiles: Dict[ivec3, bool]
allDefaultAdjacencies: Dict[str, StructureAdjacency]
subGridVolumes: List[Box]
volumeGrid: Box
volumeRotation: int
placedTiles: Dict[ivec3, Structure]
centralTile: ivec3

def __init__(
self,
Expand Down Expand Up @@ -76,6 +78,8 @@ def __init__(
onResolve=self.onResolve,
)

self.placedTiles = dict()

self.buildStructure(volume.offset)

def reinitWFC(self, wfc: WaveFunctionCollapse):
Expand Down Expand Up @@ -219,7 +223,7 @@ def onResolve(self, wfc: WaveFunctionCollapse):

@staticmethod
def removeOrphanedBuildings(wfc: WaveFunctionCollapse):
buildings = wfc.lockedTiles
buildings = wfc.foundBuildings
print(f'Found {len(buildings)} distinct buildings, removing orphaned buildings…')
largestBuilding = max(buildings, key=lambda x: len(x))
for building in buildings:
Expand All @@ -244,6 +248,7 @@ def buildStructure(self, buildVolumeOffset: ivec3 = ivec3(0, 0, 0)):
print('Placing tiles…')
for building in self.getCollapsedState(buildVolumeOffset=buildVolumeOffset):
building.place()
self.placedTiles[building.tile] = building
# Build central atrium/staircase
atriumCoreFolder = globals.structureFolders['central_core']
atriumCoreBuildingInstance: Structure = atriumCoreFolder.structureClass(
Expand All @@ -252,3 +257,29 @@ def buildStructure(self, buildVolumeOffset: ivec3 = ivec3(0, 0, 0)):
offset=buildVolumeOffset,
)
atriumCoreBuildingInstance.place()
self.placedTiles[atriumCoreBuildingInstance.tile] = atriumCoreBuildingInstance
self.centralTile = atriumCoreBuildingInstance.tile

@property
def bookCapacity(self) -> int:
capacity = 0
for building in self.placedTiles.values():
capacity += building.bookCapacity
return capacity

def placeBooks(self, books: List[Dict]):
tilesFilledWithBooks: List[ivec3] = []
for index, building in self.placedTiles.items():
if building.bookCapacity > 0:
tilesFilledWithBooks.append(index)
for index in tilesFilledWithBooks:
building = self.placedTiles[index]

bookCapacity = building.bookCapacity
booksForTile = books[:bookCapacity]

building.addBooks(booksForTile)

del books[:bookCapacity]

building.doPostProcessingSteps()
57 changes: 44 additions & 13 deletions StructureBase.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from __future__ import annotations

import functools
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, Dict, List

import bookTools
import vectorTools
from gdpc.src.gdpc import Block, block_state_tools

if TYPE_CHECKING:
from StructureFolder import StructureFolder
Expand All @@ -18,13 +22,14 @@

class Structure:

decorationStructureFiles: dict[str, StructureFile]
transitionStructureFiles: dict[str, StructureFile]
decorationStructureFiles: Dict[str, StructureFile]
transitionStructureFiles: Dict[str, StructureFile]
structureFile: StructureFile

customProperties: dict[str, Any]
customProperties: Dict[str, Any]

preProcessingSteps: list[worldTools.PlacementInstruction]
preProcessingSteps: Dict[ivec3, Block]
postProcessingSteps: Dict[ivec3, Block]

adjecencies: StructureAdjacency

Expand All @@ -33,6 +38,8 @@ class Structure:

weight: float = 0.5

bookShelves: Dict[ivec3, str] = dict()

def __init__(
self,
structureFolder: StructureFolder,
Expand All @@ -47,7 +54,8 @@ def __init__(

self.customProperties = dict()

self.preProcessingSteps = []
self.preProcessingSteps = dict()
self.postProcessingSteps = dict()

self.rotation = withRotation
self.tile = tile
Expand Down Expand Up @@ -116,7 +124,7 @@ def isSameType(self, otherStructure: Structure = None) -> bool:
return False

def doPreProcessingSteps(self):
self.preProcessingSteps.extend(worldTools.getTreeCuttingInstructions(self.rectInWorldSpace))
self.preProcessingSteps.update(worldTools.getTreeCuttingInstructions(self.rectInWorldSpace))

for preProcessingStep in self.preProcessingSteps:
globals.editor.placeBlockGlobal(
Expand All @@ -131,15 +139,38 @@ def place(self):
pivot=self.structureFile.centerPivot
)

@staticmethod
def doPostProcessingSteps():
postProcessingSteps: list[worldTools.PlacementInstruction] = []
for postProcessingStep in postProcessingSteps:
def doPostProcessingSteps(self):
for index, block in self.postProcessingSteps.items():
print(f'Run post processing step {index} {block}')
pos = vectorTools.rotatePointAroundOrigin3D(self.box.center, index, self.rotation)
globals.editor.placeBlockGlobal(
position=postProcessingStep.position,
block=postProcessingStep.block,
position=pos + self.boxInWorldSpace.offset,
block=block,
)

@property
def bookCapacity(self) -> int:
# The minecraft:chiseled_bookshelf block has a capacity of 6 books.
return len(self.bookShelves) * 6

def addBooks(self, booksData: List[Dict]):
# TODO this function could be ran in seperate threads if needed.
bookShelfEntries: List[Dict] = []
bookShelfBlockPositions = self.bookShelves.copy()
for book in booksData:
bookShelfEntries.append(book)
if len(bookShelfEntries) == 6:
# Remove first entry from the list of bookShelvePositions
bookShelfPosition = list(bookShelfBlockPositions.keys())[0]
bookShelfRotation = bookShelfBlockPositions.pop(bookShelfPosition)

bookShelfBlock = bookTools.createBookShelfBlock(
block_state_tools.rotateFacing(bookShelfRotation, self.rotation)
)
bookShelfBlock = bookTools.fillBookShelf(bookShelfEntries, bookShelfBlock)
self.postProcessingSteps[bookShelfPosition] = bookShelfBlock
bookShelfEntries.clear()

def __eq__(self, other):
return hash(self) == hash(other)

Expand Down
36 changes: 16 additions & 20 deletions bookTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,24 @@ def writeBookData(data: Dict) -> str:
)


def createBookShelfBlock(facing: str) -> Block:
return Block(
id='minecraft:chiseled_bookshelf',
states={
'facing': facing,
},
)


def fillBookShelf(bookSources: List[Dict], block: Block) -> Block:
if len(bookSources) > 6:
print('Too many book sources provided at once!')
return block
shelfSNBT = '{Items: ['
for slowIndex in range(6):
book = writeBookData(bookSources[slowIndex])
shelfSNBT += f'{{Slot: {slowIndex}b, Count: 1b, id: "minecraft:written_book", tag: {book}}},'
for bookIndex in range(6):
book = writeBookData(bookSources[bookIndex])
shelfSNBT += f'{{Slot: {bookIndex}b, Count: 1b, id: "minecraft:written_book", tag: {book}}},'
block.states[f'slot_{bookIndex}_occupied'] = 'true'
shelfSNBT = shelfSNBT[:-1]
shelfSNBT += ']}'
block.data = shelfSNBT
Expand All @@ -207,18 +217,7 @@ def createMegaBookWall():
pos.y = pos.y + 1
pos.x = globals.buildarea.begin.x

bookShelfBlock = Block(
id='minecraft:chiseled_bookshelf',
states={
'facing': facing,
'slot_0_occupied': 'true',
'slot_1_occupied': 'true',
'slot_2_occupied': 'true',
'slot_3_occupied': 'true',
'slot_4_occupied': 'true',
'slot_5_occupied': 'true',
}
)
bookShelfBlock = createBookShelfBlock(facing)
bookshelfBlock = fillBookShelf(bookShelfEntries, bookShelfBlock)
globals.editor.placeBlockGlobal(block=bookshelfBlock, position=pos)
bookShelfEntries = []
Expand All @@ -239,7 +238,7 @@ def splitByCategory():
writeCategoryFile(line, primaryCategory, year)


def gatherBooksOfCategory(category: str = 'cs.') -> List[List[Dict]]:
def gatherBooksOfCategory(category: str = 'cs.') -> List[Dict]:
groupedBooks = []
startYear = 1980
endYear = datetime.today().year
Expand All @@ -251,8 +250,5 @@ def gatherBooksOfCategory(category: str = 'cs.') -> List[List[Dict]]:
for line in f:
bookGroup.append(json.loads(line))
bookGroup.sort(key=lambda x: primaryAuthor(x))
groupedBooks.append(bookGroup)
groupedBooks.extend(bookGroup)
return groupedBooks


gatheredBooks = gatherBooksOfCategory('cs.')
26 changes: 21 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os

from glm import ivec3
from termcolor import cprint

import bookTools
from LibraryFloor import LibraryFloor
import globals
from gdpc.src.gdpc import Box
Expand All @@ -10,22 +12,36 @@

globals.initialize()

volumeRotatiom = 3
for y in range(100, -70, -10):
computerScienceBooks = bookTools.gatherBooksOfCategory('cs.')
volumeRotatiom = 0
volumeY = 100
VOLUME_Y_SIZE = 10
floorNumber = 0
while volumeY > -70 and len(computerScienceBooks) > 0:
floorVolume = Box(
offset=ivec3(
globals.buildVolume.offset.x,
y,
volumeY,
globals.buildVolume.offset.z,
),
size=ivec3(
globals.buildVolume.size.x,
10,
VOLUME_Y_SIZE,
globals.buildVolume.size.z,
)
)
LibraryFloor(
libraryFloor = LibraryFloor(
volume=floorVolume,
volumeRotation=volumeRotatiom,
)

bookCapacity = libraryFloor.bookCapacity
cprint(f'Filling floor {floorNumber} with {bookCapacity} books', 'black', 'on_green')
booksForFloor = computerScienceBooks[-bookCapacity:]
libraryFloor.placeBooks(booksForFloor)

del computerScienceBooks[-bookCapacity:]

volumeY -= VOLUME_Y_SIZE
volumeRotatiom += 1
floorNumber -= 1
63 changes: 63 additions & 0 deletions structures/doha9/book_corner/book_corner.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,69 @@ class BookCorner(Structure):

weight = 0.2

bookShelves = {
ivec3(7, 5, 7): 'north',
ivec3(6, 5, 7): 'north',
ivec3(5, 5, 7): 'north',
ivec3(4, 5, 7): 'north',
ivec3(3, 5, 7): 'north',
ivec3(2, 5, 7): 'north',
ivec3(1, 5, 6): 'east',
ivec3(1, 5, 5): 'east',
ivec3(1, 5, 4): 'east',
ivec3(1, 5, 3): 'east',
ivec3(1, 5, 2): 'east',
ivec3(1, 5, 1): 'east',
ivec3(7, 4, 7): 'north',
ivec3(6, 4, 7): 'north',
ivec3(5, 4, 7): 'north',
ivec3(4, 4, 7): 'north',
ivec3(3, 4, 7): 'north',
ivec3(2, 4, 7): 'north',
ivec3(1, 4, 6): 'east',
ivec3(1, 4, 5): 'east',
ivec3(1, 4, 4): 'east',
ivec3(1, 4, 3): 'east',
ivec3(1, 4, 2): 'east',
ivec3(1, 4, 1): 'east',
ivec3(7, 3, 7): 'north',
ivec3(6, 3, 7): 'north',
ivec3(5, 3, 7): 'north',
ivec3(4, 3, 7): 'north',
ivec3(3, 3, 7): 'north',
ivec3(2, 3, 7): 'north',
ivec3(1, 3, 6): 'east',
ivec3(1, 3, 5): 'east',
ivec3(1, 3, 4): 'east',
ivec3(1, 3, 3): 'east',
ivec3(1, 3, 2): 'east',
ivec3(1, 3, 1): 'east',
ivec3(7, 2, 7): 'north',
ivec3(6, 2, 7): 'north',
ivec3(5, 2, 7): 'north',
ivec3(4, 2, 7): 'north',
ivec3(3, 2, 7): 'north',
ivec3(2, 2, 7): 'north',
ivec3(1, 2, 6): 'east',
ivec3(1, 2, 5): 'east',
ivec3(1, 2, 4): 'east',
ivec3(1, 2, 3): 'east',
ivec3(1, 2, 2): 'east',
ivec3(1, 2, 1): 'east',
ivec3(7, 1, 7): 'north',
ivec3(6, 1, 7): 'north',
ivec3(5, 1, 7): 'north',
ivec3(4, 1, 7): 'north',
ivec3(3, 1, 7): 'north',
ivec3(2, 1, 7): 'north',
ivec3(1, 1, 6): 'east',
ivec3(1, 1, 5): 'east',
ivec3(1, 1, 4): 'east',
ivec3(1, 1, 3): 'east',
ivec3(1, 1, 2): 'east',
ivec3(1, 1, 1): 'east',
}

def __init__(
self,
withRotation: int = 0,
Expand Down
Loading

0 comments on commit d3db8af

Please sign in to comment.