summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/rudel/obby/rudel-obby-state.el
blob: a190967c62aa09211b1eb5991710ef4809bbbc5a (plain) (blame)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
;;; rudel-obby-state.el --- Base class for states used in the obby backend
;;
;; Copyright (C) 2009 Jan Moringen
;;
;; Author: Jan Moringen <scymtym@users.sourceforge.net>
;; Keywords: Rudel, obby, state machine
;; X-RCS: $Id:$
;;
;; This file is part of Rudel.
;;
;; Rudel is free software: you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; Rudel is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Rudel. If not, see <http://www.gnu.org/licenses>.


;;; Commentary:
;;
;; This file contains a base class for finite state machine states
;; used in the obby backend.


;;; History:
;;
;; 0.1 - Initial revision


;;; Code:
;;

(require 'eieio)

(require 'rudel-util)
(require 'rudel-state-machine)

(require 'rudel-obby-util)


;;; Class rudel-obby-state
;;

(defclass rudel-obby-state (rudel-state)
  ((connection :initarg :connection
	       :type    rudel-obby-socket-owner
	       :documentation
	       "Connection object that uses the state."))
  "Base class for state classes used in the obby backend."
  :abstract t)

(defmethod rudel-enter ((this rudel-obby-state))
  "Default behavior is doing nothing when entering a state."
  nil)

(defmethod rudel-leave ((this rudel-obby-state))
  "Default behavior is doing nothing when leaving a state.")

(defmethod rudel-accept ((this rudel-obby-state) message)
  "Dispatch to appropriate handler based on MESSAGE.
Display a warning if no such handler is found."
  ;; Try to dispatch to the correct message handler. If there is none,
  ;; warn.
  (let ((name      (car message))
	(arguments (cdr message)))
    (condition-case error
	;; Try to dispatch
	(rudel-dispatch this "rudel-obby/" name arguments)
      ;; Warn if we failed to locate or execute the method. Return nil
      ;; in this case, so we remain in the current state.
      (rudel-dispatch-error
       (progn
	 (display-warning
	  '(rudel obby)
	  (format "%s: no method (%s: %s): `%s/%s'; arguments: %s"
		  (object-print this) (car error) (cdr error)
		  "rudel-obby" name arguments)
	  :debug)
	 nil))))
  )

(defmethod rudel-send ((this rudel-obby-state) &rest args)
  "Send ARGS through the connection associated with THIS."
  (with-slots (connection) this
    (apply #'rudel-send connection args)))


;;; Class rudel-obby-client-connection-state
;;

(defclass rudel-obby-client-connection-state (rudel-obby-state)
  ()
  "Base class for state classes used by obby client connections."
  :abstract t)

(defmethod rudel-obby/net6_ping ((this rudel-obby-client-connection-state))
  "Handle net6 'ping' message."
  (rudel-send this "net6_pong")
  nil)


;;; Class rudel-obby-server-connection-state
;;

(defclass rudel-obby-server-connection-state (rudel-obby-state)
  ()
  "Base class for server connection states."
  :abstract t)

(defmethod rudel-broadcast ((this rudel-obby-server-connection-state)
			    receivers name &rest arguments)
  "Broadcast message NAME with arguments ARGUMENTS to RECEIVERS."
  (with-slots (connection) this
    (apply #'rudel-broadcast connection receivers name arguments)))


;;; Class rudel-obby-document-handler
;;

(defclass rudel-obby-document-handler ()
  ()
  "Mixin class that provides ability to process submessages of
  obby 'document' messages.")

(defmethod rudel-obby/obby_document
  ((this rudel-obby-document-handler) doc-id action &rest arguments)
  "Handle obby 'document' message family."
  ;; Try to dispatch to the correct message handler. If there is none,
  ;; warn.
  (with-parsed-arguments ((doc-id document-id))
    ;; Locate the document based on owner id and document id.
    (let ((document (with-slots (connection) this
		      (with-slots (session) connection
			(rudel-find-document session doc-id
					     #'equal #'rudel-both-ids)))))
      (if document
	  (condition-case error
	      ;; Try to dispatch
	      (rudel-dispatch this "rudel-obby/obby_document/" action
			      (cons document arguments))
	    ;; Warn if we failed to locate or execute the
	    ;; method. Return nil in this case, so we remain in the
	    ;; current state.
	    (rudel-dispatch-error
	     (progn
	       (display-warning
		'(rudel obby)
		(format "%s: no method (%s: %s): `%s:%s'; arguments: %s"
			(object-print this) (car error) (cdr error)
			"rudel-obby/obby_document/" action arguments)
		:debug)
	       nil)))
	;; If we did not find the document, warn.
	(progn
	  (display-warning
	   '(rudel obby)
	   (format "Document not found: %s" doc-id)
	   :debug)
	  nil))))
  )

(provide 'rudel-obby-state)
;;; rudel-obby-state.el ends here