ywatds/nodedb.lisp

41 lines
1.6 KiB
Common Lisp

(defpackage :nodedb
(:nicknames :ndb)
(:use :cl)
(:export :import-data :loopdb))
(in-package :ndb)
(defmacro loopdb ((db pos name param2) &body body)
(alexandria:with-gensyms (nodes names k v id)
(alexandria:once-only
(db)
`(loop with ,names = (car ,db) and ,nodes = (cdr ,db)
for ,k being the hash-keys of ,nodes using (hash-value ,v)
for ,id = (ash ,v -2)
for ,pos = ,k and ,name = (gethash ,id ,names) and ,param2 = (mod ,v 4) ,@body))))
;; written based on https://gigamonkeys.com/book/practical-parsing-binary-files.html
(defun import-data (fn)
(with-open-file (stream fn :element-type '(unsigned-byte 8))
(labels ((read-u8 () (read-byte stream nil nil))
(read-u16 () (let ((msb (read-u8)) (lsb (read-u8)))
(if (and msb lsb) (+ (* 256 msb) lsb))))
(read-int () (let ((i (read-u16))) (if i (- i 32768))))
(read-ln ()
(with-output-to-string (s)
(loop for c = (read-u8) while c for char = (code-char c)
until (char= char #\Newline) do (write-char char s))))
(read-node-entry ()
(let ((x (read-int)) (y (read-int)) (z (read-int)) (v (read-int)))
(if (and x y z v) (cons (aux:make-v3d :x x :y y :z z) v))))
(validp (ent nodelist)
(and ent (gethash (ash (cdr ent) -2) nodelist))))
(assert (= (read-u8) 1))
(let ((nodelist (make-hash-table :test #'equal))
(nodes (make-hash-table :test #'equalp)))
(loop repeat (read-int)
for id = (read-int) for name = (read-ln)
do (setf (gethash id nodelist) name))
(loop for ent = (read-node-entry) while (validp ent nodelist)
do (setf (gethash (car ent) nodes) (cdr ent)))
(cons nodelist nodes)))))