From 358c67cc6baecd56540c3fad70a35c73edf8729f Mon Sep 17 00:00:00 2001 From: Roman Zhuravlev Date: Wed, 23 Apr 2025 23:16:55 +0500 Subject: [PATCH] Initial commit --- .gitignore | 1 + Makefile | 12 ++++ README.md | 71 +++++++++++++++++++++ mca.sh | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++ screenrc | 44 +++++++++++++ 5 files changed, 305 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100755 mca.sh create mode 100644 screenrc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..43b7d86 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +PREFIX ?= /usr + +all: + @echo Run \'make install\' to install MCA + +install: + @install -m 0755 mca.sh -D $(DESTDIR)$(PREFIX)/bin/mca + @install -m 0644 screenrc -Dt $(DESTDIR)/etc/mca + +uninstall: + @rm -rf $(DESTDIR)/etc/mca + @rm -f $(DESTDIR)$(PREFIX)/bin/mca diff --git a/README.md b/README.md new file mode 100644 index 0000000..1838872 --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# Minecraft server launcher - utility + +MCA is easy-to-use and allows you to run a Minecraft server with +just one short command in the background with the ability to +view the output with GNU Screen and run commands. + +## Usage +```bash +mca [-fdx] [MCA_NAME|MCA_JAR|MCA_DIR] [--] [INPUT]… +``` + +## MCA examples + +### Running `minecraft` server with 2048 megabytes max memory +```bash +mkdir ~/mca/myserver +cd ~/mca/myserver +# This link is taken from https://www.minecraft.net/en-us/download/server +wget https://piston-data.mojang.com/v1/objects/e6ec2f64e6080b9b5d9b471b291c33cc7f509733/server.jar +echo 'MAX_MEMORY=2048M' >> ./.mcarc +mca +``` + +### Running `paper` server with Aikar flags +```bash +echo 'PLATFORM=paper' >> ./.mcarc +mca +``` + +### Running `velocity` server with Aikar flags +```bash +echo 'PLATFORM=velocity' >> ./.mcarc +mca +``` + +Also, the platform can be determined automatically based on the `.jar` name. For example, the file name is `paper-1.21.5.jar`, since it starts with `paper`, the platform will be `paper` and there is no need to manually specify it in the `PLATFORM` variable. + +## Installation + +### From Zhira Debian repository + +Debian 12 Bookworm has deb packages in the Zhira Debian repository. + +#### Add the Zhira Debian repository: +```bash +wget -qO- https://deb.zhira.net/debian/zhira.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/zhira.gpg > /dev/null +echo 'deb [arch=all] https://deb.zhira.net/debian/ bookworm main' | sudo tee /etc/apt/sources.list.d/zhira.list > /dev/null +``` + +#### Update the package list +```bash +sudo apt update +``` + +#### Install `mca` +```bash +sudo apt install mca +``` + +### From sources + +#### Clone the repository +```bash +git clone https://git.zhira.net/rozhur/mca +``` + +### Install `mca` into `/usr/local/bin` directory +```bash +cd ./mca +sudo make PREFIX=/usr/local install +``` diff --git a/mca.sh b/mca.sh new file mode 100755 index 0000000..d8a8bf6 --- /dev/null +++ b/mca.sh @@ -0,0 +1,177 @@ +#!/bin/sh + +set -e + +EXEC_NAME="$(basename -- "$0")" + +options="$(getopt -n "$EXEC_NAME" -s sh -o hvfdx -l help -l version -- "$@")" +eval set -- "$options" + +SCREEN_OPTS= + +while :; do + case "$1" in + -h|--help) + echo "Usage: $EXEC_NAME [-fdx] [MCA_NAME|MCA_JAR|MCA_DIR] [--] [INPUT]…" + exit + ;; + -v|--version) + echo "MCA 1.0.0" + exit + ;; + -f) + SCREEN_OPTS=Dm + ;; + -d) + SCREEN_OPTS=d + ;; + -x) + SCREEN_OPTS=x + ;; + --) + shift + break + esac + shift +done + +MCA_NAME=$1 + +if [ -z "$MCA_NAME" ]; then + MCA_DIR="$PWD" + MCA_NAME="$(basename -- "$MCA_DIR")" +elif echo "$MCA_NAME" | grep -qE '^\.{,2}/' && MCA_NAME="$(readlink -f -- "$MCA_NAME")"; then + if [ -d "$MCA_NAME" ]; then + MCA_DIR="$MCA_NAME" + MCA_NAME="$(basename -- "$MCA_DIR")" + else + MCA_DIR="$(dirname -- "$MCA_NAME")" MCA_JAR="$MCA_NAME" + MCA_NAME="$(basename -- "$MCA_DIR")" + fi +else + MCA_DIR="$HOME/mca/$MCA_NAME" +fi + +command -v screen > /dev/null || { echo "$EXEC_NAME: screen not found" >&2; exit 2; } + +if [ -n "$2" ]; then + shift + INPUT="$(echo "$*" | sed 's/"/\\\0/g')" + screen -S "$MCA_NAME" -X eval "stuff \"$INPUT\"\\015" > /dev/null || { + echo "$EXEC_NAME: no screen found" >&2 + exit 2 + } + exit +fi + +MCA_SCREENRC_FILE="/etc/mca/screenrc" +[ -r "$MCA_SCREENRC_FILE" ] || { echo "$EXEC_NAME: can't read $MCA_SCREENRC_FILE" >&2; exit 2; } + +if screen -c "$MCA_SCREENRC_FILE" "-$SCREEN_OPTS"rS "$MCA_NAME" > /dev/null 2>&1; then + exit +elif screen -S "$MCA_NAME" -X select . > /dev/null 2>&1; then + echo "$EXEC_NAME: this screen has already been attached to someone" >&2 + exit 2 +fi + +[ -d "$MCA_DIR" ] || { echo "$EXEC_NAME: $MCA_DIR: not found" >&2; exit 2; } + +cd "$MCA_DIR" + +MCA_RC_FILE="$MCA_DIR/.mcarc" + +# this file is taken from a dynamic variable, so we cannot specify an explicit path to the file +# shellcheck disable=SC1090 +# `--` is supported in dash +# shellcheck disable=SC2240 +[ -e "$MCA_RC_FILE" ] && . -- "$MCA_RC_FILE" + +if [ -z "$PLATFORM" ]; then + if [ -z "$MCA_JAR" ]; then + MCA_JAR="$(find "$MCA_DIR" -maxdepth 1 -type f -name \*.jar | head -1)" + [ -z "$MCA_JAR" ] && { + echo "$EXEC_NAME: no jar found in $MCA_DIR" >&2 + exit 2 + } + fi + + if [ -e "$MCA_JAR" ]; then + PLATFORM="$(basename -- "$MCA_JAR")" + PLATFORM="$(echo "$PLATFORM" | tr '[:upper:]' '[:lower:]' | grep -oE '[a-z]+' | head -1)" + else + echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 + exit 2 + fi +else + [ -z "$MCA_JAR" ] && MCA_JAR="$MCA_DIR/$PLATFORM.jar" + [ ! -e "$MCA_JAR" ] && { + echo "$EXEC_NAME: $MCA_JAR: no such file" >&2 + exit 2 + } +fi + +[ -n "$JVM_FLAGS" ] && JVM_FLAGS="$JVM_FLAGS " +JVM_FLAGS="$JVM_FLAGS-Dfile.encoding=UTF-8 -Djava.awt.headless=true" + +case "$PLATFORM" in + bungee) + ;; + waterfall|velocity) + [ "$PLATFORM" = "bungee" ] || JVM_FLAGS="$JVM_FLAGS -XX:+UseG1GC \ +-XX:G1HeapRegionSize=4M \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+ParallelRefProcEnabled \ +-XX:+AlwaysPreTouch \ +-DIReallyKnowWhatIAmDoingISwear=true" + ;; + minecraft|bukkit|craftbukkit|spigot|paper) + JVM_FLAGS="$JVM_FLAGS -Dcom.mojang.eula.agree=true \ +-DIReallyKnowWhatIAmDoingISwear=true" + [ "$PLATFORM" = "paper" ] && JVM_FLAGS="$JVM_FLAGS -XX:+UseG1GC \ +-XX:+ParallelRefProcEnabled \ +-XX:MaxGCPauseMillis=200 \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+DisableExplicitGC \ +-XX:+AlwaysPreTouch \ +-XX:G1NewSizePercent=30 \ +-XX:G1MaxNewSizePercent=40 \ +-XX:G1HeapRegionSize=8M \ +-XX:G1ReservePercent=20 \ +-XX:G1HeapWastePercent=5 \ +-XX:G1MixedGCCountTarget=4 \ +-XX:InitiatingHeapOccupancyPercent=15 \ +-XX:G1MixedGCLiveThresholdPercent=90 \ +-XX:G1RSetUpdatingPauseTimePercent=5 \ +-XX:SurvivorRatio=32 \ +-XX:+PerfDisableSharedMem \ +-XX:MaxTenuringThreshold=1 \ +-Dusing.aikars.flags=https://mcflags.emc.gs \ +-Daikars.new.flags=true" + ;; + custom) + ;; + *) + echo "$EXEC_NAME: invalid platform: $PLATFORM. Valid: \ +bungee, waterfall, velocity, minecraft, bukkit, craftbukkit, spigot, paper, custom" >&2 + exit 2 + ;; +esac + +[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME/bin" ] && PATH="$JAVA_HOME/bin:$PATH" + +java -version > /dev/null 2>&1 || { + echo "$EXEC_NAME: unable to get Java version (is Java installed?)" >&2 + exit 2 +} + +[ -n "$MAX_MEMORY" ] && JVM_FLAGS="-Xmx$MAX_MEMORY $JVM_FLAGS" +[ -n "$MIN_MEMORY" ] && JVM_FLAGS="-Xms$MIN_MEMORY $JVM_FLAGS" + +MCA_CMD="$(which java) -server $JVM_FLAGS -jar $MCA_JAR" + +# papermc prints uncolored text if the COLORTERM variable is set to `truecolor` +export COLORTERM= + +# we don't quote $MCA_CMD because screen treats arguments after the second one as a command +# shellcheck disable=SC2086 +exec screen -c "$MCA_SCREENRC_FILE" "-$SCREEN_OPTS"S "$MCA_NAME" -- $MCA_CMD diff --git a/screenrc b/screenrc new file mode 100644 index 0000000..4dcdb76 --- /dev/null +++ b/screenrc @@ -0,0 +1,44 @@ +termcapinfo xterm* ti@:te@ + +escape ^Bb + +bind c +bind ^c +bind : +bind ^: +bind | +bind s +bind \" +bind - +bind i +bind ^i +bind o +bind ^o +bind f +bind ^f +bind x +bind ^x +bind h +bind ^h +bind g +bind ^g +bind r +bind ^r +bind t +bind ^t +bind p +bind ^p +bind n +bind ^n +bind v +bind . +bind ^. +bind , +bind ^, +bind > +bind ^> +bind < +bind ^< +bind \' + +bindkey ^c echo 'The CTRL+C keyboard shortcut has been disabled to prevent accidental process termination'