aboutsummaryrefslogtreecommitdiffstats
path: root/Lisp/moxie/events.lisp
blob: 88afb718668e9bdd3220b6ddb75dcf0767ebdd0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(in-package :moxie)

(defgeneric moxie-event-handler (event &rest args)
  (:documentation "Handle EVENT (w/ ARGS)."))

(defmethod moxie-event-handler ((event (eql :world-event)) &rest args)
  (apply #'world-event args))

(defmethod moxie-event-handler ((event (eql :eval)) &rest args)
  (do* ((f args (cdr f))
        (form (car f) (car f)))
       ((null f))
    (case form
      (:r (let ((restarts (compute-restarts))
                (num (cadr f)))
            (if (and (integerp num)
                     (> num 0) (<= num (length restarts)))
                (progn
                  (setf f (cdr f))
                  (invoke-restart (elt restarts (1- num))))
                (print-restarts restarts))))
      ((:? :h :help) (format t "~A~%" *repl-help*))
      (t (let (values)
           (setq - form)
           (setq values (multiple-value-list (eval -)))
           (setq /// // // / / values *** ** ** * * (car /))
           (send-command :repl-result `(:values ,@values))))))
  (send-command :repl-result `(:prompt ,(repl-prompt))))

(defmethod world-event-handler ((event (eql :close-world)) &rest args)
  (declare (ignore args))
  (close-world))

(defmethod world-event-handler ((event (eql :connect-world)) &rest args)
  (declare (ignore args))
  (world-connect))

(defmethod world-event-handler ((event (eql :disconnect-world)) &rest args)
  (declare (ignore args))
  (world-disconnect))

(defmethod world-event-handler ((event (eql :load-world)) &rest args)
  (format t "world-event-handler :load-world ~S~%" args)
  (apply #'load-world-state *world* args))

(defmethod world-event-handler ((event (eql :save-world)) &rest args)
  (apply #'save-world-state *world* args))

(defmethod world-event-handler ((event (eql :setting-changed)) &rest args)
  (let* ((form (car args))
         (key (car form))
         (val (cadr form))
         (old-val (world-var key)))
    (unless (eql old-val val)
      (format t "DEBUG: changing setting ~S: ~S -> ~S.~%" key old-val val)
      (setf (world-var key) val)
      (format t "DEBUG: running hook.~%")
      (run-hook :setting-changed-hook (list key val old-val))
      (format t "DEBUG: hook finished.~%"))))

(defmethod world-event-handler ((event (eql :input-from-client-hook)) &rest args)
  (send-to-mux *world* (or (run-hook event (car args)) (car args))))

(defmethod load-world-state ((world world) &key path &allow-other-keys)
  (format t "load-world-state ~S ~S~%" world path)
  (with-open-file (s (or path (world-save-path world)))
    (awhen (aand (read s) (parse-world-version-1 it))
      (setf (world-vars world) it)
      (setf (world-save-path world) path)
      (let ((*world* world))
        (run-hook :world-loaded-hook)))))

(defmethod save-world-state ((world world) &key path as-copy &allow-other-keys)
  (with-open-file (s (or path (world-save-path world))
                     :direction :output :if-exists :supersede
                     :if-does-not-exist :create)
    (prin1 (write-world-version-1) s))
  (unless as-copy
    (setf (world-save-path world) path))
  (let ((*world* world))
    (run-hook :world-saved-hook)))

(defun parse-world-version-1 (form)
  "Parses a world definition in the form '(:KEY value), returning an ALIST."
  (when (evenp (length form))
    (labels ((keyvalue-to-alist (form &optional (accumulator nil))
               (if (null form)
                   accumulator
                   (keyvalue-to-alist (cddr form)
                                      (cons (cons (car form) (cadr form)) accumulator)))))
      (keyvalue-to-alist form))))

(defun write-world-version-1 (&optional (world *world*))
  "Writes out a FORM of '(:KEY1 value1 :KEY2 value2) from WORLD."
  (labels ((alist-to-keyvalue (form &optional (accumulator nil))
             (if (null form)
                 accumulator
                 (alist-to-keyvalue (cdr form)
                                    (cons (caar form) (cons (cdar form) accumulator))))))
    (alist-to-keyvalue (world-vars world))))