|
|
@@ -7,10 +7,12 @@
|
|
|
(defvar *watcher* nil "Log watcher thread if set")
|
|
|
(defvar *lock-game* (bordeaux-threads:make-recursive-lock "Q3A lock"))
|
|
|
|
|
|
+(defvar *first-read*)
|
|
|
(defun watch-file (filespec thunk &optional (start-at :end))
|
|
|
"This will block forever, waiting for new data"
|
|
|
(with-open-file (s filespec)
|
|
|
(file-position s start-at)
|
|
|
+ (setf *first-read* t)
|
|
|
(loop
|
|
|
with last-pos = (file-position s)
|
|
|
for line = (read-line s nil nil)
|
|
|
@@ -19,6 +21,7 @@
|
|
|
(error (e) (log:error e)))
|
|
|
(setf last-pos (file-position s)))
|
|
|
else do (progn
|
|
|
+ (setf *first-read* nil)
|
|
|
(sleep 0.1)
|
|
|
(when (> last-pos (file-length s))
|
|
|
(file-position s :start))))))
|
|
|
@@ -61,18 +64,19 @@
|
|
|
(let ((ranks (get-rankings)))
|
|
|
(if ranks
|
|
|
(format nil (if (game-is-active game)
|
|
|
- "[Q3] Match *~A* is on for ~A~%~{~A~^~%~}"
|
|
|
- "[Q3] Match *~A* has ended after ~A~%~{~A~^~%~}")
|
|
|
+ "[[Q3]] Match *~A* is on for ~A~%~{~A~^~%~}"
|
|
|
+ "[[Q3]] Match *~A* has ended after ~A~%~{~A~^~%~}")
|
|
|
(map-name) (game-last-time *game*)
|
|
|
(loop for (score . player) in ranks
|
|
|
collect (format nil "*~A* ~A" score (player-name player))))
|
|
|
- "[Q3] War awaits")))
|
|
|
+ "[[Q3]] War awaits")))
|
|
|
|
|
|
(defun say (fmt &rest args)
|
|
|
(let ((words (apply #'format nil fmt args)))
|
|
|
(write words) (terpri)
|
|
|
- (dolist (*chat-id* (lists-get :q3a))
|
|
|
- (bot-send-message words))))
|
|
|
+ (unless *first-read*
|
|
|
+ (dolist (*chat-id* (lists-get :q3a))
|
|
|
+ (bot-send-message words :parse-mode "Markdown")))))
|
|
|
|
|
|
(defun weapon (kill)
|
|
|
(kill-how kill))
|
|
|
@@ -81,23 +85,24 @@
|
|
|
|
|
|
(defun on-begin (player)
|
|
|
(unless (player-began player)
|
|
|
- (say "[Q3] ~A joined the server on ~A" (player-name player) (map-name))))
|
|
|
+ (say "[[Q3]] ~A joined the server on ~A" (player-name player) (map-name))))
|
|
|
|
|
|
;; (defun on-kill (player kill)
|
|
|
;; (let* ((name (player-name player))
|
|
|
;; (who (kill-whom kill)))
|
|
|
;; (if (suicidep player kill)
|
|
|
-;; (say "[Q3] ~A suicides with score ~A" name (player-score player))
|
|
|
-;; (say "[Q3] ~A frags ~A with score ~A" name (player-name who) (player-score player)))))
|
|
|
+;; (say "[[Q3]] ~A suicides with score ~A" name (player-score player))
|
|
|
+;; (say "[[Q3]] ~A frags ~A with score ~A" name (player-name who) (player-score player)))))
|
|
|
(defun on-kill (player kill)
|
|
|
(declare (ignorable player kill)))
|
|
|
|
|
|
(defun on-disconnect (player)
|
|
|
(when (player-began player)
|
|
|
- (say "[Q3] ~A has left the match with ~A frags" (player-name player) (player-score player))))
|
|
|
+ (say "[[Q3]] ~A has left the match with ~A frags" (player-name player) (player-score player))))
|
|
|
|
|
|
(defun on-exit ()
|
|
|
- (say (game-status)))
|
|
|
+ (when (get-rankings)
|
|
|
+ (say (game-status))))
|
|
|
|
|
|
(defun process-log (line)
|
|
|
(bordeaux-threads:with-recursive-lock-held (*lock-game*)
|
|
|
@@ -148,7 +153,8 @@
|
|
|
(bt:with-recursive-lock-held (*lock-game*)
|
|
|
(if (lists-get :q3a)
|
|
|
(unless *watcher*
|
|
|
- (setf *watcher* (bt:make-thread (lambda () (watch-file *server-log* #'process-log)) :name "q3a watch")))
|
|
|
+ (setf *watcher* (bt:make-thread (lambda () (watch-file *server-log* #'process-log :start))
|
|
|
+ :name "q3a watch")))
|
|
|
(when *watcher*
|
|
|
(bt:destroy-thread *watcher*)
|
|
|
(setf *watcher* nil))))
|
|
|
@@ -157,10 +163,10 @@
|
|
|
(defun handle-set-watch (enable)
|
|
|
(lists-set-entry :q3a *chat-id* enable)
|
|
|
(ensure-watcher)
|
|
|
- (bot-send-message (if enable "[Q3] Шлём войну!" "[Q3] Миру-мир!")))
|
|
|
+ (bot-send-message (if enable "[[Q3]] Шлём войну!" "[[Q3]] Миру-мир!")))
|
|
|
|
|
|
(defun handle-active ()
|
|
|
- (bot-send-message (game-status)))
|
|
|
+ (bot-send-message (game-status) :parse-mode "Markdown"))
|
|
|
|
|
|
(def-message-cmd-handler handle-cmd-q3a (:q3a)
|
|
|
(cond
|