예제 #1
0
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
}
예제 #2
0
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
}