Updating my Minecraft command book using Emacs, TRAMP, and mcf.el
| minecraft, play, emacs
I wanted to see what else people have done in terms of combining
Minecraft and Emacs. It turns out that you can control Minecraft from
Emacs via mcf if you set enable-rcon=true
in your
server.properties
(also a good idea to set rcon.password
) and you
configure variables like mcf-rcon-password
on the Emacs side. It
needed a little tweaking to get it to connect to a remote server, so
I've submitted a pull request. Anyway, since Emacs can talk to
Minecraft and I can write sequences of Minecraft commands as
functions, I thought about turning my Minecraft command books into
something that I could update right from Emacs.
Creating my own datapack was pretty straightforward once I figured out
the directory structure. I needed to put functions in
<world-name>/datapacks/sachac/data/sachac/functions
. Inside
<world-name>/datapacks/sachac
, I created pack.mcmeta
with the
following contents:
{ "pack": { "pack_format": 10, "description": "sachac's tweaks" } }
Inside <world-name>/datapacks/sachac/data/sachac/functions
, I
created a command_book.mcfunction
file with the command to give me
the book. I updated my command book function to remove the /
from
the beginning.
I used /reload
to reload my Minecraft configuration and /datapack
list
to confirm that my datapack was loaded. Then /function
sachac:command_book
ran the function to give me the command book, so
that all worked out. I replaced the command in the command block with
the function call.
The next step was to update it directly from Emacs, including reloading. First, I needed a function to give me the filename of a function file.
(defun my-minecraft-datapack-function-file-name (world datapack-name function-name) "Return the filename for a mcfunction file given WORLD, DATAPACK-NAME, and FUNCTION-NAME." (seq-reduce (lambda (path subdir) (expand-file-name subdir path)) (list "datapacks" datapack-name "data" datapack-name "functions" (concat function-name ".mcfunction")) world))
I used C-c C-x p
(org-set-property
) to add a WORLD
property to
my Org subtree. For example, my snapshot world is at
/ssh:desktop:~/.minecraft/saves/Snapshot
. Then I can get the correct
value within the subtree by using org-entry-get-with-inheritance
.
This is how I wrote the command book function for my snapshot world:
#+begin_src emacs-lisp :var body=mc-snapshot :var team=mc-team :var quick=mc-quick :var effects=mc-effects :var items=mc-items :results silent (with-temp-file (my-minecraft-datapack-function-file-name (org-entry-get-with-inheritance "WORLD") "sachac" "command_book") (insert (my-minecraft-book "Commands 8.5" "Mom" (append team quick body effects items)))) (mcf-eval "reload") #+end_src
So now I can use C-c C-c
to execute the Emacs Lisp block and have my
Minecraft world updated. Then I just need to right-click on my command
block's button or run the function in order to get the new version.
I'm looking forward to learning more about mcfunctions so that I can write a function that automatically replaces the book in everyone's inventories. Could be fun.