(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) do (progn ,@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)))))