(ns advent.steam (:require [play-clj.core :refer :all] [clojure.edn :as edn] [clojure.tools.logging :as log] ) (:import [java.nio ByteBuffer CharBuffer] [java.io ByteArrayOutputStream] [com.badlogic.gdx.graphics Pixmap PixmapIO$PNG] [com.badlogic.gdx.files FileHandle] )) (def has-steam? (try (import '[com.codedisaster.steamworks SteamUserStats SteamUserStatsCallback SteamAPI SteamRemoteStorage]) true (catch Exception e false))) (def is-app-store? (System/getProperty "app-store")) (defmacro steamify [steam-version & [regular-version]] (if has-steam? `(if (and has-steam? (not (System/getProperty "no-steam"))) ~steam-version ~regular-version) regular-version)) (defn init [] (steamify (if (SteamAPI/init) (log/info "Steam initialized") (do (log/info "Steam not initialized") (def has-steam? false))))) (defn update [] (steamify (when (SteamAPI/isSteamRunning) (SteamAPI/runCallbacks)))) (if has-steam? (eval '(do (defn achievement-fn [f achievement] (steamify (let [stats (atom nil)] (log/info "Getting stats...") (reset! stats (SteamUserStats. (reify SteamUserStatsCallback (onUserStatsReceived [_ _ _ _] (f @stats achievement) ) (onUserStatsStored [_ _ _]) (onUserAchievementStored [_ _ _ _ _ _])))) (.requestCurrentStats @stats)))) (def set-achievement (partial achievement-fn (fn [^SteamUserStats stats ^String achievement] (log/info "Setting achievement" achievement) (.setAchievement stats achievement) (.storeStats stats) (log/info "Done setting achievement" achievement)))) (def clear-achievement (partial achievement-fn (fn [^SteamUserStats stats ^String achievement] (log/info "Clearing achievement" achievement) (.clearAchievement stats achievement) (.storeStats stats) (log/info "Done clearing achievement" achievement))))) ) (do (defn set-achievement [achievement]) (defn clear-achievement [achievement]))) (def all-achievements ["PARDON" "EX_CON" "PRO_WRESTLER" "SHEEP_HORDER" "SAFE_AND_SOUND" "DESTINY" "WISE_UP" "BLOODCLOT" "KITTY_KISS"]) (defn clear-all-achievements [] (doall (map clear-achievement all-achievements))) (defn get-bytes [filename] (steamify (let [rs (SteamRemoteStorage. nil) len (.getFileSize rs filename) bb (ByteBuffer/allocateDirect len) bytes (make-array Byte/TYPE len)] (.fileRead rs filename bb len) (.get bb bytes) bytes) (.readBytes (if is-app-store? (files! :external filename) (files! :local filename))))) (defn write-bytes [filename bytes] (steamify (let [rs (SteamRemoteStorage. nil) bb (ByteBuffer/allocateDirect (* 2 (count bytes)))] (-> bb (.put bytes) ) (.fileWrite rs filename bb (* 2 (count bytes)))) (let [f (if is-app-store? (files! :external filename) (files! :local filename))] (.writeBytes f bytes false)))) (defn list-edn-files [] (steamify (let [rs (SteamRemoteStorage. nil)] (for [i (range (.getFileCount rs)) :let [n (.getFileNameAndSize rs i (make-array Integer/TYPE 1))] :when (.endsWith n ".edn")] n)) (if is-app-store? (for [save-file (.list (files! :external "saves/") ".edn")] (str "saves/" (.name ^FileHandle save-file))) (for [save-file (.list (files! :local "saves/") ".edn")] (str "saves/" (.name ^FileHandle save-file)))))) (defn save-screenshot [^Pixmap pm ^String filename] (steamify (let [rs (SteamRemoteStorage. nil) png (PixmapIO$PNG. (* (.getWidth pm) (.getHeight pm) 1.5)) baos (ByteArrayOutputStream. (* (.getWidth pm) (.getHeight pm) 1.5)) _ (.write png baos pm) bytes (.toByteArray baos) bb (ByteBuffer/allocateDirect (count bytes))] (.put bb bytes) (.fileWrite rs filename bb (count bytes))) (let [f (if is-app-store? (files! :external filename) (files! :local filename)) png (PixmapIO$PNG. (* (.getWidth pm) (.getHeight pm) 1.5))] (.write png f pm) (.dispose png)))) (defn delete-file [filename] (steamify (.fileDelete (SteamRemoteStorage. nil) filename) (.delete (if is-app-store? (files! :external filename) (files! :local filename))))) (defn save-screenshot-file-name [name] (steamify (str "screenshot-" (clojure.core/name name) ".png" ) (str "saves/screenshot-" (clojure.core/name name) ".png" ))) (defn save-file-name [id] (steamify (str id ".edn") (str "saves/" id ".edn")))