func LoadBlockDefs(reader io.Reader) (blocks BlockTypeList, err os.Error) { blocksStr := make(map[string]blockDef) decoder := json.NewDecoder(reader) err = decoder.Decode(&blocksStr) // Find the max block ID so we allocate the correct amount of memory. Also // range check the IDs. maxId := 0 for idStr := range blocksStr { var id int id, err = strconv.Atoi(idStr) if err != nil { return } if id < types.BlockIdMin || id > types.BlockIdMax { err = os.NewError(fmt.Sprintf( "Encountered block type with ID %d which is outside the range"+ "%d <= N <= %d", id, types.BlockIdMin, types.BlockIdMax)) return } if id > maxId { maxId = id } } // Convert map string keys to ints. blocks = make(BlockTypeList, maxId+1) for idStr, blockDef := range blocksStr { var id int id, _ = strconv.Atoi(idStr) if blocks[id].defined { err = os.NewError(fmt.Sprintf( "Block ID %d defined more than once.", id)) } var block *BlockType block, err = blockDef.LoadBlockType() if err != nil { return } block.id = types.BlockId(id) block.defined = true blocks[id] = *block } // Put VoidAspect in any undefined blocks rather than leave it nil, and also // set id on each block type. for id := range blocks { block := &blocks[id] block.id = types.BlockId(id) if !block.defined { void := makeVoidAspect() block.Aspect = void void.setAttrs(&block.BlockAttrs) } } return }
func (aspect *SaplingAspect) makeTree(instance *BlockInstance) bool { loc := instance.SubLoc minheight := 3 maxheight := 6 height := minheight + rand.Intn(maxheight-minheight) maxy := loc.Y + types.SubChunkCoord(height) for y := loc.Y; y < maxy; y++ { loc.Y = y index, ok := loc.BlockIndex() if !ok { // TODO: Can't place a block outside chunk boundaries log.Printf("Couldn't place a tree block (%v,%v,%v)", loc.X, loc.Y, loc.Z) } else { instance.Chunk.SetBlockByIndex(index, types.BlockId(17), byte(0)) } } // Store the location at the top block of the tree treex, treey, treez := int(loc.X), int(loc.Y), int(loc.Z) cradius := height / 2 // Start one block above the tree and move down for y := treey + 1; y >= treey-1; y-- { var radius int // Slightly round out the canopy if y > treey { radius = cradius - 1 } else if y == treey { radius = cradius } else if y < treey { radius = cradius - 1 } for x := treex - radius; x <= treex+radius; x++ { for z := treez - radius; z <= treez+radius; z++ { if y > treey || x != treex || z != treez { loc.X = types.SubChunkCoord(x) loc.Y = types.SubChunkCoord(y) loc.Z = types.SubChunkCoord(z) index, ok := loc.BlockIndex() if !ok { // TODO: Can't place a block outside chunk boundaries log.Printf("Couldn't place a leaf block (%v,%v,%v)", loc.X, loc.Y, loc.Z) } else { instance.Chunk.SetBlockByIndex(index, types.BlockId(18), byte(0)) } } } } } return true }