Created
May 7, 2011 02:56
-
-
Save jb55/960155 to your computer and use it in GitHub Desktop.
minecraft stuff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {EventEmitter} = require 'events' | |
| mmap = require 'mmap' | |
| path = require 'path' | |
| fs = require 'fs' | |
| # Used for accessing blocks | |
| class Blocks | |
| @chunks = {} | |
| # Blocks takes a path to a world directory. | |
| constructor: (@path, @log, @options) -> | |
| @options or= {} | |
| @chunkLoader = @options.loader or @loadChunk | |
| # Load all of our chunks by mapping to virtual memory. This implements | |
| # on-demand chunk loading, loading blocks into RAM only when we access them. | |
| load: (cb) -> | |
| chunkFiles @path, (err, files) -> | |
| cb(err) if err | |
| n_chunks = files.length | |
| ev = new EventEmitter | |
| chunks = [] | |
| n = 0 | |
| # Pass each chunk file into our chunk loader | |
| # This will emit a load event when a chunk finishes loading | |
| @chunkLoader(file, ev, @log) for file in files | |
| # When a chunk has finished loading, add it to our chunk list | |
| ev.on 'load', (err, chunk) -> | |
| n++ | |
| return @log.error("Chunk failed to load: #{err.message}") if err | |
| return @log.error("Too many chunk load events emitted") if n > n_chunks | |
| @log.info("Loaded chunk #{chunk.x}, #{chunk.y}") | |
| chunks.push chunk | |
| cb(chunks) if n is n_chunks | |
| # Get a specific chunk from an x, y coordinate | |
| getChunk: (x, y) -> | |
| # Get a specific block from an x, y coordinate. Returns an integer | |
| getBlock: (x, y, z, cb) -> | |
| # Load a chunk in a non-lazy manner | |
| @loadChunkStrict: @loadChunk | |
| # Load a chunk using the default method, mmap/demand paging | |
| @loadChunk: (file, ev) -> | |
| fs.stat file, (err, stats) -> | |
| return ev.emit('load', err) if err | |
| size = stats.size | |
| fs.open file, 'r', (err, fd) -> | |
| return ev.emit('load', err) if err | |
| # Parse the region numbers out of the chunk filename | |
| filename = path.basename file | |
| [_, x, y, _] = filename.split('.') | |
| # mmap our chunk into virtual memory, the node Buffer object uses this | |
| # underlying mapping when reading and writing to it | |
| buffer = mmap.map(size, mmap.PROT_READ, mmap.MAP_PRIVATE, fd, 0) | |
| chunk = { x: x, y: y, file: file, buffer: buffer } | |
| ev.emit('load', err, chunk) | |
| # Returns true if .mcr is in a filename | |
| @isMcrFile: (f) -> path.basename(f).indexOf(".mcr") != -1 | |
| # Get a list of chunks from a path | |
| @chunkFiles: (p, cb) -> | |
| region = path.join p 'region' | |
| # If there's a region directory in the current path, use that instead | |
| path.exists region, (regionExists) -> | |
| p = region if regionExists | |
| fs.readdir p, (err, files) -> | |
| cb(err) if err | |
| cb(null, f for f in files when isMcrFile(f) is true) | |
| module.exports = Blocks |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment