You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
8.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>How to use tmux to send and receive things from your Minecraft server | tait.tech</title>
<link rel="stylesheet" href="/assets/css/style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Tait Hoyem">
<meta name="keywords" content="">
<meta name="description" content="">
</head>
<body>
<div id="wrapper">
<header>
<h1>tait.tech</h1>
<nav>
<a href="/" class="nav-link" >Home</a>
<a href="/blog/" class="nav-link" >Blog</a>
<a href="/ideas/" class="nav-link" >Ideas</a>
<a href="/links/" class="nav-link" >Links</a>
<a href="https://github.com/TTWNO/" class="nav-link" target="_blank" rel="noopener noreferrer" >Github</a>
</nav>
</header>
<main>
<article>
<header>
<h1 class="post-title">How to use tmux to send and receive things from your Minecraft server</h1>
<time datetime="20-06-25" class="post-date">Thursday, June 25 2020</time>
</header>
<hr>
<p>So recently I had problem.
I run a Minecraft server on a big Linux computer I have running in my room.
Now, as a system administrator it is very helpful to be able to run some simple commands without needing to login with my key, password, TFA, etc.
It is, frankly, a lot of work.
Especially when I really just want to be playing games but I just need to check something quickly.</p>
<p>So for simple things like finding out of the network, CPU, memory or disk usage is my bottleneck, I wrote this really nifty script to connect the world of Minecraft and the Linux shell.</p>
<p>My completed solution for what I needed can be found at <a href="https://github.com/TTWNO/termcraft/">https://github.com/TTWNO/termcraft</a>.</p>
<p>If you want some of the implementation details, stick around.</p>
<h2 id="solution">Solution</h2>
<p>So to solve this interesting problem, I decided to use <code class="language-plaintext highlighter-rouge">tmux</code>.
<code class="language-plaintext highlighter-rouge">tmux</code> is a <strong>t</strong>terminal <strong>mu</strong>ltiple<strong>x</strong>er.
This allows you to run a terminal session, then detach fromc it while it still runs in the background.</p>
<p>This is very valuable when running command line applications that need to have an active console connection, like a Minecraft server.</p>
<p>So first I looked at the <code class="language-plaintext highlighter-rouge">tmux</code> command <code class="language-plaintext highlighter-rouge">send-keys</code>.</p>
<h4 id="send-keys"><code class="language-plaintext highlighter-rouge">send-keys</code></h4>
<p><code class="language-plaintext highlighter-rouge">send-keys</code> allows you to send text, and key presses to a <code class="language-plaintext highlighter-rouge">tmux</code> session.
Now assuming this <code class="language-plaintext highlighter-rouge">tmux</code> session is attached to a Minecraft server,
there is no reason you could not run a command like this:</p>
<pre class="terminal">
$ tmux send-keys "tell @a This is a Test" Enter
</pre>
<p>This will send the text “tell @a This is a Test” to the Minecraft server.
Then, it will hit the newline character, this will execute the command.</p>
<p>So now we can send information to the server and have it tell the users something.</p>
<p>But how do we get information about who is typing what in the Minecraft chat?</p>
<h3 id="tmuxs-capture-pane-is-painful"><code class="language-plaintext highlighter-rouge">tmux</code>s <code class="language-plaintext highlighter-rouge">capture-pane</code> is painful</h3>
<p>So in the manual page for <code class="language-plaintext highlighter-rouge">tmux</code> I can see a section recorded below for options I can give to the <code class="language-plaintext highlighter-rouge">capture-pane</code> subcommand.</p>
<pre class="terminal">
-S and -E specify the starting and ending line numbers,
zero is the first line of the visible pane and negative
numbers are lines in the history. - to -S is the start
of the history and to -E the end of the visible pane. The
default is to capture only the visible contents of the pane.
</pre>
<p>What it seems to be saying is I can start at line <code class="language-plaintext highlighter-rouge">-S n</code> and end at line <code class="language-plaintext highlighter-rouge">-E n</code>.
Negative numbers start from the bottom, so <em>in theory</em> I can do the following: <code class="language-plaintext highlighter-rouge">tmux capture-pane -S -1</code> should capture only the last line, because Im starting from the last line. Right?</p>
<p>No. It just doesnt work. Negative numbers do <em>not</em> work with the <code class="language-plaintext highlighter-rouge">tmux capture-pane</code> subcommand.</p>
<p>So I did some simple UNIX piping, like so, to get just the last thing in the chat.</p>
<pre class="terminal">
$ tmux capture-pane -p -t steve | tail -n1
[SERVER] [ExtraDebuggingInfoHere]: &lt;TaterTheTot&gt; MY_MESSAGE
</pre>
<p>TaterTheTot is my Minecraft username :)</p>
<p><code class="language-plaintext highlighter-rouge">-p</code> prints the result to the terminal/stdout.</p>
<p><code class="language-plaintext highlighter-rouge">steve</code> is the name of the tmux session Im trying to pull form.</p>
<p>So thats done! Beauty!</p>
<p>Now that we have that, how can we extract the username and the message from the latest line?</p>
<h3 id="grep"><code class="language-plaintext highlighter-rouge">grep</code></h3>
<p><code class="language-plaintext highlighter-rouge">grep</code> is a command to find patterns of text.
<code class="language-plaintext highlighter-rouge">grep</code> has an option to only show a matching pattern of text.
This option is <code class="language-plaintext highlighter-rouge">-o</code>.</p>
<p>Lets see how we can use this in conjunction with our latest line of server output to get our results.</p>
<pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&lt;.&ast;&gt;"
&lt;TaterTheTot&gt;
</pre>
<p>Now, thats my name with the &lt; and &gt; attached. Not bad!
We can use the <code class="language-plaintext highlighter-rouge">sed</code> command to clean it up a bit.</p>
<p>The syntax is like so: <code class="language-plaintext highlighter-rouge">select/somepattern/replacewith/global</code></p>
<p>So the following command is: <code class="language-plaintext highlighter-rouge">s/[&lt;&gt;]//g</code></p>
<p>Select any characters that are either &lt; or &gt;.
Replace with nothing.
Do so globally (as in, dont stop after you replace only one character).</p>
<p>Take two!</p>
<pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&lt;.&ast;&gt;" | sed 's/[&lt;&gt;]//g'
TaterTheTot
</pre>
<p>Beautiful!</p>
<p>Now what about that pesky message?</p>
<h3 id="more-grep-more-sed">more <code class="language-plaintext highlighter-rouge">grep</code>; more <code class="language-plaintext highlighter-rouge">sed</code></h3>
<p>Simple: capture everything after the &gt;. Leaving the users message entirely in tact.</p>
<pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&gt;.&ast;$" | sed 's/&gt; //'
MY_MESSAGE
</pre>
<p>So now we have a way to get the username of someone typing in the Minecraft server chat.
We have a way to find out what they said.
And, we have a way to respond.</p>
<p>You can imagine how these might go together for your own use case.</p>
<h3 id="conclusion">Conclusion</h3>
<p>This shows some pretty fun stuff you can do with a few simple Linux commands and a Minecraft server.</p>
<p>I hope you learned something and found my explanations not horrific haha!</p>
<p>Remember to checkout the git repository to see what I did with it: <a href="https://github.com/TTWNO/termcraft">https://github.com/TTWNO/termcraft</a>.</p>
<p>Happy hacking!</p>
</article>
</main>
<hr>
<footer>
This page will be mirrored on <a href="https://beta.tait.tech/2020/06/25/tmux-minecraft/">beta.tait.tech</a>.
</footer>
</div>
</body>
</html>