mca/mca.sh

279 lines
7.5 KiB
Bash
Executable file

#!/bin/sh
set -e
EXEC_NAME="$(basename -- "$0")"
USAGE="Usage: $EXEC_NAME [OPTION]... [NAME|JAR|DIR] [INPUT]..."
VERSION="mca 1.0.0"
OPTION="$(getopt -n "$EXEC_NAME" -s sh -o hvfdxrsc -l help -l version -- "$@")"
eval set -- "$OPTION"
SCREEN_OPTS=
REATTACH_ONLY=0
SKIP_CONFIGURE=0
CONFIGURE_ONLY=0
while :; do
case "$1" in
-h|--help)
echo "$USAGE"
exit
;;
-v|--version)
echo "$VERSION"
exit
;;
-f)
SCREEN_OPTS=Dm
;;
-d)
SCREEN_OPTS=d
;;
-x)
SCREEN_OPTS=x
;;
-r)
REATTACH_ONLY=1
;;
-s)
SKIP_CONFIGURE=1
;;
-c)
CONFIGURE_ONLY=1
;;
--)
shift
break
esac
shift
done
if [ "$SKIP_CONFIGURE" -eq 1 ] && [ "$CONFIGURE_ONLY" -eq 1 ]; then
echo "$EXEC_NAME: can't skip configuration and only configure at \
the same time" >&2
exit 2
fi
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
if [ "$CONFIGURE_ONLY" -eq 0 ]; then
if ! command -v screen > /dev/null; then
echo "$EXEC_NAME: screen not found" >&2
exit 2
fi
SCREEN_NAME="$(echo "$MCA_NAME" | tr / -)"
if [ -n "$2" ]; then
shift
INPUT="$(echo "$*" | sed 's/"/\\\0/g')"
if screen -S "$SCREEN_NAME" \
-X eval "stuff \"$INPUT\"\\015" > /dev/null; then
exit 0
else
echo "$EXEC_NAME: $SCREEN_NAME: no such screen found" >&2
exit 2
fi
fi
SCREEN_RC_FILE=
for i in "$HOME/.config" /etc; do
j="$i/mca/screenrc"
if [ -r "$j" ]; then
SCREEN_RC_FILE=$j
break
fi
done
if [ -z "$SCREEN_RC_FILE" ]; then
echo "$EXEC_NAME: can't find screenrc" >&2
exit 2
fi
if screen -c "$SCREEN_RC_FILE" "-$SCREEN_OPTS"rS \
"$SCREEN_NAME" > /dev/null 2>&1; then
exit 0
elif screen -S "$SCREEN_NAME" -X select . > /dev/null 2>&1; then
echo "$EXEC_NAME: this screen has already been attached to someone" >&2
exit 2
fi
if [ "$REATTACH_ONLY" -eq 1 ]; then
echo "$EXEC_NAME: $SCREEN_NAME: no such screen found" >&2
exit 2
fi
if [ ! -d "$MCA_DIR" ]; then
echo "$EXEC_NAME: $MCA_DIR: such directory not found" >&2
exit 2
fi
fi
cd "$MCA_DIR"
MCA_RC_FILE="$MCA_DIR/.mcarc"
if [ -e "$MCA_RC_FILE" ]; then
# don't use `-p` in `read` for line breaks to avoid long lines.
# shellcheck disable=SC2162
while IFS= read line; do
# skip lines starting with '#'
case "$line" in
''|\#*)
continue
;;
esac
# to get `$1` and `$2` as key and value.
# shellcheck disable=SC2086
set $line
if echo "$1" | grep -i '[^a-zA-Z0-9_]'; then
echo "$EXEC_NAME: $1: option key contains invalid characters" >&2
else
KEY="MCA_$(echo "$1" | tr '[:lower:]' '[:upper:]')"
if [ -n "$2" ]; then
shift
VALUE=$*
fi
export "$KEY"="$VALUE"
fi
done < "$MCA_RC_FILE"
MCA_RC_FILE_READ=1
else
MCA_RC_FILE_READ=0
fi
if [ "$CONFIGURE_ONLY" -eq 0 ]; then
if [ -z "$MCA_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
MCA_PLATFORM="$(basename -- "$MCA_JAR")"
MCA_PLATFORM="$(echo "$MCA_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/$MCA_PLATFORM.jar"
if [ ! -e "$MCA_JAR" ]; then
echo "$EXEC_NAME: $MCA_JAR: no such file" >&2
exit 2
fi
fi
[ -n "$MCA_JVM_FLAGS" ] && MCA_JVM_FLAGS="$MCA_JVM_FLAGS "
MCA_JVM_FLAGS="$MCA_JVM_FLAGS-Dfile.encoding=UTF-8 \
-Djava.awt.headless=true"
case "$MCA_PLATFORM" in
bungee)
;;
waterfall|velocity)
[ "$MCA_PLATFORM" = "bungee" ] || MCA_JVM_FLAGS="$MCA_JVM_FLAGS \
-XX:+UseG1GC \
-XX:G1HeapRegionSize=4M \
-XX:+UnlockExperimentalVMOptions \
-XX:+ParallelRefProcEnabled \
-XX:+AlwaysPreTouch \
-DIReallyKnowWhatIAmDoingISwear=true"
;;
minecraft|bukkit|craftbukkit|spigot|paper)
MCA_JVM_FLAGS="$MCA_JVM_FLAGS -Dcom.mojang.eula.agree=true \
-DIReallyKnowWhatIAmDoingISwear=true"
[ "$MCA_PLATFORM" = "paper" ] && MCA_JVM_FLAGS="$MCA_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: $MCA_PLATFORM. Valid: bungee, \
waterfall, velocity, minecraft, bukkit, craftbukkit, spigot, \
paper, custom" >&2
exit 2
;;
esac
if [ -n "$MCA_OPT_JAVA_HOME" ] && [ -d "$MCA_OPT_JAVA_HOME/bin" ]; then
PATH="$MCA_OPT_JAVA_HOME/bin:$PATH"
fi
if ! command -v java > /dev/null; then
echo "$EXEC_NAME: unable to get Java version (is Java installed?)" >&2
exit 2
fi
[ -n "$MCA_OPT_MAX_MEMORY" ] \
&& MCA_JVM_FLAGS="-Xmx$MCA_OPT_MAX_MEMORY $MCA_JVM_FLAGS"
[ -n "$MCA_OPT_MIN_MEMORY" ] \
&& MCA_JVM_FLAGS="-Xms$MCA_OPT_MIN_MEMORY $MCA_JVM_FLAGS"
SCREEN_CMD="$(which java) -server $MCA_JVM_FLAGS -jar $MCA_JAR"
fi
if [ "$SKIP_CONFIGURE" -eq 0 ] && [ "$MCA_RC_FILE_READ" -eq 1 ]; then
ENV_LIST="$(env | grep ^MCA_ | cut -d= -f1 | sed 's/^/$/g')"
FILE_LIST="$(find . -name '*.in' -type f)"
[ -z "$FILE_LIST" ] || echo "$FILE_LIST" | while read -r line; do
envsubst "$ENV_LIST" < "$line" > "${line%*.in}"
done
fi
if [ "$CONFIGURE_ONLY" -eq 0 ]; then
# papermc prints uncolored text if the COLORTERM variable is set to
# `truecolor`.
export COLORTERM=
# we don't quote $SCREEN_CMD because screen treats arguments after the
# second one as a command.
# shellcheck disable=SC2086
exec screen -c "$SCREEN_RC_FILE" "-$SCREEN_OPTS"S "$SCREEN_NAME" \
-- $SCREEN_CMD
fi