Advertisement
Guest User

minecraft_server with additional server types

a guest
Nov 24th, 2012
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 43.23 KB | None | 0 0
  1. #! /bin/sh
  2. ### BEGIN INIT INFO
  3. # Provides:       minecraft_server
  4. # Required-Start: $remote_fs $syslog
  5. # Required-Stop:  $remote_fs $syslog
  6. # Default-Start:  3 4 5
  7. # Default-Stop:   0 1 2 6
  8. # chkconfig:      345 50 50
  9. # Description:    Minecraft Server control script.
  10. ### END INIT INFO
  11.  
  12. # Minecraft Server control script.
  13. #
  14. # Options:
  15. #   start <world>         - Start the Minecraft world server.  Start all world
  16. #                           servers by default.
  17. #   stop <world>          - Stop the Minecraft world server.  Stop all world
  18. #                           servers by default.
  19. #   force-stop <world>    - Forcibly stop the Minecraft world server.  Forcibly
  20. #                           stop all world servers by default.
  21. #   restart <world>       - Restart the Minecraft world server.  Restart all
  22. #                           world servers by default.
  23. #   force-restart <world> - Forcibly restart the Minecraft world server.
  24. #                           Forcibly restart all world servers by default.
  25. #   status <world>        - Display the status of the Minecraft world server.
  26. #                           Display the status of all world servers by default.
  27. #   sync <world>          - Synchronize the data stored in the mirror images of
  28. #                           the Minecraft world server.  Synchronizes all of
  29. #                           the world servers by default.  This option is only
  30. #                           available when the mirror image option is enabled.
  31. #   send <world> <cmd>    - Send a command to a Minecraft world server.
  32. #   screen <world>        - Display the Screen for the Minecraft world server.
  33. #   watch <world>         - Watch the log file for the Minecraft world server.
  34. #   backup <world>        - Backup the Minecraft world.  Backup all worlds by
  35. #                           default.
  36. #   c10t <world>          - Run the c10t mapping software on the Minecraft
  37. #                           world.  Map all worlds by default.
  38. #   pigmap <world>        - Run the pigmap mapping software on the Mincraft
  39. #                           world.  Map all worlds by default.
  40. #   update <software>     - Update a software package.  Update the server
  41. #                           software and all add-ons by default.
  42. #
  43. #   Available software packages for update option:
  44. #     server        - Minecraft server software.
  45. #     c10t          - c10t mapping software.
  46. #     pigmap        - Pigmap mapping software.
  47.  
  48.  
  49. # User name used to run all commands.
  50. USER_NAME="minecraft"
  51.  
  52. # The location of server software and data.
  53. LOCATION="/home/$USER_NAME"
  54.  
  55.  
  56. ## Required software.
  57.  
  58. JAVA=$(which java)
  59. JAR=$(which jar)
  60. PERL=$(which perl)
  61. RSYNC=$(which rsync)
  62. SCREEN=$(which screen)
  63. WGET=$(which wget)
  64. RDIFF_BACKUP=$(which rdiff-backup)
  65.  
  66.  
  67. ## Generic options.
  68.  
  69. # Automatically restart the Minecraft server when a SEVERE error is caught.
  70. #   0 - Do not auto restart.
  71. #   1 - Auto restart.
  72. AUTO_RESTART_ON_ERROR=0
  73.  
  74. # Software packages updated with the update command.
  75. #   server        - Minecraft server software.
  76. #   c10t          - c10t mapping software.
  77. #   pigmap        - Pigmap mapping software.
  78. UPDATE_PACKAGES="server c10t pigmap"
  79.  
  80.  
  81. ## Minecraft server options.
  82. SERVER_TYPES="mojang bukkit tekkit"
  83.  
  84. ## Some extra Java Options
  85. #JAVA_OPTS="-Xmx1536M -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=2 -XX:+AggressiveOpts"
  86.  
  87. # Default Mojang server distribution.
  88. SERVER_MOJANG_URL="https://s3.amazonaws.com/MinecraftDownload/launcher/Minecraft_Server.exe"
  89. SERVER_MOJANG_JAR="minecraft_server.jar"
  90. SERVER_MOJANG_ARGS="nogui"
  91. SERVER_MOJANG_JAVA_OPTS="-Xms512M -Xmx1G"
  92.  
  93. # CraftBukkit server distribution.
  94. SERVER_BUKKIT_URL="http://cbukk.it/craftbukkit.jar"
  95. SERVER_BUKKIT_JAR="craftbukkit.jar"
  96. SERVER_BUKKIT_JAVA_OPTS="-Xms512M -Xmx1G"
  97. SERVER_BUKKIT_ARGS=""
  98.  
  99. # Tekkit server distribution.
  100. SERVER_TEKKIT_URL="http://mirror.technicpack.net/Technic/servers/tekkit/Tekkit_Server_3.1.3.zip"
  101. SERVER_TEKKIT_JAR="Tekkit.jar"
  102. SERVER_TEKKIT_JAVA_OPTS="-Xms512M -Xmx1G"
  103. SERVER_TEKKIT_ARGS="nogui"
  104.  
  105. # Feed the Beast server distribution.
  106. SERVER_FTB_URL="http://repo.creeperhost.net/direct/FTB2/71a030a9197ede2920757ecdc59cd6c1/FTBBetaA_Server.zip"
  107. SERVER_FTB_JAR="FTB-Beta-A.jar"
  108. SERVER_FTB_JAVA_OPTS="-Xms512M -Xmx1G"
  109. SERVER_FTB_ARGS="nogui"
  110.  
  111. # Generic server options.
  112. SERVER_LOCATION="$LOCATION/minecraft_server"
  113.  
  114.  
  115. ## World configuration.
  116.  
  117. # The location to store files for each world server.
  118. WORLDS_LOCATION="$LOCATION/worlds"
  119.  
  120. # List of worlds and the ports they are running on.  This file will
  121. # be generated if missing.
  122. #
  123. # Note: The world name should not contain a space.  Leave the ip
  124. # address blank if not needed.
  125. #
  126. # # Minecraft world configuration file
  127. # # <world> <server>    <port>  <ip>
  128. #   alpha   mojang  25565
  129. #   beta    mojang  25566
  130. #   gamma   bukkit  25567
  131. #   delta   tekkit  25568
  132. #   epsilon ftb 25569
  133. WORLDS_CONF="$LOCATION/worlds.conf"
  134.  
  135. # Default world name, server type, port, and IP address if the worlds.conf file is missing.
  136. # Supported server types are ( mojang bukkit tekkit )
  137. DEFAULT_WORLD="world"
  138. DEFAULT_SERVER="mojang"
  139. DEFAULT_PORT="25565"
  140. DEFAULT_IP=""
  141.  
  142.  
  143. ## Global Message Of The Day file (MOTD).
  144.  
  145. # Location of the file to display to users on login and when the /motd command
  146. # is used on any world.  Nothing will be done if this file does not exist.
  147. MOTD="$LOCATION/motd.txt"
  148.  
  149.  
  150. ## Help file.
  151.  
  152. # Location of the file to display to users when the /help command is used. A
  153. # basic file will be generated on the first run if it does not exist.
  154. HELP="$LOCATION/help.txt"
  155.  
  156.  
  157. ## MOTD and help files can contain color codes as follows:
  158. #  §0 - black
  159. #  §1 - blue
  160. #  §2 - dark green
  161. #  §3 - aqua
  162. #  §4 - dark red
  163. #  §5 - purple
  164. #  §6 - gold
  165. #  §7 - gray
  166. #  §8 - dark gray
  167. #  §9 - light blue
  168. #  §a - green
  169. #  §b - teal
  170. #  §c - red
  171. #  §d - magenta
  172. #  §e - yellow
  173. #  §f - white
  174.  
  175.  
  176. ## Backup configuration.
  177.  
  178. # Location to store backups.
  179. BACKUP_LOCATION="$LOCATION/backups"
  180.  
  181. # Location of the backup log file.
  182. BACKUP_LOG="$BACKUP_LOCATION/backup.log"
  183.  
  184. # Length in days that backups survive.
  185. BACKUP_DURATION=31
  186.  
  187.  
  188. ## Mirror image options.
  189.  
  190. # Create a mirror image of the world data on system startup, and
  191. # update that mirror image on system shutdown.
  192. #
  193. # IMPORTANT: If using this option, the admin should schedule
  194. # periodic synchronizations of the mirror image using cron
  195. # to avoid data loss.
  196. #
  197. # 0 - Do not use a mirror image, default.
  198. # 1 - Use a mirror image.
  199. ENABLE_MIRROR=0
  200.  
  201. # The location to store the mirror image.
  202. #
  203. # NOTE: This is usually a ramdisk.
  204. MIRROR_PATH="/dev/shm/minecraft"
  205.  
  206.  
  207. ## c10t mapping software options.
  208. C10T_URL="http://toolchain.eu/minecraft/c10t/releases"
  209. C10T_LOCATION="$LOCATION/c10t"
  210. C10T_BIN="$C10T_LOCATION/c10t"
  211. C10T_MAPS_URL="http://minecraft.server.com/maps/c10t"
  212. C10T_MAPS_LOCATION="$LOCATION/maps/c10t"
  213.  
  214.  
  215. ## Pigmap mapping software options.
  216. MINECRAFT_CLIENT_URL="https://s3.amazonaws.com/MinecraftDownload/minecraft.jar"
  217. PIGMAP_URL="https://github.com/equalpants/pigmap/tarball/master"
  218. PIGMAP_LOCATION="$LOCATION/pigmap"
  219. PIGMAP_BIN="$PIGMAP_LOCATION/pigmap"
  220. PIGMAP_MAPS_URL="http://minecraft.server.com/maps/pigmap"
  221. PIGMAP_MAPS_LOCATION="$LOCATION/maps/pigmap"
  222.  
  223.  
  224. ## Lib-notify configuration.
  225.  
  226. # Use lib-notify to print a message on your desktop of important server events.
  227. # 0 - Do not use lib-notify.
  228. # 1 - Display server events using lib-notify.
  229. USE_LIBNOTIFY=0
  230.  
  231. # The username and display that messages will be routed to.
  232. LIBNOTIFY_USER_NAME=$USER_NAME
  233. LIBNOTIFY_DISPLAY=":0.0"
  234.  
  235.  
  236. ## Internal Methods.
  237.  
  238. # Execute the given command.
  239. #
  240. # @param 1 The command to execute.
  241. # @param 2 The user name to execute the command with.
  242. execute() {
  243.     if [ $(id -u) -eq 0 ]; then
  244.         # Script is running as root, switch user and execute
  245.         # the command.
  246.         su -c "$1" $2
  247.     else
  248.         # Script is running as a user, just execute the command.
  249.         sh -c "$1"
  250.     fi
  251. }
  252.  
  253. # Get the PIDs of the Screen and Java process for the world server.
  254. #
  255. # @param 1 The world server of interest.
  256. # @return The Screen and Java PIDs
  257. getProcessIDs() {
  258.     local SCREEN_PID JAVA_PID
  259.     SCREEN_PID=$(execute "$SCREEN -ls" $USER_NAME | $PERL -ne 'if ($_ =~ /^\t(\d+)\.minecraft-'$1'\s+/) { print $1; }')
  260.     JAVA_PID=$(ps -a -u $USER_NAME -o pid,ppid,comm | $PERL -ne 'if ($_ =~ /^\s*(\d+)\s+'$SCREEN_PID'\s+java/) { print $1; }')
  261.     echo "$SCREEN_PID $JAVA_PID"
  262. }
  263.  
  264. # Check to see if the world server is running.
  265. #
  266. # @param 1 The world server of interest.
  267. # @return A 1 if the server is thought to be running, a 0 otherwise.
  268. serverRunning() {
  269.     local PIDS
  270.     PIDS=$(getProcessIDs $1)
  271.     # Try to determine if the world is running.
  272.     if [ -n "$(echo $PIDS | cut -d ' ' -f1)" ] && [ -n "$(echo $PIDS | cut -d ' ' -f2)" ]; then
  273.         echo 1
  274.     else
  275.         echo 0
  276.     fi
  277. }
  278.  
  279. # Send a command to the world server.
  280. #
  281. # @param 1 The world server of interest.
  282. # @param 2 The command to send.
  283. sendCommand() {
  284.     local COMMAND PID
  285.     COMMAND=$(printf "$2\r")
  286.     PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f1)
  287.     execute "$SCREEN -S $PID.minecraft-$1 -p 0 -X stuff \"$COMMAND\"" $USER_NAME
  288.     if [ $? -ne 0 ]; then
  289.         printf "Error sending command to server $1.\n"
  290.         exit 1
  291.     fi
  292. }
  293.  
  294. # Connect to the Screen of a world server.
  295. #
  296. # @param 1 The world server of interest.
  297. displayScreen() {
  298.     local PID
  299.     PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f1)
  300.     printf "About to load the screen for world $1.\n"
  301.     printf "To exit the screen, hit Ctrl+A then type the letter d.\n"
  302.     sleep 5
  303.     execute "$SCREEN -x $PID.minecraft-$1" $USER_NAME
  304.     if [ $? -ne 0 ]; then
  305.         printf "Error connecting to Screen.\n"
  306.         exit 1
  307.     fi
  308. }
  309.  
  310. # Check whether the item is in the list.
  311. #
  312. # @param 1 The item being searched for.
  313. # @param 2 The list being searched.
  314. # @return A 1 if the list contains the item, a 0 otherwise.
  315. listContains() {
  316.     local MATCH ITEM
  317.     MATCH=0
  318.     for ITEM in $2; do
  319.         if [ "$ITEM" = "$1" ]; then
  320.             MATCH=1
  321.         fi
  322.     done
  323.     echo $MATCH
  324. }
  325.  
  326. # Grab the port for the given world.
  327. #
  328. # @param 1 The world server of interest.
  329. # @return The port that the world is configured to use.
  330. getPort() {
  331.     local PORT
  332.     PORT=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^'$1'\s+[\w\d]+\s+(\d+)/) { print "$1"; }')
  333.     echo $PORT
  334. }
  335.  
  336. # Grab the IP address for the given world.
  337. #
  338. # @param 1 The world server of interest.
  339. # @return The IP address that the world is configured to run on.
  340. getIP() {
  341.     local IP
  342.     IP=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^'$1'\s+[\w\d]+\s+\d+\s+([\d\.]+)/) { print "$1"; }')
  343.     echo $IP
  344. }
  345.  
  346. # Grab the server type for the given world.
  347. #
  348. # @param 1 The world server of interest.
  349. # @return The server type that the world is configured to run on.
  350. getServerType() {
  351.     local SERVER
  352.     SERVER=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^'$1'\s+([\w\d]+)/) { print "$1"; }')
  353.     echo $SERVER
  354. }
  355.  
  356. # Grab the first line of the Message of the Day file as a summary, and strip
  357. # any color codes from it.
  358. getMOTD() {
  359.     local MOTD_SUMMARY
  360.     MOTD_SUMMARY=""
  361.     if [ -e $MOTD ]; then
  362.         MOTD_SUMMARY=$(head -n 1 $MOTD | $PERL -ne '$_ =~ s/§[0-9a-fA-F]//g; print;')
  363.     fi
  364.     echo $MOTD_SUMMARY
  365. }
  366.  
  367. # Grab the list of worlds.
  368. #
  369. # @return The list of worlds.
  370. getWorlds() {
  371.     local WORLDS
  372.     WORLDS=$(execute "cat $WORLDS_CONF" $USER_NAME | $PERL -ne 'if ($_ =~ /^([\w\d]+)\s+[\w\d]+\s+\d+/) { print "$1 "; }')
  373.     echo $WORLDS
  374. }
  375.  
  376. # Modify the value of a key/value combo in a properties file.
  377. #
  378. # @param 1 The properties file of interest.
  379. # @param 2 The key to modify.
  380. # @param 3 The value to assign to the key.
  381. setPropertiesValue() {
  382.     local KEY_VALUE
  383.     # Make sure that the properties file exists.
  384.     execute "touch $1" $USER_NAME
  385.     # Replace the key/value combo if it already exists, otherwise just
  386.     # append it to the end of the file.
  387.     KEY_VALUE=$($PERL -ne 'if ($_ =~ /^('$2'=.*)$/) { print "$1"; }' $1)
  388.     if [ -n "$KEY_VALUE" ]; then
  389.         execute "$PERL -i -ne 'if (\$_ =~ /^$2=.*$/) { print \"$2=$3\\n\"; } else { print; }' $1" $USER_NAME
  390.     else
  391.         execute "printf \"$2=$3\\n\" >> $1" $USER_NAME
  392.     fi
  393. }
  394.  
  395. # Send a message to the desktop using lib-notify, if it is available.
  396. #
  397. # @param 1 The summary of the message to send.
  398. # @param 2 The body of the message to send.
  399. libNotify() {
  400.     local NOTIFY
  401.     NOTIFY=$(which notify-send)
  402.     if [ -e $NOTIFY ]; then
  403.         execute "DISPLAY=$LIBNOTIFY_DISPLAY $NOTIFY \"$1\" \"$2\"" $LIBNOTIFY_USER_NAME > /dev/null 2>&1
  404.     fi
  405. }
  406.  
  407. # Send the contents of the Message Of The Day (MOTD) to the user.
  408. #
  409. # @param 1 The world server of interest.
  410. # @param 2 The user being told the contents of the motd file.
  411. tellMOTD() {
  412.     local LINE
  413.     if [ -e $MOTD ]; then
  414.         while read LINE; do
  415.             sendCommand $1 "tell $2 $LINE"
  416.         done < $MOTD
  417.     fi
  418. }
  419.  
  420. # Check to see if the user is in the ops.txt file of the specified world.
  421. #
  422. # @param 1 The world server of interest.
  423. # @param 2 The user being checked.
  424. checkUserIsAdmin() {
  425.     local IS_ADMIN
  426.     IS_ADMIN=$(cat $WORLDS_LOCATION/$1/ops.txt | $PERL -ne 'if ($_ =~ /^'$2'$/i) { print "1"; }')
  427.     echo $IS_ADMIN
  428. }
  429.  
  430. # Check for the optional argument.  If the argument is not supplied, return
  431. # the original list.  If the argument is supplied, verify that it is a member
  432. # of the list, then modify the list to just contain that member.
  433. #
  434. # @param 1 The original list.
  435. # @param 2 The name of the script.
  436. # @param 3 The command line argument used.
  437. # @param 4 The optional command line argument.
  438. # @return Either the original list, or the optional command line argument.
  439. checkOptionalArgument() {
  440.     local LIST
  441.     LIST="$1"
  442.     # Check for the optional command line argument.
  443.     if [ -n "$4"  ] && [ $(listContains $4 "$1") -eq 1 ]; then
  444.         LIST="$4"
  445.     elif [ -n "$4" ]; then
  446.             printf "Optional argument '$4' not recognized.\n"
  447.             printf "  Usage:  $2 $3 <optional argument>\n"
  448.         exit 1
  449.     fi
  450.     echo "$LIST"
  451. }
  452.  
  453. # Check for users logging into a world.  If a user logs in, perform
  454. # login functions.
  455. #
  456. # @param 1 The world server of interest.
  457. # @param 2 The message to check for users logging in.
  458. checkForLogin() {
  459.     local LOGIN PLAYER_NAME
  460.     LOGIN=$(echo "$2" | $PERL -ne 'if ($_ =~ /(\w+)\s*\[\/([0-9\.]+)\:(\d+)\] logged in with entity id (\d+)/) { print "$1\t$2\t$3\t$4"; }')
  461.     if [ -n "$LOGIN" ]; then
  462.         PLAYER_NAME=$(printf "$LOGIN" | cut -f1)
  463.         # Add the user to the world.users file.
  464.         execute "printf \"$LOGIN\n\" >> \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
  465.         # Announce the user logging in via lib-notify.
  466.         if [ $USE_LIBNOTIFY ]; then
  467.             libNotify "Minecraft - $1" "$PLAYER_NAME has logged into world."
  468.         fi
  469.         # Whisper the MOTD to the user logging in.
  470.         tellMOTD $1 $PLAYER_NAME
  471.     fi
  472. }
  473.  
  474. # Check for users logging out of a world.  If a user logs out, perform the
  475. # logout functions.
  476. #
  477. # @param 1 The world server of interest.
  478. # @param 2 The message to check for users logging out.
  479. checkForLogout() {
  480.     local LOGOUT PLAYER_NAME
  481.     LOGOUT=$(echo "$2" | $PERL -ne 'if ($_ =~ /(\w+) lost connection\: (.+)/) { print "$1\t$2"; }')
  482.     if [ -n "$LOGOUT" ]; then
  483.         PLAYER_NAME=$(printf "$LOGOUT" | cut -f1)
  484.         # Remove the user from the world.users file.
  485.         execute "$PERL -i -ne 'print unless /^$PLAYER_NAME\t[0-9\.]+\t\d+\d+/;' $WORLDS_LOCATION/$1.users" $USER_NAME
  486.         # Announce the user logging out via lib-notify.
  487.         if [ $USE_LIBNOTIFY ]; then
  488.             libNotify "Minecraft - $1" "$PLAYER_NAME has logged out of world."
  489.         fi
  490.     fi
  491. }
  492.  
  493. # Parse through the log file for the given world.  Uses checkFor methods to
  494. # find events such as users logging in or out.
  495. #
  496. # @param 1 The world server generating the log to parse.
  497. parseLog() {
  498.     local LINE DATE TIME TYPE MESSAGE
  499.     while read LINE; do
  500.         LINE=$(echo "$LINE" | $PERL -ne 'if ($_ =~ /(.+) (.+) \[(\w+)\] (.+)/) { print "$1\t$2\t$3\t$4"; }')
  501.         DATE=$(echo "$LINE" | cut -f1)
  502.         TIME=$(echo "$LINE" | cut -f2)
  503.         TYPE=$(echo "$LINE" | cut -f3)
  504.         MESSAGE=$(echo "$LINE" | cut -f4)
  505.         case "$TYPE" in
  506.             INFO)
  507.                 checkForLogin $1 "$MESSAGE"
  508.                 checkForLogout $1 "$MESSAGE"
  509.             ;;
  510.             SEVERE)
  511.                 if [ $AUTO_RESTART_ON_ERROR -eq 1 ]; then
  512.                     sendCommand $1 "say The server is experiencing issues, restarting in 5 seconds..."
  513.                     sleep 5
  514.                     stop $1
  515.                     sleep 5
  516.                     start $1
  517.                 fi
  518.             ;;
  519.             WARNING)
  520.             ;;
  521.             *)
  522.             ;;
  523.         esac
  524.     done
  525. }
  526.  
  527. # Watch the world server log file.
  528. #
  529. # @param 1 The world server generating the log to watch.
  530. watchLog() {
  531.     local PID WORLD_DIR
  532.     WORLD_DIR="$WORLDS_LOCATION/$1"
  533.     # Use the mirror copy of the world directory if enabled.
  534.     if [ $ENABLE_MIRROR -eq 1 ] && [ -d $MIRROR_PATH ]; then
  535.         WORLD_DIR="$MIRROR_PATH/$1"
  536.     fi
  537.     # Make sure that the server.log file exists.
  538.     if [ -e "$WORLD_DIR/server.log" ]; then
  539.         # Watch the log.
  540.         PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f2)
  541.         tail -n0 -f --pid=$PID $WORLD_DIR/server.log
  542.     fi
  543. }
  544.  
  545. # Synchronizes the data stored in the mirror images.
  546. #
  547. # @param 1 The world server to sync.
  548. syncMirrorImage() {
  549.     # Sync the world server.
  550.     execute "$RSYNC -rt $MIRROR_PATH/$1/* $WORLDS_LOCATION/$1" $USER_NAME
  551.     if [ $? -ne 0 ]; then
  552.         printf "Error synchronizing mirror images for world $1.\n"
  553.         exit 1
  554.     fi
  555. }
  556.  
  557. # Start the world server and the log processor.  Generate the appropriate
  558. # environment for the server if it doesn't already exist.
  559. #
  560. # @param 1 The world server to start.
  561. start() {
  562.     local PID WORLD_DIR SERVER_TYPE SERVER_JAR SERVER_ARGS JAVA_OPTS
  563.  
  564.     # Make sure that the world's directory exists.
  565.     WORLD_DIR="$WORLDS_LOCATION/$1"
  566.     if [ ! -d "$WORLDS_LOCATION/$1" ]; then
  567.         execute "mkdir -p $WORLD_DIR" $USER_NAME
  568.     fi
  569.  
  570.     # Get the world server type
  571.     SERVER_TYPE=$(getServerType "$1")
  572.  
  573.     # Set the server location, and args
  574.     if [ $SERVER_TYPE = "mojang" ]; then
  575.         SERVER_JAR=$SERVER_MOJANG_JAR
  576.         SERVER_ARGS=$SERVER_MOJANG_ARGS
  577.         JAVA_OPTS=$SERVER_MOJANG_JAVA_OPTS
  578.     elif [ $SERVER_TYPE = "bukkit" ]; then
  579.         SERVER_JAR=$SERVER_BUKKIT_JAR
  580.         SERVER_ARGS=$SERVER_BUKKIT_ARGS
  581.         JAVA_OPTS=$SERVER_BUKKIT_JAVA_OPTS
  582.     elif [ $SERVER_TYPE = "tekkit" ]; then
  583.         SERVER_JAR=$SERVER_TEKKIT_JAR
  584.         SERVER_ARGS=$SERVER_TEKKIT_ARGS
  585.         JAVA_OPTS=$SERVER_TEKKIT_JAVA_OPTS
  586.     elif [ $SERVER_TYPE = "ftb" ]; then
  587.         SERVER_JAR=$SERVER_FTB_JAR
  588.         SERVER_ARGS=$SERVER_FTB_ARGS
  589.         JAVA_OPTS=$SERVER_FTB_JAVA_OPTS
  590.     else
  591.         SERVER_JAR=$SERVER_MOJANG_JAR
  592.         SERVER_ARGS=$SERVER_MOJANG_ARGS
  593.         JAVA_OPTS=$SERVER_MOJANG_JAVA_OPTS
  594.     fi
  595.  
  596.     # Make sure that the server software exists.
  597.     if [ ! -e $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR ]; then
  598.         printf "\nServer software not found, downloading it...\n"
  599.         update "server"
  600.     fi
  601.  
  602.     # Custom actions for tekkit
  603.     if [ $SERVER_TYPE = "tekkit" ] && [ ! -e "$WORLDS_LOCATION/$1/$SERVER_TEKKIT_JAR" ]; then
  604.         execute "cp -Rp $SERVER_LOCATION/$SERVER_TYPE/* $WORLDS_LOCATION/$1/" $USER_NAME
  605.     fi
  606.  
  607.     # Custom actions for feed-the-beast
  608.     if [ $SERVER_TYPE = "ftb" ] && [ ! -e "$WORLDS_LOCATION/$1/$SERVER_FTB_JAR" ]; then
  609.         execute "cp -Rp $SERVER_LOCATION/$SERVER_TYPE/* $WORLDS_LOCATION/$1/" $USER_NAME
  610.     fi
  611.  
  612.     # Make sure that the server.properties file holds the same values as
  613.     # the worlds.conf and motd.txt files.
  614.     setPropertiesValue $WORLDS_LOCATION/$1/server.properties "level-name" $1
  615.     setPropertiesValue $WORLDS_LOCATION/$1/server.properties "server-port" $(getPort $1)
  616.     setPropertiesValue $WORLDS_LOCATION/$1/server.properties "server-ip" $(getIP $1)
  617.     setPropertiesValue $WORLDS_LOCATION/$1/server.properties "motd" "$(getMOTD $1)"
  618.  
  619.     # Make a mirror image of the world directory if requested.
  620.     if [ $ENABLE_MIRROR -eq 1 ] && [ -d $MIRROR_PATH ]; then
  621.         execute "mkdir -p $MIRROR_PATH/$1" $USER_NAME
  622.         execute "cp -R $WORLDS_LOCATION/$1/* $MIRROR_PATH/$1" $USER_NAME
  623.         WORLD_DIR="$MIRROR_PATH/$1"
  624.     elif [ $ENABLE_MIRROR -eq 1 ]; then
  625.         printf "Error copying the world data to the mirror location, path not found.\n"
  626.         exit 1
  627.     fi
  628.     # Change to the world's directory.
  629.     cd $WORLD_DIR
  630.     # Make sure that the server.log file exists.
  631.     execute "touch server.log" $USER_NAME
  632.     # Erase the world's users file before starting up the world, in
  633.     # case it is not already empty for some reason.
  634.     execute "printf \"\" > \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
  635.     # Start the server.
  636.     execute "$SCREEN -dmS minecraft-$1 $JAVA $JAVA_OPTS -jar $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR $SERVER_ARGS" $USER_NAME
  637.     if [ $? -ne 0 ]; then
  638.         printf "Error starting the server.\n"
  639.         exit 1
  640.     fi
  641.     # Grab the Process ID of the world server.
  642.     PID=$(echo $(getProcessIDs $1) | cut -d ' ' -f2)
  643.     if [ ! -n "$PID" ]; then
  644.         printf "Error starting the server, the Process ID was not found.\n"
  645.         exit 1
  646.     fi
  647.     # Start the log processor.
  648.     tail -n0 -f --pid=$PID $WORLD_DIR/server.log | parseLog $1 &
  649.     # Create a lock file on RedHat and derivatives.
  650.     if [ -d "/var/lock/subsys" ]; then
  651.         touch /var/lock/subsys/minecraft_server
  652.     fi
  653. }
  654.  
  655. # Stop the world server.
  656. #
  657. # @param 1 The world server to stop.
  658. stop() {
  659.     local WORLD NUM
  660.     sendCommand $1 "stop"
  661.     # Erase the world's users file since we won't be able to catch
  662.     # anyone logging off.
  663.     execute "printf \"\" > \"$WORLDS_LOCATION/$1.users\"" $USER_NAME
  664.     # Synchronize the mirror image of the world prior to closing, if required.
  665.     if [ $ENABLE_MIRROR -eq 1 ] && [ -d $MIRROR_PATH ]; then
  666.         syncMirrorImage $1
  667.     fi
  668.     # Remove the lock file on Redhat and derivatives if all world servers are stopped.
  669.     if [ -e "/var/lock/subsys/minecraft_server" ]; then
  670.         NUM=0
  671.         for WORLD in $ALL_WORLDS; do
  672.             if [ "$1" != "$WORLD" ] && [ $(serverRunning $WORLD) -eq 1 ]; then
  673.                 NUM=$(($NUM + 1))
  674.             fi
  675.         done
  676.         if [ $NUM -eq 0 ]; then
  677.             rm -f /var/lock/subsys/minecraft_server
  678.         fi
  679.     fi
  680. }
  681.  
  682. # Forcibly stop the world server.
  683. #
  684. # @param 1 The world server to forcibly stop.
  685. forceStop() {
  686.     local PIDS
  687.     PIDS=$(getProcessIDs $1)
  688.     # Try to stop the server cleanly first.
  689.     stop $1
  690.     sleep 5
  691.     # Kill the process ids of the world server.
  692.     kill -9 $PIDS > /dev/null 2>&1
  693.     # Remove the lock file on Redhat and derivatives if it is still around.
  694.     rm -f /var/lock/subsys/minecraft_server
  695. }
  696.  
  697. # Backup the world server.
  698. #
  699. # @param 1 The world server to backup.
  700. worldBackup() {
  701.     # Make sure that the backup location exists.
  702.     execute "mkdir -p $BACKUP_LOCATION" $USER_NAME
  703.     # Create the backup.
  704.     execute "$RDIFF_BACKUP -v5 --print-statistics $WORLDS_LOCATION/$1 $BACKUP_LOCATION/$1 >> $BACKUP_LOG" $USER_NAME
  705.     # Cleanup old backups.
  706.     if [ $BACKUP_DURATION > 0 ]; then
  707.         execute "$RDIFF_BACKUP --remove-older-than ${BACKUP_DURATION}D --force $BACKUP_LOCATION/$1 >> $BACKUP_LOG" $USER_NAME
  708.     fi
  709. }
  710.  
  711. # Update the server software.
  712. updateServerSoftware() {
  713.     local SERVER_JAR SERVER_URL
  714.  
  715.     for SERVER_TYPE in $SERVER_TYPES; do
  716.         # Set the server location, and args
  717.         if [ $SERVER_TYPE = "mojang" ]; then
  718.             SERVER_URL=$SERVER_MOJANG_URL
  719.             SERVER_JAR=$SERVER_MOJANG_JAR
  720.         elif [ $SERVER_TYPE = "bukkit" ]; then
  721.             SERVER_URL=$SERVER_BUKKIT_URL
  722.             SERVER_JAR=$SERVER_BUKKIT_JAR
  723.         elif [ $SERVER_TYPE = "tekkit" ]; then
  724.             SERVER_URL=$SERVER_TEKKIT_URL
  725.             SERVER_JAR=$SERVER_TEKKIT_JAR
  726.         elif [ $SERVER_TYPE = "ftb" ]; then
  727.             SERVER_URL=$SERVER_FTB_URL
  728.             SERVER_JAR=$SERVER_FTB_JAR
  729.         fi
  730.  
  731.         execute "mkdir -p $SERVER_LOCATION/$SERVER_TYPE" $USER_NAME
  732.  
  733.         # Custom actions for tekkit
  734.         if [ $SERVER_TYPE = "tekkit" ]; then
  735.             printf "\nTekkit must be updated manually.\n"
  736.             # Backup the old server package.
  737.             # if [ -e "$SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR" ]; then
  738.             #   execute "tar zcf $SERVER_LOCATION/$SERVER_TYPE.old.tar.gz $SERVER_LOCATION/$SERVER_TYPE/" $USER_NAME
  739.             #   execute "rm -rf $SERVER_LOCATION/$SERVER_TYPE/" $USER_NAME
  740.             #   execute "rm $SERVER_LOCATION/$SERVER_TYPE.zip" $USER_NAME
  741.             # fi
  742.  
  743.             # Download the new server software.
  744.             # execute "$WGET -qO $SERVER_LOCATION/$SERVER_TYPE.zip $SERVER_URL" $USER_NAME
  745.  
  746.             # Check for error and restore backup if found.
  747.             # if [ $? -ne 0 ]; then
  748.             #   printf "\nError updating server software.\n"
  749.             #   if [ -e "$SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR.old.tar.gz" ]; then
  750.             #       execute "tar xzf $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR.old.tar.gz" $USER_NAME
  751.             #   fi
  752.             #   exit 1
  753.             # else
  754.             #   execute "unzip -qq $SERVER_LOCATION/$SERVER_TYPE.zip -d $SERVER_LOCATION/$SERVER_TYPE/" $USER_NAME
  755.                 #TODO - copy new update to all tekkit servers
  756.             #fi
  757.         # Custom actions for feed-the-beast
  758.         elif [ $SERVER_TYPE = "ftb" ]; then
  759.             printf "\nFeed the Beast must be updated manually.\n"
  760.         else
  761.             # Backup the old server jar.
  762.             if [ -e "$SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR" ]; then
  763.                 execute "mv -f $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR.old" $USER_NAME
  764.             fi
  765.  
  766.             # Download the new server software.
  767.             execute "$WGET -qO $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR $SERVER_URL" $USER_NAME
  768.  
  769.             # Check for error and restore backup if found.
  770.             if [ $? -ne 0 ]; then
  771.                 printf "\nError updating server software.\n"
  772.                 if [ -e "$SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR.old" ]; then
  773.                     execute "mv -f $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR.old $SERVER_LOCATION/$SERVER_TYPE/$SERVER_JAR" $USER_NAME
  774.                 fi
  775.                 exit 1
  776.             fi
  777.         fi
  778.     done
  779. }
  780.  
  781. # Update the c10t mapping software.  If already installed, compare version
  782. # numbers to avoid downloading the same version again.  Verify the sha1sum
  783. # of the downloaded .tar.gz file with that provided upstream.
  784. updateC10T() {
  785.     local ARCH VERSION OLD_VERSION SHA1SUM SHA1 SHA1_EXPECT
  786.     # Make sure the directory exists.
  787.     execute "mkdir -p $C10T_LOCATION" $USER_NAME
  788.     cd $C10T_LOCATION
  789.     # See what version of c10t is currently installed.
  790.     execute "touch CURRENT" $USER_NAME
  791.     OLD_VERSION=$(cat CURRENT)
  792.     # Determine the current upstream version number of c10t.
  793.     execute "$WGET -qO CURRENT \"$C10T_URL/CURRENT\"" $USER_NAME
  794.     if [ $? -ne 0 ]; then
  795.         printf "\nError determining the current version of c10t.\n"
  796.         exit 1
  797.     fi
  798.     VERSION=$(cat CURRENT)
  799.     # Compare upstream version number to the version installed, perform the
  800.     # update if necessary.
  801.     if [ "$VERSION" != "$OLD_VERSION" ]; then
  802.         # Determine the architecture of the system.
  803.         if [ $(getconf LONG_BIT) -eq 64 ]; then
  804.             ARCH="x86_64"
  805.         else
  806.             ARCH="x86"
  807.         fi
  808.         # Download the new version of c10t.
  809.         execute "$WGET -qO c10t.tar.gz \"$C10T_URL/c10t-$VERSION-linux-$ARCH.tar.gz\"" $USER_NAME
  810.         if [ $? -ne 0 ]; then
  811.             printf "\nError downloading c10t.\n"
  812.             exit 1
  813.         fi
  814.         # Verify the sha1 hash of the file.
  815.         SHA1SUM=$(which sha1sum)
  816.         if [ -e $SHA1SUM ]; then
  817.             # Download the sha1 hash file.
  818.             execute "$WGET -qO c10t.tar.gz.sha1 \"$C10T_URL/c10t-$VERSION-linux-$ARCH.tar.gz.sha1\"" $USER_NAME
  819.             if [ $? -ne 0 ]; then
  820.                 printf "\nError downloading the c10t sha1 hash file.\n"
  821.                 exit 1
  822.             fi
  823.             # Compare the sha1sum of the c10t archive with the
  824.             # expected value from the downloaded hash file.
  825.             SHA1=$($SHA1SUM c10t.tar.gz | cut -d ' ' -f 1)
  826.             SHA1_EXPECT=$(cat c10t.tar.gz.sha1 | cut -d ' ' -f 1)
  827.             if [ "$SHA1" != "$SHA1_EXPECT" ]; then
  828.                 printf "\nError downloading c10t, the sha1 hash does not match.\n"
  829.                 exit 1
  830.             fi
  831.         fi
  832.         # Uncompress the archive.
  833.         execute "tar xzf c10t.tar.gz --strip 1" $USER_NAME
  834.     fi
  835. }
  836.  
  837. # Update the pigmap mapping software.
  838. updatePigmap() {
  839.     # Remove old builds of pigmap.
  840.     rm -Rf $PIGMAP_LOCATION/build
  841.     # Make sure the pigmap build directory exists.
  842.     execute "mkdir -p $PIGMAP_LOCATION/build" $USER_NAME
  843.     cd $PIGMAP_LOCATION
  844.     # Download the new version of pigmap.
  845.     execute "$WGET -qO pigmap.tar.gz \"$PIGMAP_URL\"" $USER_NAME
  846.     if [ $? -ne 0 ]; then
  847.         printf "\nError downloading pigmap.\n"
  848.         exit 1
  849.     fi
  850.     # Uncompress the pigmap archive.
  851.     execute "tar xzf pigmap.tar.gz --strip 1 -C build" $USER_NAME
  852.     # Build the pigmap executable.
  853.     cd $PIGMAP_LOCATION/build
  854.     execute "make" $USER_NAME > /dev/null 2>&1
  855.     if [ $? -ne 0 ]; then
  856.         printf "\nError building pigmap.\n"
  857.         exit 1
  858.     fi
  859.     # Copy the resulting binary to the correct location.
  860.     execute "cp pigmap $PIGMAP_BIN" $USER_NAME
  861.     # Make sure the pigmap images directory exists.
  862.     execute "mkdir -p $PIGMAP_LOCATION/images" $USER_NAME
  863.     # Copy the pigmap images to the correct location.
  864.     execute "cp *.png $PIGMAP_LOCATION/images" $USER_NAME
  865.     # Make sure the pigmap template directory exists.
  866.     execute "mkdir -p $PIGMAP_LOCATION/template" $USER_NAME
  867.     # Copy the template files to the correct location.
  868.     execute "cp template.html style.css $PIGMAP_LOCATION/template" $USER_NAME
  869.     cd $PIGMAP_LOCATION
  870.     # Download the minecraft client so that we can extract the default skin.
  871.     execute "$WGET -qO minecraft.jar \"$MINECRAFT_CLIENT_URL\"" $USER_NAME
  872.     if [ $? -ne 0 ]; then
  873.         printf "\nError downloading the minecraft client.\n"
  874.         exit 1
  875.     fi
  876.     # Extract the images from the mincraft client.
  877.     execute "$JAR xf minecraft.jar terrain.png item/chest.png item/largechest.png item/enderchest.png" $USER_NAME
  878.     if [ $? -ne 0 ]; then
  879.         printf "\nError extracting the images from the minecraft client.\n"
  880.         exit 1
  881.     fi
  882.     # Move the minecraft client images to the correct location.
  883.     execute "mv terrain.png item/chest.png item/largechest.png item/enderchest.png $PIGMAP_LOCATION/images" $USER_NAME
  884.     execute "rmdir item"
  885. }
  886.  
  887. # Update a software package.  Uses the other update functions to actually
  888. # perform the update.
  889. #
  890. # @param 1 The package to update.
  891. update() {
  892.     case "$1" in
  893.         server)
  894.             updateServerSoftware
  895.         ;;
  896.         c10t)
  897.             updateC10T
  898.         ;;
  899.         pigmap)
  900.             updatePigmap
  901.         ;;
  902.         *)
  903.             printf "Unknown software package: $1\n"
  904.             exit 1
  905.         ;;
  906.     esac
  907. }
  908.  
  909. # Run c10t mapping software on the world.  Generates multiple image files in
  910. # the specified maps location.
  911. #
  912. # @param 1 The world server to map with c10t.
  913. c10t() {
  914.     local WORLD_DIR
  915.     WORLD_DIR="$WORLDS_LOCATION/$1"
  916.     # Use the mirror copy of the world directory if enabled.
  917.     if [ $ENABLE_MIRROR -eq 1 ] && [ -d $MIRROR_PATH ]; then
  918.         WORLD_DIR="$MIRROR_PATH/$1"
  919.     fi
  920.     # Make sure the maps directory exists.
  921.     execute "mkdir -p $C10T_MAPS_LOCATION/$1" $USER_NAME
  922.     # Make sure that the world files are actually there before mapping.
  923.     if [ -e "$WORLD_DIR/server.properties" ]; then
  924.         # Create various maps for the main world.
  925.         execute "LC_ALL='C' $C10T_BIN -s -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/surface.png" $USER_NAME
  926.         execute "LC_ALL='C' $C10T_BIN -s -c -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/caves.png" $USER_NAME
  927.         execute "LC_ALL='C' $C10T_BIN -s -c -H -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/caves_heightmap.png" $USER_NAME
  928.         execute "LC_ALL='C' $C10T_BIN -s -a -i 21 -H -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/lapis_heightmap.png" $USER_NAME
  929.         execute "LC_ALL='C' $C10T_BIN -s -a -i 56 -H -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/diamonds_heightmap.png" $USER_NAME
  930.         execute "LC_ALL='C' $C10T_BIN -s -a -i 4 -H -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/cobble_heightmap.png" $USER_NAME
  931.         execute "LC_ALL='C' $C10T_BIN -s -q -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/surface_oblique.png" $USER_NAME
  932.         execute "LC_ALL='C' $C10T_BIN -s -q -c -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/caves_oblique.png" $USER_NAME
  933.         execute "LC_ALL='C' $C10T_BIN -s -z -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/surface_isometric.png" $USER_NAME
  934.         execute "LC_ALL='C' $C10T_BIN -s -z -c -w $WORLD_DIR/$1 -o $C10T_MAPS_LOCATION/$1/caves_isometric.png" $USER_NAME
  935.         # Create various maps for the nether world if it exists.
  936.         if [ -d "$WORLD_DIR/$1/DIM-1" ]; then
  937.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -w $WORLD_DIR/$1/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface.png" $USER_NAME
  938.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -q -w $WORLD_DIR/$1/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface_oblique.png" $USER_NAME
  939.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -z -w $WORLD_DIR/$1/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface_isometric.png" $USER_NAME
  940.         elif [ -d "$WORLD_DIR/$1_nether/DIM-1" ]; then
  941.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -w $WORLD_DIR/$1_nether/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface.png" $USER_NAME
  942.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -q -w $WORLD_DIR/$1_nether/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface_oblique.png" $USER_NAME
  943.             execute "LC_ALL='C' $C10T_BIN -s -N --hell-mode -z -w $WORLD_DIR/$1_nether/DIM-1 -o $C10T_MAPS_LOCATION/$1/nether_surface_isometric.png" $USER_NAME
  944.         fi
  945.     fi
  946. }
  947.  
  948. # Run pigmap mapping software on the world.  Generates an index.html file using the Google Maps API.
  949. #
  950. # @param 1 The world server to map with c10t.
  951. pigmap() {
  952.     # Make sure the maps directory exists.
  953.     execute "mkdir -p $PIGMAP_MAPS_LOCATION/$1" $USER_NAME
  954.     # Make sure that the world files are actually there before mapping.
  955.     if [ -e "$WORLDS_LOCATION/$1/server.properties" ]; then
  956.         execute "$PIGMAP_BIN -i $WORLDS_LOCATION/$1/$1 -o $PIGMAP_MAPS_LOCATION/$1 -g $PIGMAP_LOCATION/images -m $PIGMAP_LOCATION/template -B 5 -T 5" $USER_NAME > /dev/null 2>&1
  957.         # Copy pigmap-default.html to index.html if the index.html file does not exist.
  958.         if [ ! -e "$PIGMAP_MAPS_LOCATION/$1/index.html" ]; then
  959.             execute "cp $PIGMAP_MAPS_LOCATION/$1/pigmap-default.html $PIGMAP_MAPS_LOCATION/$1/index.html" $USER_NAME
  960.         fi
  961.     fi
  962. }
  963.  
  964.  
  965. ## Begin.
  966.  
  967.  
  968. # Make sure that Java, Perl, Rsync, GNU Screen, and GNU Wget are installed.
  969. if [ ! -e $JAVA ] || [ ! -e $JAR ]; then
  970.     printf "ERROR: Java not found!\n"
  971.     printf "Try installing this with:\n"
  972.     printf "sudo apt-get install openjdk-7-jre\n"
  973.     exit 1
  974. fi
  975. if [ ! -e $PERL ]; then
  976.     printf "ERROR: Perl not found!\n"
  977.     printf "Try installing this with:\n"
  978.     printf "sudo apt-get install perl\n"
  979.     exit 1
  980. fi
  981. if [ $ENABLE_MIRROR -eq 1 ] && [ ! -e $RSYNC ]; then
  982.     printf "ERROR: Rsync not found!\n"
  983.     printf "Try installing this with:\n"
  984.     printf "sudo apt-get install rsync\n"
  985.     exit 1
  986. fi
  987. if [ ! -e $SCREEN ]; then
  988.     printf "ERROR: GNU Screen not found!\n"
  989.     printf "Try installing this with:\n"
  990.     printf "sudo apt-get install screen\n"
  991.     exit 1
  992. fi
  993. if [ ! -e $WGET ]; then
  994.     printf "ERROR: GNU Wget not found!\n"
  995.     printf "Try installing this with:\n"
  996.     printf "sudo apt-get install wget\n"
  997.     exit 1
  998. fi
  999. if [ ! -e $RDIFF_BACKUP ]; then
  1000.     printf "ERROR: rdiff-backup not found!\n"
  1001.     printf "Try installing this with:\n"
  1002.     printf "sudo apt-get install rdiff-backup\n"
  1003.     exit 1
  1004. fi
  1005.  
  1006. # Make sure that the minecraft user exists.
  1007. if [ ! -n "$(grep $USER_NAME /etc/passwd)" ]; then
  1008.     printf "ERROR: This script requires that a user account named $USER_NAME exist on this system.\n"
  1009.     printf "Either modify the USER_NAME variable in this script, or try adding this user:\n"
  1010.     printf "sudo adduser $USER_NAME\n"
  1011.     exit 1
  1012. fi
  1013.  
  1014. # Warn if the script is running with the wrong user.
  1015. if [ $(id -u) -ne 0 ] && [ "$(whoami)" != "$USER_NAME" ]; then
  1016.     printf "WARNING: This script appears to have been started by the wrong user.\n"
  1017.     printf "Expected to find the user: $USER_NAME.  You can try to log on to this user:\n"
  1018.     printf "su $USER_NAME\n"
  1019.     exit 1
  1020. fi
  1021.  
  1022. # Generate a default worlds.conf file if it does not already exist.
  1023. if [ ! -e $WORLDS_CONF ]; then
  1024.     execute "printf \"# Minecraft world configuration file\n\" > $WORLDS_CONF" $USER_NAME
  1025.     execute "printf \"# <world>\t<server>\t<port>\t<ip>\n\" >> $WORLDS_CONF" $USER_NAME
  1026.     execute "printf \"$DEFAULT_WORLD\t$DEFAULT_SERVER\t$DEFAULT_PORT\t$DEFAULT_IP\n\" >> $WORLDS_CONF" $USER_NAME
  1027. fi
  1028.  
  1029. # Make sure that the server software exists.
  1030. if [ ! -e $SERVER_LOCATION/$SERVER_JAR ]; then
  1031.     printf "Server software not found, downloading it...\n"
  1032.     update "server"
  1033. fi
  1034.  
  1035. # Update old worlds.conf files.
  1036. if [ -e $WORLDS_CONF ] && [ "$(grep '<eport>' $WORLDS_CONF)" != ""  ]; then
  1037.     execute "cp $WORLDS_CONF $WORLDS_CONF.old" $USER_NAME
  1038.     execute "$PERL -i -ne 'if (\$_ =~ /#\s*<world>\s+<eport>\s+<iport>\s+<ip>/) { print \"# <world>\t<port>\t<ip>\n\"; } else { print; }' $WORLDS_CONF" $USER_NAME
  1039.     execute "$PERL -i -ne 'if (\$_ =~ /(\w+)\s+(\d+)\s+\d+\s*([\d\.]*)/) { printf \"%s\t%d\t%s\n\",\$1,\$2,\$3; } else { print; }' $WORLDS_CONF" $USER_NAME
  1040. fi
  1041.  
  1042. # Grab the list of worlds.
  1043. ALL_WORLDS=$(getWorlds)
  1044.  
  1045. # Respond to the command line arguments.
  1046. case "$1" in
  1047.     start)
  1048.         # Figure out which worlds to start.
  1049.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1050.         # Start each world requested, if not already running.
  1051.         printf "Starting Minecraft Server:"
  1052.         for WORLD in $WORLDS; do
  1053.             if [ $(serverRunning $WORLD) -eq 0 ]; then
  1054.                 printf " $WORLD"
  1055.                 start $WORLD
  1056.             fi
  1057.         done
  1058.         printf "\n"
  1059.     ;;
  1060.     stop|force-stop)
  1061.         # Figure out which worlds to stop.
  1062.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1063.         # Stop each world requested, if running.
  1064.         printf "Stopping Minecraft Server:"
  1065.         for WORLD in $WORLDS; do
  1066.             # Try to stop the world cleanly.
  1067.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1068.                 printf " $WORLD"
  1069.                 sendCommand $WORLD "say The server is about to go down."
  1070.                 sendCommand $WORLD "save-all"
  1071.                 sendCommand $WORLD "save-off"
  1072.                 sendCommand $WORLD "say The server is going down in 5 seconds..."
  1073.                 sleep 5
  1074.                 if [ "$1" = "force-stop" ]; then
  1075.                     forceStop $WORLD
  1076.                 else
  1077.                     stop $WORLD
  1078.                 fi
  1079.                 sleep 5
  1080.             fi
  1081.         done
  1082.         printf "\n"
  1083.     ;;
  1084.     restart|reload|force-restart|force-reload)
  1085.         # Figure out which worlds to restart.
  1086.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1087.         # Restart each world requested, start those not already running.
  1088.         printf "Restarting Minecraft Server:"
  1089.         for WORLD in $WORLDS; do
  1090.             printf " $WORLD"
  1091.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1092.                 sendCommand $WORLD "say The server is about to restart."
  1093.                 sendCommand $WORLD "save-all"
  1094.                 sendCommand $WORLD "save-off"
  1095.                 sendCommand $WORLD "say Restarting in 5 seconds..."
  1096.                 sleep 5
  1097.                 if [ "$(echo \"$1\" | cut -d '-' -f1)" = "force" ]; then
  1098.                     forceStop $WORLD
  1099.                 else
  1100.                     stop $WORLD
  1101.                 fi
  1102.                 sleep 5
  1103.             fi
  1104.             start $WORLD
  1105.         done
  1106.         printf "\n"
  1107.     ;;
  1108.     status|show)
  1109.         # Figure out which worlds to show the status for.
  1110.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1111.         # Show the status of each world requested.
  1112.         printf "Minecraft Server Status:\n"
  1113.         for WORLD in $WORLDS; do
  1114.             printf "  $WORLD: "
  1115.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1116.                 printf "running (%d users online).\n" $(cat $WORLDS_LOCATION/$WORLD.users | wc -l)
  1117.             else
  1118.                 printf "not running.\n"
  1119.             fi
  1120.         done
  1121.     ;;
  1122.     sync|synchronize)
  1123.         # Make sure the Mirror image option is enabled.
  1124.         if [ $ENABLE_MIRROR -ne 1 ]; then
  1125.             printf "Mirror image option not enabled, unable to synchronize.\n";
  1126.             exit 1
  1127.         fi
  1128.         # Figure out which worlds to synchronize.
  1129.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1130.         # Synchronize the images for each world.
  1131.         printf "Synchronizing Minecraft Server:"
  1132.         for WORLD in $WORLDS; do
  1133.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1134.                 printf " $WORLD"
  1135.                 sendCommand $WORLD "save-off"
  1136.                 syncMirrorImage $WORLD
  1137.                 sendCommand $WORLD "save-on"
  1138.             fi
  1139.         done
  1140.         printf "\n"
  1141.     ;;
  1142.     send)
  1143.         # Check for the world command line argument.
  1144.         if [ -n "$2" ] && [ $(listContains $2 "$ALL_WORLDS") -eq 1 ] && [ -n "$3" ]; then
  1145.             WORLD=$2
  1146.             shift 2
  1147.             printf "Send command to world $WORLD: $*\n"
  1148.             sendCommand $WORLD "$*"
  1149.         else
  1150.             printf "Usage:  $0 $1 <world> <command>\n"
  1151.             printf "   ie:  $0 $1 world say Hello World!\n"
  1152.             exit 1
  1153.         fi
  1154.     ;;
  1155.     screen)
  1156.         # Check for the world command line argument.
  1157.         if [ -n "$2" ] && [ $(listContains $2 "$ALL_WORLDS") -eq 1 ]; then
  1158.             displayScreen $2
  1159.         else
  1160.             if [ -n "$2" ]; then
  1161.                 printf "Minecraft world $2 not found!\n"
  1162.             else
  1163.                 printf "Minecraft world not provided!\n"
  1164.             fi
  1165.             printf "  Usage:  $0 $1 <world>\n"
  1166.             exit 1
  1167.         fi
  1168.     ;;
  1169.     watch)
  1170.         # Check for the world command line argument.
  1171.         if [ -n "$2" ] && [ $(listContains $2 "$ALL_WORLDS") -eq 1 ]; then
  1172.             watchLog $2
  1173.         else
  1174.             if [ -n "$2" ]; then
  1175.                 printf "Minecraft world $2 not found!\n"
  1176.             else
  1177.                 printf "Minecraft world not provided!\n"
  1178.             fi
  1179.             printf "  Usage:  $0 $1 <world>\n"
  1180.             exit 1
  1181.         fi
  1182.     ;;
  1183.     backup)
  1184.         # Figure out which worlds to backup.
  1185.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1186.         # Backup each world requested.
  1187.         printf "Backing up Minecraft Server:"
  1188.         for WORLD in $WORLDS; do
  1189.             printf " $WORLD"
  1190.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1191.                 sendCommand $WORLD "say Backing up the world."
  1192.                 sendCommand $WORLD "save-all"
  1193.                 sendCommand $WORLD "save-off"
  1194.                 sleep 20
  1195.                 worldBackup $WORLD
  1196.                 sendCommand $WORLD "save-on"
  1197.                 sendCommand $WORLD "say Backup complete."
  1198.             else
  1199.                 worldBackup $WORLD
  1200.             fi
  1201.         done
  1202.         printf "\n"
  1203.     ;;
  1204.     update)
  1205.         printf "Updating the Minecraft Server software...\n"
  1206.         # Figure out which packages to update.
  1207.         UPDATE_PACKAGES=$(checkOptionalArgument "$UPDATE_PACKAGES" $0 $1 $2)
  1208.         # If the server software is being updated, stop all of
  1209.         # the world servers and backup the worlds.
  1210.         if [ $(listContains "server" "$UPDATE_PACKAGES") -eq 1 ]; then
  1211.             printf "Stopping Minecraft Server:"
  1212.             for WORLD in $ALL_WORLDS; do
  1213.                 if [ $(serverRunning $WORLD) -eq 1 ]; then
  1214.                     printf " $WORLD"
  1215.                     sendCommand $WORLD "say The server software is being updated."
  1216.                     sendCommand $WORLD "say Server restart is imminent."
  1217.                     sendCommand $WORLD "save-all"
  1218.                     sendCommand $WORLD "save-off"
  1219.                     sendCommand $WORLD "say Restarting in 5 seconds."
  1220.                     sleep 5
  1221.                     stop $WORLD
  1222.                 fi
  1223.             done
  1224.             printf "\n"
  1225.             printf "Backing up Minecraft Server:"
  1226.             for WORLD in $ALL_WORLDS; do
  1227.                 printf " $WORLD"
  1228.                 worldBackup $WORLD
  1229.             done
  1230.             printf "\n"
  1231.         fi
  1232.         # Update each software package requested.
  1233.         printf "Updating software package:"
  1234.         for PACKAGE in $UPDATE_PACKAGES; do
  1235.             printf " $PACKAGE"
  1236.             update $PACKAGE
  1237.         done
  1238.         printf "\n"
  1239.         if [ $(listContains "server" "$UPDATE_PACKAGES") -eq 1 ]; then
  1240.             printf "Starting Minecraft Server:"
  1241.             for WORLD in $ALL_WORLDS; do
  1242.                 printf " $WORLD"
  1243.                 start $WORLD
  1244.             done
  1245.             printf "\n"
  1246.         fi
  1247.     ;;
  1248.     c10t)
  1249.         # Make sure that the c10t software exists.
  1250.         if [ ! -e $C10T_BIN ]; then
  1251.             printf "c10t software not found, downloading it...\n"
  1252.             update "c10t"
  1253.         fi
  1254.         # Figure out which worlds to map.
  1255.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1256.         # Run c10t on each world requested.
  1257.         printf "Running c10t mapping:"
  1258.         for WORLD in $WORLDS; do
  1259.             printf " $WORLD"
  1260.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1261.                 sendCommand $WORLD "say The world is about to be mapped with c10t."
  1262.                 sendCommand $WORLD "save-all"
  1263.                 sendCommand $WORLD "save-off"
  1264.                 sleep 20
  1265.                 worldBackup $WORLD
  1266.                 c10t $WORLD
  1267.                 sendCommand $WORLD "save-on"
  1268.                 sendCommand $WORLD "say Mapping is complete.  You can access the maps at:"
  1269.                 sendCommand $WORLD "say $C10T_MAPS_URL/$WORLD"
  1270.             else
  1271.                 worldBackup $WORLD
  1272.                 c10t $WORLD
  1273.             fi
  1274.         done
  1275.         printf "\n"
  1276.     ;;
  1277.     map|pigmap)
  1278.         # Make sure that the pigmap software exists.
  1279.         if [ ! -e $PIGMAP_BIN ]; then
  1280.             printf "pigmap software not found, downloading it...\n"
  1281.             update "pigmap"
  1282.         fi
  1283.         # Figure out which worlds to map.
  1284.         WORLDS=$(checkOptionalArgument "$ALL_WORLDS" $0 $1 $2)
  1285.         # Run pigmap on each world requested.
  1286.         printf "Running pigmap mapping:"
  1287.         for WORLD in $WORLDS; do
  1288.             printf " $WORLD"
  1289.             if [ $(serverRunning $WORLD) -eq 1 ]; then
  1290.                 sendCommand $WORLD "say The world is about to be mapped with pigmap."
  1291.                 sendCommand $WORLD "save-all"
  1292.                 sendCommand $WORLD "save-off"
  1293.                 sleep 20
  1294.                 worldBackup $WORLD
  1295.                 pigmap $WORLD
  1296.                 sendCommand $WORLD "save-on"
  1297.                 sendCommand $WORLD "say Mapping is complete.  You can access the maps at:"
  1298.                 sendCommand $WORLD "say $PIGMAP_MAPS_URL/$WORLD"
  1299.             else
  1300.                 worldBackup $WORLD
  1301.                 pigmap $WORLD
  1302.             fi
  1303.         done
  1304.         printf "\n"
  1305.     ;;
  1306.     *)
  1307.         printf "Usage: $0 {start|stop|force-stop|restart|force-restart|status|sync|send|screen|watch|backup|update|map} {Optional: world or software package}\n"
  1308.         exit 1
  1309.     ;;
  1310. esac
  1311. exit 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement