mclaunch 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +30 -0
- data/Rakefile +1 -0
- data/bin/mclaunch +3 -0
- data/lib/mclaunch/commands.rb +155 -0
- data/lib/mclaunch/runtime.rb +143 -0
- data/lib/mclaunch/tools.rb +323 -0
- data/lib/mclaunch/version.rb +3 -0
- data/lib/mclaunch.rb +347 -0
- data/mclaunch.gemspec +19 -0
- metadata +58 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 odie
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Mclaunch
|
2
|
+
|
3
|
+
mclaunch is a launcher for a craftbukkit server, that runs the
|
4
|
+
craftbukkit server in either a tmux or a GNU screen session.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'mclaunch'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install mclaunch
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
type "mclaunch --help" in a terminal for help
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
|
26
|
+
1. Fork it
|
27
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
28
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
29
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
30
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/mclaunch
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
module Mclaunch
|
2
|
+
# Commands to issue on minecraft server
|
3
|
+
|
4
|
+
class Commands
|
5
|
+
def initialize(runtime=nil, options=nil, tools=nil)
|
6
|
+
@runtime = runtime
|
7
|
+
@options = options
|
8
|
+
@tools = tools
|
9
|
+
@quiet = @options[:quiet]
|
10
|
+
@debug = @options[:debug]
|
11
|
+
end #end initialize
|
12
|
+
|
13
|
+
#setter for @runtime
|
14
|
+
def set_runtime(runtime)
|
15
|
+
@runtime = runtime
|
16
|
+
end #end set_runtime(runtime)
|
17
|
+
|
18
|
+
#setter for @options
|
19
|
+
def set_options(options)
|
20
|
+
@options = options
|
21
|
+
end #end set_options(options)
|
22
|
+
|
23
|
+
#Reload command
|
24
|
+
def reload
|
25
|
+
puts "sending reload command to server" unless @quiet
|
26
|
+
@runtime.send_command("reload")
|
27
|
+
end #end reload
|
28
|
+
|
29
|
+
#save-on command
|
30
|
+
def save_on
|
31
|
+
puts "sending save-on command to server" unless @quiet
|
32
|
+
@runtime.send_command("save-on")
|
33
|
+
end #end save_on
|
34
|
+
|
35
|
+
#save-off command
|
36
|
+
def save_off
|
37
|
+
puts "sending save-off command to server" unless @quiet
|
38
|
+
@runtime.send_command("save-off")
|
39
|
+
end #end save_off
|
40
|
+
|
41
|
+
#save-all command
|
42
|
+
def save_all
|
43
|
+
puts "sending save-all command to server" unless @quiet
|
44
|
+
@runtime.send_command("save-all")
|
45
|
+
end #end save_all
|
46
|
+
|
47
|
+
#defaultgamemode command
|
48
|
+
def change_gamemode(mode)
|
49
|
+
raise "\n False command: #{mode}\n\n Use:\n 0 or survival\n 1 or creative\n 2 or adventure" unless mode =~ /^([0-2]|(survival|creative|adventure))$/
|
50
|
+
puts "changing gamemode to \"#{mode}\"" unless @quiet
|
51
|
+
@runtime.send_command("defaultgamemode #{mode.to_i}") if mode =~ /^[0-2]$/
|
52
|
+
@runtime.send_command("defaultgamemode #{mode.to_s}") if mode =~ /^(survival|creative|adventure)$/
|
53
|
+
end #end change_gamemode(mode)
|
54
|
+
|
55
|
+
#difficulty command
|
56
|
+
def change_difficulty(difficulty)
|
57
|
+
raise "\n Command only available with minecraft-server.jar" unless @options[:server_executable].eql? "minecraft-server.jar"
|
58
|
+
raise "\n False command: #{difficulty}\n\n Use:\n 0 or peaceful\n 1 or easy\n 2 or normal\n 3 or hard" unless difficulty =~ /^([0-3]|(peaceful|easy|normal|hard))$/
|
59
|
+
puts "changing difficulty to \"#{difficulty}\"" unless @quiet
|
60
|
+
@runtime.send_command("difficulty #{difficulty.to_i}") if difficulty =~ /^[0-3]$/
|
61
|
+
@runtime.send_command("difficulty #{difficulty.to_s}") if difficulty =~ /^(peaceful|easy|normal|hard)i$/
|
62
|
+
end #end change_difficulty(difficulty)
|
63
|
+
|
64
|
+
#op command
|
65
|
+
def op(player)
|
66
|
+
cmd = "op #{player}"
|
67
|
+
online_mode = @tools.to_boolean(@runtime.get_server_properties['online-mode'])
|
68
|
+
is_player = @tools.is_minecraft_player?(player)
|
69
|
+
puts "adding \"#{player}\" to #{@options[:server_runtime_directory]}opts.txt" unless @quiet
|
70
|
+
if online_mode
|
71
|
+
@runtime.send_command(cmd) if is_player && @tools.is_op?(player)
|
72
|
+
else
|
73
|
+
@runtime.send_command(cmd)
|
74
|
+
end
|
75
|
+
end #end op(player)
|
76
|
+
|
77
|
+
#deop command
|
78
|
+
def deop(player)
|
79
|
+
puts "removing #{player} from #{@options[:server_runtime_directory]}opts.txt" unless @quiet
|
80
|
+
@runtime.send_command("deop #{player}") if @tools.is_op?(player)
|
81
|
+
end #end deop(player)
|
82
|
+
|
83
|
+
#kick player command
|
84
|
+
def kick_player(player)
|
85
|
+
puts "kicking #{player} from server" unless @quiet
|
86
|
+
@runtime.send_command("kick #{player}")
|
87
|
+
end #end kick_player(player, reason=nil)
|
88
|
+
|
89
|
+
#ban player command
|
90
|
+
def ban_player(player, reason=nil)
|
91
|
+
puts "banning #{player} from server" unless @quiet
|
92
|
+
reason_string = reason if reason.is_a?(String)
|
93
|
+
reason_string = @tools.array_to_string(reason) if reason.is_a?(Array)
|
94
|
+
@runtime.send_command("ban #{player} #{reason_string}")
|
95
|
+
end #end ban_player(player, reason=nil)
|
96
|
+
|
97
|
+
#ban ip command
|
98
|
+
def ban_ip(ip, reason=nil)
|
99
|
+
raise "This is not an IP address!" unless ip =~/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/
|
100
|
+
puts "banning \"#{ip}\ from server" unless @quiet
|
101
|
+
reason_string = reason if reason.is_a?(String)
|
102
|
+
reason_string = @tools.array_to_string(reason) if reason.is_a?(Array)
|
103
|
+
@runtime.send_command("ban-ip #{ip} #{reason_string}")
|
104
|
+
end #end ban_ip(ip, reason=nil)
|
105
|
+
|
106
|
+
#pardon player command
|
107
|
+
def pardon_player(player)
|
108
|
+
puts "removing ban for \"#{player}\"." unless @quiet
|
109
|
+
@runtime.send_command("pardon #{player}")
|
110
|
+
end #end pardon_player(player, reason=nil)
|
111
|
+
|
112
|
+
#pardon ip command
|
113
|
+
def pardon_ip(ip)
|
114
|
+
raise "This is not an IP address!" unless ip =~/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/
|
115
|
+
puts "removing ban for \"#{ip}\"." unless @quiet
|
116
|
+
@runtime.send_command("pardon-ip #{ip}")
|
117
|
+
end #end pardon_ip(ip, reason=nil)
|
118
|
+
|
119
|
+
#whitelist <on|off|list> command
|
120
|
+
def whitelist(cmd)
|
121
|
+
raise "Available commands are: on, off, list" unless cmd =~ /^(on|off|list)$/
|
122
|
+
unless @quiet
|
123
|
+
puts "turning whitelist on." if cmd.eql?("on")
|
124
|
+
puts "turning whitelist off." if cmd.eql?("off")
|
125
|
+
end
|
126
|
+
@runtime.send_command("whitelist #{cmd}")
|
127
|
+
end #end whitelist(cmd)
|
128
|
+
|
129
|
+
#whitelist add command
|
130
|
+
def whitelist_add(player)
|
131
|
+
cmd = "whitelist add #{player}"
|
132
|
+
online_mode = @tools.to_boolean(@runtime.get_server_properties['online-mode'])
|
133
|
+
is_player = @tools.is_minecraft_player?(player)
|
134
|
+
puts "adding \"#{player}\" to whitelist" unless @quiet
|
135
|
+
if online_mode
|
136
|
+
@runtime.send_command(cmd) if is_player
|
137
|
+
else
|
138
|
+
@runtime.send_command(cmd)
|
139
|
+
end
|
140
|
+
end #end whitelist_add(player)
|
141
|
+
|
142
|
+
#whitelist remove command
|
143
|
+
def whitelist_remove(player)
|
144
|
+
cmd = "whitelist remove #{player}"
|
145
|
+
online_mode = @tools.to_boolean(@runtime.get_server_properties['online-mode'])
|
146
|
+
is_player = @tools.is_minecraft_player?(player)
|
147
|
+
puts "removing \"#{player}\" to whitelist" unless @quiet
|
148
|
+
if online_mode
|
149
|
+
@runtime.send_command(cmd) if is_player && @tools.is_op?(player)
|
150
|
+
else
|
151
|
+
@runtime.send_command(cmd)
|
152
|
+
end
|
153
|
+
end #end whitelist_remove(player)
|
154
|
+
end #end Commands
|
155
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Mclaunch
|
2
|
+
# Runtime Class for Minecraft server
|
3
|
+
|
4
|
+
extend self
|
5
|
+
require 'logrotate'
|
6
|
+
require 'mclaunch'
|
7
|
+
|
8
|
+
class Runtime
|
9
|
+
def initialize(options=nil)
|
10
|
+
@options = options
|
11
|
+
@start_cmd = "java -Xms#{@options[:server_min_heap_memory]} -Xmx#{@options[:server_max_heap_memory]} #{@options[:server_additional_options]} -jar #{@options[:server_executable]}"
|
12
|
+
@path = options[:server_runtime_directory]
|
13
|
+
@quiet = @options[:quiet]
|
14
|
+
@debug = @options[:debug]
|
15
|
+
@multiplexer = @options[:server_terminal_multiplexer]
|
16
|
+
@multiplexer_session_name = @options[:server_terminal_multiplexer_name]
|
17
|
+
@multiplexer_session = @options[:server_terminal_multiplexer_session]
|
18
|
+
end #end initialize
|
19
|
+
|
20
|
+
#setter for @options
|
21
|
+
def set_options(options)
|
22
|
+
@options = options
|
23
|
+
end #end set_options(options)
|
24
|
+
|
25
|
+
#Run server
|
26
|
+
def run
|
27
|
+
puts "starting server now." unless @quiet
|
28
|
+
if @debug
|
29
|
+
puts "Command: #{@start_cmd}"
|
30
|
+
puts "Multiplexer: #{@multiplexer}"
|
31
|
+
end
|
32
|
+
Dir.chdir(@path)
|
33
|
+
create_tmux_session(@multiplexer_session_name)
|
34
|
+
start
|
35
|
+
sleep 1
|
36
|
+
if is_running?
|
37
|
+
puts "server is running now." unless @quiet
|
38
|
+
else
|
39
|
+
run
|
40
|
+
end
|
41
|
+
end #end run
|
42
|
+
|
43
|
+
#start server
|
44
|
+
def start
|
45
|
+
send_command(@start_cmd)
|
46
|
+
end #end start
|
47
|
+
|
48
|
+
#stop server
|
49
|
+
def stop
|
50
|
+
send_command("stop")
|
51
|
+
sleep 5
|
52
|
+
end #end stop
|
53
|
+
|
54
|
+
#halt
|
55
|
+
def halt
|
56
|
+
puts "halting server now." unless @quiet
|
57
|
+
stop
|
58
|
+
log_rotate
|
59
|
+
kill_tmux_session(@multiplexer_session_name)
|
60
|
+
puts "server haltet." unless @quiet
|
61
|
+
end #end halt
|
62
|
+
|
63
|
+
def restart
|
64
|
+
puts "restarting server now." unless @quiet
|
65
|
+
stop
|
66
|
+
start
|
67
|
+
if is_running?
|
68
|
+
puts "server restart complete" unless @quiet
|
69
|
+
else
|
70
|
+
run
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#check is server is running
|
75
|
+
def is_running?
|
76
|
+
puts "check if server is running" if @debug
|
77
|
+
return true if `ps ax | grep -v grep | egrep "(minecraft|craftbukkit).jar" | wc -l`.to_i > 0
|
78
|
+
end #end is_running?
|
79
|
+
|
80
|
+
#Send a command to a running server
|
81
|
+
def send_command(cmd)
|
82
|
+
puts "sending \"#{cmd}\" to #{@multiplexer} session \"#{@multiplexer_session_name}\"" if @debug
|
83
|
+
`tmux -S #{@multiplexer_session} send -t #{@multiplexer_session_name} "#{cmd}" ENTER` if @multiplexer.eql?("tmux")
|
84
|
+
`screen -p 0 -S #{@multiplexer_session_name} -X eval 'stuff \"#{cmd}\"'\15` if @multiplexer.eql?("screen")
|
85
|
+
end #end send_command(cmd)
|
86
|
+
|
87
|
+
#Send a chat message as a server say command
|
88
|
+
def send_message(msg)
|
89
|
+
msg = "say #{msg}"
|
90
|
+
puts "sending \"#{msg}\" as server chat message" if @debug
|
91
|
+
send_command(msg)
|
92
|
+
end #end send_message(msg)
|
93
|
+
|
94
|
+
#Create a tmux session for the server to run in
|
95
|
+
def create_tmux_session(name)
|
96
|
+
puts "connecting to or creating a new #{@multiplexer} session now" if @debug
|
97
|
+
`tmux -S #{@multiplexer_session} has-session -t #{name} > /dev/null 2>&1 || tmux -S #{@multiplexer_session} new-session -s #{name} -d` if @multiplexer.eql?("tmux")
|
98
|
+
`ps ax | grep -v grep | grep SCREEN | grep craftbukkit 2>&1 || screen -dmS #{name}` if @multiplexer.eql?("screen")
|
99
|
+
puts "multiplexer session should be started now" if @debug
|
100
|
+
sleep 0.1
|
101
|
+
File.chmod(01000, @multiplexer_session) if @Multiplexer.eql?("tmux")
|
102
|
+
end #end create_tmux_session(name)
|
103
|
+
|
104
|
+
#Kill a tmux session
|
105
|
+
def kill_tmux_session(name)
|
106
|
+
puts "killing #{@multiplexer} sessinon now" if @debug
|
107
|
+
case @multiplexer
|
108
|
+
when "screen"
|
109
|
+
send_command("exit") unless is_running?
|
110
|
+
when "tmux"
|
111
|
+
`tmux -S #{@multiplexer_session} kill-session -t #{@multiplexer_session_name}`
|
112
|
+
end
|
113
|
+
halt if is_running?
|
114
|
+
end #end kill_tmux_session(name)
|
115
|
+
|
116
|
+
#Rotate the server log file
|
117
|
+
def log_rotate
|
118
|
+
puts "Rotating logfile now" if @debug
|
119
|
+
options = {
|
120
|
+
:gzip => true,
|
121
|
+
:count => 5,
|
122
|
+
}
|
123
|
+
LogRotate.rotate_file("/home/odie/bukkit/server/server.log", options)
|
124
|
+
end #end log_rotate
|
125
|
+
|
126
|
+
#Get server.properties file from server runtime directory
|
127
|
+
def get_server_properties
|
128
|
+
props = Hash[File.read("#{@options[:server_runtime_directory]}server.properties").split("\n").map{|i|i.split('=') unless i =~ /^#.*$/}]
|
129
|
+
if @debug
|
130
|
+
puts "---"
|
131
|
+
puts "Server properties: "
|
132
|
+
puts
|
133
|
+
props.each do |k,v|
|
134
|
+
puts "\t#{k}=#{v}"
|
135
|
+
end
|
136
|
+
puts "---"
|
137
|
+
puts
|
138
|
+
end
|
139
|
+
props
|
140
|
+
end #end get_server_properties
|
141
|
+
|
142
|
+
end #end Runtime
|
143
|
+
end
|
@@ -0,0 +1,323 @@
|
|
1
|
+
module Mclaunch
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'progressbar'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
class Tools
|
10
|
+
def initialize(runtime, options)
|
11
|
+
@runtime = runtime
|
12
|
+
@options = options
|
13
|
+
@server_properties = @runtime.get_server_properties
|
14
|
+
@versions = {}
|
15
|
+
@debug = @options[:debug]
|
16
|
+
@quiet = @options[:quiet]
|
17
|
+
@xml_document = nil
|
18
|
+
@craftbukkit_version_regex = /^[1-9]\.[0-9]\.[0-9]-R[0-9]\.[0-9]$/
|
19
|
+
@commands = nil
|
20
|
+
end #end initialize
|
21
|
+
|
22
|
+
#Method desctiption
|
23
|
+
def commands(commands=nil)
|
24
|
+
@commands = commands
|
25
|
+
@commands unless @commands
|
26
|
+
end #end commands(commands=nil)
|
27
|
+
|
28
|
+
#Check online if Player name is a valid minecraft username if server is in online mode
|
29
|
+
def is_minecraft_player?(player)
|
30
|
+
if to_boolean(@server_properties['online-mode']) == true
|
31
|
+
uri = URI.parse("https://minecraft.net/haspaid.jsp?user=#{player}")
|
32
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
33
|
+
http.use_ssl = true
|
34
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
35
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
36
|
+
response = http.request(request)
|
37
|
+
to_boolean response.body
|
38
|
+
end
|
39
|
+
end #end is_minecraft_player?(player, cmd)
|
40
|
+
|
41
|
+
#check if player is in ops.txt
|
42
|
+
def is_op?(player)
|
43
|
+
puts "checking if \"#{player}\" is op." if @debug
|
44
|
+
ops = File.new("#{@options[:server_runtime_directory]}ops.txt", "r")
|
45
|
+
op = false
|
46
|
+
ops.each_line do |l|
|
47
|
+
op = true if l.gsub("\n", "").eql?(player)
|
48
|
+
end
|
49
|
+
op
|
50
|
+
end #end is_op?
|
51
|
+
|
52
|
+
def is_symlink_or_file(path)
|
53
|
+
File.exist?(path) || File.symlink?(path)
|
54
|
+
end #end is_symlink_or_file(path)
|
55
|
+
|
56
|
+
#Convert String to Boolean
|
57
|
+
def to_boolean(s)
|
58
|
+
s.eql?"true"
|
59
|
+
end #end to_boolean(s)
|
60
|
+
|
61
|
+
#Convert a array into a String.
|
62
|
+
def array_to_string(array, delimiter=" ")
|
63
|
+
tmp = ""
|
64
|
+
array.each do |s|
|
65
|
+
tmp += s+delimiter
|
66
|
+
end
|
67
|
+
tmp
|
68
|
+
end #end array_to_string(array, delimiter=" ")
|
69
|
+
|
70
|
+
def get_worlds
|
71
|
+
worlds = {}
|
72
|
+
dir = Dir.new(@options[:server_world_directory])
|
73
|
+
dir.each do |world|
|
74
|
+
unless world =~ /^(\.|\.\.)$/
|
75
|
+
ramdisk = false
|
76
|
+
ramdisk = true if File.exists?("#{@options[:server_world_directory]}#{world}/ramdisk")
|
77
|
+
worlds[world] = ramdisk
|
78
|
+
if @debug
|
79
|
+
puts " world: #{world} runs from ramdisk" if ramdisk
|
80
|
+
puts " world: #{world} runs from disk" unless ramdisk
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end #end dir.each
|
84
|
+
return worlds
|
85
|
+
end #end get_worlds
|
86
|
+
|
87
|
+
#Create world Symlinks
|
88
|
+
def worlds_create_symlinks
|
89
|
+
worlds = get_worlds
|
90
|
+
worlds.each do |world,ramdisk|
|
91
|
+
src = "#{@options[:server_world_directory]}#{world}"
|
92
|
+
src = "#{@options[:server_ramdisk_directory]}#{world}" if ramdisk
|
93
|
+
dst = "#{@options[:server_runtime_directory]}#{world}"
|
94
|
+
File.unlink(dst) if File.symlink?(dst)
|
95
|
+
File.symlink(src,dst)
|
96
|
+
puts "Symlink created for: #{world}" unless @quiet
|
97
|
+
puts "Source: #{src}\nDestination: #{dst}" if @debug
|
98
|
+
end
|
99
|
+
end #end worlds_create_symlinks
|
100
|
+
|
101
|
+
def world_ramdisk_state(world_name)
|
102
|
+
worlds = get_worlds
|
103
|
+
world_exists = false
|
104
|
+
world_already_on_ramdisk = false
|
105
|
+
worlds.each do |world,ramdisk|
|
106
|
+
if world.eql? world_name
|
107
|
+
world_exists = true
|
108
|
+
world_already_on_ramdisk = ramdisk
|
109
|
+
end
|
110
|
+
end
|
111
|
+
if world_name
|
112
|
+
if world_exists
|
113
|
+
if world_already_on_ramdisk
|
114
|
+
puts "\"#{world_name}\" will run from harddisk on next server start" unless @quiet
|
115
|
+
File.delete("#{@options[:server_world_directory]}#{world_name}/ramdisk")
|
116
|
+
else
|
117
|
+
puts "\"#{world_name}\" will run from ramdisk on next server start" unless @quiet
|
118
|
+
File.open("#{@options[:server_world_directory]}#{world_name}/ramdisk", "w")
|
119
|
+
end #end if world_already_on_ramdisk
|
120
|
+
else
|
121
|
+
puts "\"#{world_name}\" does not exist in world folder!"
|
122
|
+
end #end if world_exists
|
123
|
+
end #end if world_name
|
124
|
+
end #end world_ramdisk_state(world_name)
|
125
|
+
|
126
|
+
def worlds_to_ramdisk
|
127
|
+
worlds = get_worlds
|
128
|
+
worlds.each do |world,ramdisk|
|
129
|
+
if ramdisk
|
130
|
+
print "copy #{world} to ramdisk... " unless @quiet
|
131
|
+
`rsync -rt --exclude 'ramdisk' #{@options[:server_world_directory]}#{world}/ #{@options[:server_ramdisk_directory]}#{world}`
|
132
|
+
puts "ok" unless @quiet
|
133
|
+
end #end if ramdisk
|
134
|
+
end #worlds.each
|
135
|
+
end #end to_ramdisk
|
136
|
+
|
137
|
+
def worlds_to_disk
|
138
|
+
worlds = get_worlds()
|
139
|
+
ramdisk_worlds = Dir.open("#{@options[:server_ramdisk_directory]}")
|
140
|
+
ramdisk_worlds.each do |world|
|
141
|
+
if worlds.key?(world)
|
142
|
+
if worlds[world]
|
143
|
+
print "copy #{world} to harddisk... " unless @quiet
|
144
|
+
`rsync -rt --exclude 'ramdisk' #{@options[:server_ramdisk_directory]}#{world}/ #{@options[:server_world_directory]}#{world}`
|
145
|
+
puts "ok" unless @quiet
|
146
|
+
end
|
147
|
+
end #end if ramdisk
|
148
|
+
end #worlds.each
|
149
|
+
end #end to_ramdisk
|
150
|
+
|
151
|
+
#Get a hash of the locally available server versions
|
152
|
+
def get_local_server_versions
|
153
|
+
dir = Dir.new(@options[:server_jar_directory])
|
154
|
+
dir.sort.each do |f|
|
155
|
+
@versions[f.gsub(/^craftbukkit-|\.jar$/, "")] = "#{@options[:server_jar_directory]}#{f}" unless f =~ /^(\.\.|\.)$/
|
156
|
+
end
|
157
|
+
@versions
|
158
|
+
end #end get_local_server_versions
|
159
|
+
|
160
|
+
#Print locally available server versions to stdout
|
161
|
+
def print_local_server_versions
|
162
|
+
get_local_server_versions.each do |k,v|
|
163
|
+
puts "#{k}, #{v}"
|
164
|
+
end
|
165
|
+
end #end print_local_server_versions
|
166
|
+
|
167
|
+
#Check if given version is available locally
|
168
|
+
def local_version_available?(channel, version, build_number)
|
169
|
+
true if get_local_server_versions.has_key?("#{channel}-#{version}-#{build_number}")
|
170
|
+
end #end local_version_available?(version)
|
171
|
+
|
172
|
+
#Get an xml Document from the given url
|
173
|
+
def get_xml_document(url)
|
174
|
+
xml_data = Net::HTTP.get_response(URI.parse(url))
|
175
|
+
raise "Search for xml document data returned HTTP Error 404\n\nMaybe the version you entered does not exist." if xml_data.is_a?(Net::HTTPNotFound)
|
176
|
+
@xml_document = REXML::Document.new(xml_data.body)
|
177
|
+
raise "xml document empty" unless @xml_document
|
178
|
+
end #end get_xml_document(url)
|
179
|
+
|
180
|
+
#Get xml data from craftbukkit site as hash
|
181
|
+
def get_xml_first_path(url, path)
|
182
|
+
get_xml_document(url)
|
183
|
+
REXML::XPath.first(@xml_document, path).text
|
184
|
+
end #end get_xml_data(url)
|
185
|
+
|
186
|
+
#Get the latest build number for given version that was not broken
|
187
|
+
def get_latest_build_number(version, page=1)
|
188
|
+
url = "http://dl.bukkit.org/api/1.0/downloads/projects/craftbukkit/artifacts/?_accept=application%2Fxml&limit=20&page=#{page}"
|
189
|
+
build_number = nil
|
190
|
+
get_xml_document(url)
|
191
|
+
max_page = REXML::XPath.first(@xml_document, "//pages").text
|
192
|
+
REXML::XPath.each(@xml_document, "/root/results/list-item") do |element|
|
193
|
+
vers = element.text "version"
|
194
|
+
build_nr = element.text "build_number"
|
195
|
+
next if element.text("is_broken") =~ /^[Tt][Rr][Uu][Ee]$/
|
196
|
+
build_number = build_nr if version.eql? vers
|
197
|
+
end
|
198
|
+
if build_number.to_i > 0
|
199
|
+
return build_number
|
200
|
+
else
|
201
|
+
get_latest_build_number(version, page + 1) if page <= max_page.to_i
|
202
|
+
end
|
203
|
+
end #end get_latest_build_number(version)
|
204
|
+
|
205
|
+
#Return the link for the latest version of craftbukkit
|
206
|
+
def get_download_link(version)
|
207
|
+
prefix = "http://dl.bukkit.org"
|
208
|
+
url = "#{prefix}/api/1.0/downloads/projects/craftbukkit/artifacts/#{version}/?_accept=application%2Fxml" if version =~ /^(rb|beta|dev)$/
|
209
|
+
url = "#{prefix}/api/1.0/downloads/projects/craftbukkit/view/build-#{version}/?_accept=application%2Fxml" if version =~ /^[0-9][0-9][0-9][0-9]$/
|
210
|
+
url = "#{prefix}/api/1.0/downloads/projects/craftbukkit/view/build-#{get_latest_build_number(version)}/?_accept=application%2Fxml" if version =~ @craftbukkit_version_regex
|
211
|
+
raise "Thist is no Craftbukkit Version." unless url
|
212
|
+
{
|
213
|
+
:link => "#{prefix}#{get_xml_first_path(url, '//file/url')}",
|
214
|
+
:checksum => get_xml_first_path(url, "//file/checksum_md5"),
|
215
|
+
:version => get_xml_first_path(url, "//version"),
|
216
|
+
:build_number => get_xml_first_path(url, "//build_number"),
|
217
|
+
:channel => get_xml_first_path(url, "//channel/slug"),
|
218
|
+
}
|
219
|
+
end #end get_latest_download_link
|
220
|
+
|
221
|
+
#Download the latest server executable
|
222
|
+
def download_server_executable(version)
|
223
|
+
link = get_download_link(version)
|
224
|
+
url = link[:link]
|
225
|
+
md5 = link[:checksum]
|
226
|
+
version = link[:version]
|
227
|
+
build_number = link[:build_number]
|
228
|
+
channel = link[:channel]
|
229
|
+
target = "#{@options[:server_jar_directory]}craftbukkit-#{channel}-#{version}-#{build_number}.jar"
|
230
|
+
|
231
|
+
#Debug output
|
232
|
+
if @debug
|
233
|
+
puts "[#{version}]"
|
234
|
+
puts " link:\t\t#{url}"
|
235
|
+
puts " md5:\t\t#{md5}"
|
236
|
+
puts " taret:\t#{target}"
|
237
|
+
puts " build_nr:\t#{build_number}"
|
238
|
+
puts " channel:\t#{channel}"
|
239
|
+
end
|
240
|
+
|
241
|
+
if local_version_available? channel, version, build_number
|
242
|
+
puts "local version available. Will symlink local version to server runtime directory." if @debug
|
243
|
+
else
|
244
|
+
puts "local version not available. Will download new version and put symlink to it in server runtime directory." if @debug
|
245
|
+
download_file(url, target)
|
246
|
+
end
|
247
|
+
set_server_exe_symlink(target)
|
248
|
+
end #end download_latest_server_executable
|
249
|
+
|
250
|
+
#Change server version manually
|
251
|
+
def server_change_version(version)
|
252
|
+
link = get_download_link(version)
|
253
|
+
raise "This is no Craftbukkit Version!" unless version =~ /^(#{@craftbukkit_version_regex}|[0-9]{4})$/
|
254
|
+
if local_version_available?(link[:channel], link[:version], link[:build_number])
|
255
|
+
filename = "craftbukkit-#{version}.jar"
|
256
|
+
set_server_exe_symlink filename
|
257
|
+
else
|
258
|
+
download_server_executable(version)
|
259
|
+
end
|
260
|
+
end #end server_change_version(version)
|
261
|
+
|
262
|
+
#Download url to path
|
263
|
+
def download_file(url, path)
|
264
|
+
puts "downloading file from: \"#{url}\"" unless @quiet
|
265
|
+
url = URI(url)
|
266
|
+
location = URI(Net::HTTP.get_response(url)['location'])
|
267
|
+
Net::HTTP.start(location.host, location.port) do |http|
|
268
|
+
unless File.exist?(path)
|
269
|
+
f = open(path, 'wb')
|
270
|
+
begin
|
271
|
+
downloadedSize = 0
|
272
|
+
http.request_get(location.request_uri) do |resp|
|
273
|
+
progressBar = ProgressBar.new("Downloading", 100)
|
274
|
+
size = resp.content_length
|
275
|
+
resp.read_body do |segment|
|
276
|
+
downloadedSize += segment.length
|
277
|
+
if(downloadedSize != 0)
|
278
|
+
percent = (downloadedSize * 100 / size)
|
279
|
+
progressBar.set(percent)
|
280
|
+
end
|
281
|
+
f.write(segment)
|
282
|
+
end #end resp.read_body
|
283
|
+
progressBar.finish
|
284
|
+
end #end http.request_get
|
285
|
+
ensure
|
286
|
+
f.close()
|
287
|
+
end #end begin
|
288
|
+
end #end Net::HTTP.start
|
289
|
+
end
|
290
|
+
end #end download_file(url, path)
|
291
|
+
|
292
|
+
def set_server_exe_symlink(file)
|
293
|
+
current_file = "#{@options[:server_runtime_directory]}#{@options[:server_executable]}"
|
294
|
+
was_running = false
|
295
|
+
if @runtime.is_running?
|
296
|
+
was_running = true
|
297
|
+
@runtime.stop
|
298
|
+
end
|
299
|
+
puts "symlinking #{file} to #{current_file}"
|
300
|
+
File.unlink(current_file) if is_symlink_or_file(current_file)
|
301
|
+
File.symlink(file,current_file)
|
302
|
+
@runtime.start if was_running
|
303
|
+
end #end set_server_exe_symlink(file)
|
304
|
+
|
305
|
+
#Create a world backup with rsync
|
306
|
+
def world_backup_create
|
307
|
+
puts "Creating world folder backup now." unless @quiet
|
308
|
+
@commands.save_off
|
309
|
+
@commands.save_all
|
310
|
+
sleep 1
|
311
|
+
`rsync -a --delete-after #{@options[:server_world_directory]} #{@options[:server_backup_directory]}worlds/latest > #{@options[:server_backup_directory]}worlds/latest/rsync.log`
|
312
|
+
@commands.save_on
|
313
|
+
now = DateTime.now.strftime("%Y-%m-%d-%H:%M:%S")
|
314
|
+
`cp -al #{@options[:server_backup_directory]}worlds/latest #{@options[:server_backup_directory]}worlds/#{now}`
|
315
|
+
end #end world_backup create
|
316
|
+
|
317
|
+
#Delete world backups which are older than a month
|
318
|
+
def world_backup_delete
|
319
|
+
puts "Deleting old backups" unless @quiet
|
320
|
+
`find #{@options[:server_backup_directory]} -mindepth 1 -maxdepth 1 -not -newermt '1 month ago' -exec rm -rf {} \\;`
|
321
|
+
end #end world_backup_delete
|
322
|
+
end #end class Tools
|
323
|
+
end #end module Mclaunch
|
data/lib/mclaunch.rb
ADDED
@@ -0,0 +1,347 @@
|
|
1
|
+
module Mclaunch
|
2
|
+
require "mclaunch/version"
|
3
|
+
require "mclaunch/runtime"
|
4
|
+
require "mclaunch/commands"
|
5
|
+
require "mclaunch/tools"
|
6
|
+
require 'optparse'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
default_options = {
|
10
|
+
:server_executable => "craftbukkit.jar",
|
11
|
+
:server_runtime_directory => "#{ENV["HOME"]}/bukkit/server/",
|
12
|
+
:server_world_directory => "#{ENV["HOME"]}/bukkit/worlds/",
|
13
|
+
:server_jar_directory => "#{ENV["HOME"]}/bukkit/jars/",
|
14
|
+
:server_backup_directory => "#{ENV["HOME"]}/bukkit/backup/",
|
15
|
+
:server_ramdisk_directory => "#{ENV["HOME"]}/bukkit/ramdisk/",
|
16
|
+
:server_min_heap_memory => "512M",
|
17
|
+
:server_max_heap_memory => "1024M",
|
18
|
+
:server_additional_options => nil,
|
19
|
+
:server_terminal_multiplexer => "tmux",
|
20
|
+
:server_terminal_multiplexer_name => "craftbukkit",
|
21
|
+
:server_terminal_multiplexer_session => "/tmp/craftbukkit",
|
22
|
+
}
|
23
|
+
@options = {
|
24
|
+
:debug => false,
|
25
|
+
:quiet => false,
|
26
|
+
:config_file => nil,
|
27
|
+
:server_management => {
|
28
|
+
:list_versions => false,
|
29
|
+
:update_to_latest => nil,
|
30
|
+
:server_change_version => nil,
|
31
|
+
:world_to_ramdisk => nil,
|
32
|
+
:world_to_disk => nil,
|
33
|
+
:worlds_create_symlinks => nil,
|
34
|
+
},
|
35
|
+
:server_commands => {
|
36
|
+
:reload => false,
|
37
|
+
:save_on => false,
|
38
|
+
:save_off => false,
|
39
|
+
:save_all => false,
|
40
|
+
:gamemode => nil,
|
41
|
+
:difficulty => nil,
|
42
|
+
:op => nil,
|
43
|
+
:deop => nil,
|
44
|
+
:kick => nil,
|
45
|
+
:kick_player => nil,
|
46
|
+
:kick_ip => nil,
|
47
|
+
:pardon_player => nil,
|
48
|
+
:pardon_ip => nil,
|
49
|
+
:whitelist_on => false,
|
50
|
+
:whitelist_off => false,
|
51
|
+
:whitelist_add => nil,
|
52
|
+
:whitelist_remove => nil,
|
53
|
+
}
|
54
|
+
}
|
55
|
+
@options.merge! default_options
|
56
|
+
|
57
|
+
|
58
|
+
opt_parser = OptionParser.new do |opts|
|
59
|
+
|
60
|
+
#Write Standard config file if it does't exist
|
61
|
+
|
62
|
+
@config_file = "#{@options[:server_runtime_directory]}mclaunch.properties" unless @options[:config_file]
|
63
|
+
@config_file = @options[:config_file] if @options[:config_file]
|
64
|
+
if File.exists?(@config_file) == false
|
65
|
+
File.open(@config_file, "w") {|f| f.write(default_options.to_yaml)}
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
opts.banner = " Usage:\t#{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} <options> start/stop/restart\n"
|
70
|
+
opts.separator ""
|
71
|
+
opts.separator " Avalable options are:\n"
|
72
|
+
opts.separator ""
|
73
|
+
|
74
|
+
opts.separator " Game management:"
|
75
|
+
|
76
|
+
opts.on('--reload', "reload the minecraft server") do
|
77
|
+
@options[:server_commands][:reload] = true
|
78
|
+
end #end opts.on
|
79
|
+
|
80
|
+
opts.on('--save-on', "turn the save mode on") do
|
81
|
+
@options[:server_commands][:save_on] = true
|
82
|
+
end #end opts.on
|
83
|
+
|
84
|
+
opts.on('--save-off', "turn the save mode off") do
|
85
|
+
@options[:server_commands][:save_off] = true
|
86
|
+
end #end opts.on
|
87
|
+
|
88
|
+
opts.on('--save-all', "save the current world state") do
|
89
|
+
@options[:server_commands][:save_all] = true
|
90
|
+
end #end opts.on
|
91
|
+
|
92
|
+
opts.on('--gamemode GAMEMODE', String, "change the current gamemode to GAMEMODE") do |arg|
|
93
|
+
@options[:server_commands][:gamemode] = arg
|
94
|
+
end #end opts.on
|
95
|
+
|
96
|
+
opts.on('--difficulty DIFFICULTY', String, "change the current difficulty to DIFFICULTY") do |arg|
|
97
|
+
@options[:server_commands][:difficulty] = arg
|
98
|
+
end #end opts.on
|
99
|
+
|
100
|
+
opts.on('--op-player PLAYER', String, "grant op status on PLAYER") do |arg|
|
101
|
+
@options[:server_commands][:op] = arg
|
102
|
+
end #end opts.on
|
103
|
+
|
104
|
+
opts.on('--deop-player PLAYER', String, "revoke op status on Player") do |arg|
|
105
|
+
@options[:server_commands][:deop] = arg
|
106
|
+
end #end opts.on
|
107
|
+
|
108
|
+
opts.on('--ban-player PLAYER [REASON]', String, "ban PLAYER") do |arg|
|
109
|
+
@options[:server_commands][:ban_player] = arg
|
110
|
+
end #end opts.on
|
111
|
+
|
112
|
+
opts.on('--ban-ip 11.22.33.44 [REASON]', String, "ban IP") do |arg|
|
113
|
+
@options[:server_commands][:ban_ip] = arg
|
114
|
+
end #end opts.on
|
115
|
+
|
116
|
+
opts.on('--pardon-player PLAYER', String, "pardon PLAYER") do |arg|
|
117
|
+
@options[:server_commands][:pardon_player] = arg
|
118
|
+
end #end opts.on
|
119
|
+
|
120
|
+
opts.on('--pardon-ip 11.22.33.44', String, "pardon IP") do |arg|
|
121
|
+
@options[:server_commands][:pardon_ip] = arg
|
122
|
+
end #end opts.on
|
123
|
+
|
124
|
+
opts.on('--whitelist-add PLAYER', String, "add PLAYER to whitelist") do |arg|
|
125
|
+
@options[:server_commands][:whitelist_add] = arg
|
126
|
+
end #end opts.on
|
127
|
+
|
128
|
+
opts.on('--whitelist-remove PLAYER', String, "remove PLAYER from whitelist") do |arg|
|
129
|
+
@options[:server_commands][:whitelist_remove] = arg
|
130
|
+
end #end opts.on
|
131
|
+
|
132
|
+
opts.on('--whitelist-on', "turn the whitelist on") do
|
133
|
+
@options[:server_commands][:whitelist_on] = true
|
134
|
+
end #end opts.on
|
135
|
+
|
136
|
+
opts.on('--whitelist-off', "turn the whitelist off") do
|
137
|
+
@options[:server_commands][:whitelist_off] = true
|
138
|
+
end #end opts.on
|
139
|
+
|
140
|
+
opts.separator ""
|
141
|
+
opts.separator " Server Settings:"
|
142
|
+
|
143
|
+
opts.on('-m', '--minimal-mem 512M', "set the minimal memory to use in format \"512M\"") do |arg|
|
144
|
+
@options[:server_min_heap_memory] = arg
|
145
|
+
end
|
146
|
+
|
147
|
+
opts.on('-M', '--maximal-mem 1G', "set the maximal memory to use in format \"1024M\"") do |arg|
|
148
|
+
@options[:server_max_heap_memory] = arg
|
149
|
+
end
|
150
|
+
|
151
|
+
opts.on('--server-executable JAR', String, "set the JAR to use for current session") do |arg|
|
152
|
+
@options[:server_executable] = arg
|
153
|
+
end
|
154
|
+
|
155
|
+
opts.on('--server-directory DIR', String, "set the directory to user to DIR") do |arg|
|
156
|
+
@options[:server_runtime_directory] = arg
|
157
|
+
end
|
158
|
+
|
159
|
+
opts.on('--jar-directory DIR', String, "set the jar directory to use to DIR") do |arg|
|
160
|
+
@options[:server_jar_directory] = arg
|
161
|
+
end
|
162
|
+
|
163
|
+
opts.on('--world-directory DIR', String, "set the world directory to use to DIR") do |arg|
|
164
|
+
@options[:server_world_directory] = arg
|
165
|
+
end
|
166
|
+
|
167
|
+
opts.on('--backup-directory DIR', String, "set the backup directory to use to DIR") do |arg|
|
168
|
+
@options[:server_backup_directory] = arg
|
169
|
+
end
|
170
|
+
|
171
|
+
opts.separator ""
|
172
|
+
opts.separator " Server Magagement:"
|
173
|
+
|
174
|
+
opts.on('-l', '--list-versions', "list locally available Server versions") do
|
175
|
+
@options[:server_management][:list_versions] = true
|
176
|
+
end
|
177
|
+
|
178
|
+
opts.on('--update VERSION', "update to latest craftbukkit version, where version may be \"rb, beta or dev\"") do |arg|
|
179
|
+
@options[:server_management][:update_to_latest] = arg
|
180
|
+
end
|
181
|
+
|
182
|
+
opts.on('--server-version VERSION', "Set server version to Version") do |arg|
|
183
|
+
@options[:server_management][:server_change_version] = arg
|
184
|
+
end
|
185
|
+
|
186
|
+
opts.separator ""
|
187
|
+
opts.separator " World Management:"
|
188
|
+
|
189
|
+
opts.on('--world-to-ramdisk WORLD', "Set ramdisk flag for WORLD") do |arg|
|
190
|
+
@options[:server_management][:world_to_disk] = arg
|
191
|
+
end
|
192
|
+
|
193
|
+
opts.on('--world-to-disk WORLD', "Remove ramdisk flag from WORLD") do |arg|
|
194
|
+
@options[:server_management][:world_to_ramdisk] = arg
|
195
|
+
end
|
196
|
+
|
197
|
+
opts.on('--worlds-symlink', "Symlink all worlds in the worlds directory to runtime directory")do |arg|
|
198
|
+
@options[:server_management][:worlds_create_symlinks] = arg
|
199
|
+
end
|
200
|
+
|
201
|
+
opts.on('--world-backup-create', "Create a Backup from world directory to backup directory") do
|
202
|
+
@options[:server_management][:world_backup_create] = true
|
203
|
+
end
|
204
|
+
|
205
|
+
opts.on('--world-backup-delete', "Delete 1 month old backupa from backup directory") do
|
206
|
+
@options[:server_management][:world_backup_delete] = true
|
207
|
+
end
|
208
|
+
|
209
|
+
opts.separator ""
|
210
|
+
opts.separator " Misc Options:"
|
211
|
+
|
212
|
+
opts.on('-q', '--quiet', "turn off all output") do
|
213
|
+
@options[:quiet] = true
|
214
|
+
end #end opts.on
|
215
|
+
|
216
|
+
opts.on('-d', '--debug', "turn debug output on") do
|
217
|
+
@options[:debug] = true
|
218
|
+
end #end opts.on
|
219
|
+
|
220
|
+
opts.on("-h", "--help", "Show this message") do
|
221
|
+
puts opts
|
222
|
+
end # end opts.on_tail
|
223
|
+
|
224
|
+
opts.separator ""
|
225
|
+
opts.separator ""
|
226
|
+
opts.separator " Usage Examples:"
|
227
|
+
opts.separator ""
|
228
|
+
opts.separator " Start, Stop, Restart"
|
229
|
+
opts.separator " To start the craftbukkit server use:"
|
230
|
+
opts.separator " #{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} <options> start"
|
231
|
+
opts.separator " To stop the craftbukkit server use:"
|
232
|
+
opts.separator " #{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} stop"
|
233
|
+
opts.separator " To restart the craftbukkit server use:"
|
234
|
+
opts.separator " #{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} <options> restart"
|
235
|
+
opts.separator ""
|
236
|
+
opts.separator " Server Management:"
|
237
|
+
opts.separator " kick player:"
|
238
|
+
opts.separator " #{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} --kick-player notch"
|
239
|
+
opts.separator " change gamemode:"
|
240
|
+
opts.separator " #{__FILE__.gsub(/(^\/.*\/|\.rb)/, "")} --gamemode creative"
|
241
|
+
opts.separator ""
|
242
|
+
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
begin
|
247
|
+
@options.merge!(Hash[YAML::load(File.new(@config_file)).map { |k, v| @options[k] = v}])
|
248
|
+
|
249
|
+
opt_parser.parse!
|
250
|
+
rescue => exc
|
251
|
+
STDERR.puts "an error with the command line options occured:\n\t#{exc}"
|
252
|
+
STDERR.puts
|
253
|
+
STDERR.puts "For usage options use #{__FILE__.gsub(/^\/.*\//, "")} --help"
|
254
|
+
exit 1
|
255
|
+
end
|
256
|
+
|
257
|
+
begin
|
258
|
+
@runtime = Runtime.new(@options)
|
259
|
+
@tools = Tools.new(@runtime, @options)
|
260
|
+
@commands = Commands.new(@runtime, @options, @tools)
|
261
|
+
@tools.commands(@commands)
|
262
|
+
@craftbukkit_version_regex = /^[1-9]\.[0-9]\.[0-9]-R[0-9]\.[0-9]$/
|
263
|
+
|
264
|
+
@options[:server_management].each do |k,v|
|
265
|
+
case k
|
266
|
+
when :list_versions
|
267
|
+
@tools.print_local_server_versions if v
|
268
|
+
when :update_to_latest
|
269
|
+
@tools.download_server_executable(v) if v =~ /^(rb|beta|dev)$/
|
270
|
+
when :server_change_version
|
271
|
+
@tools.server_change_version(v) if v =~ /^(#{@craftbukkit_version_regex}|[0-9]{4})$/
|
272
|
+
when :world_to_ramdisk
|
273
|
+
@tools.world_ramdisk_state(v) if v
|
274
|
+
when :world_to_disk
|
275
|
+
@tools.world_ramdisk_state(v) if v
|
276
|
+
when :worlds_create_symlinks
|
277
|
+
@tools.worlds_create_symlinks if v
|
278
|
+
when :world_backup_create
|
279
|
+
@tools.world_backup_create if v
|
280
|
+
when :world_backup_delete
|
281
|
+
@tools.world_backup_delete if v
|
282
|
+
end
|
283
|
+
end
|
284
|
+
@options[:server_commands].each do |k,v|
|
285
|
+
case k
|
286
|
+
when :reload
|
287
|
+
@commands.reload if v
|
288
|
+
when :save_on
|
289
|
+
@commands.save_on if v
|
290
|
+
when :save_off
|
291
|
+
@commands.save_off if v
|
292
|
+
when :save_all
|
293
|
+
@commands.save_all if v
|
294
|
+
when :gamemode
|
295
|
+
@commands.change_gamemode(v) if v
|
296
|
+
when :difficulty
|
297
|
+
@commands.change_difficulty(v) if v
|
298
|
+
when :op
|
299
|
+
@commands.op(v) if v
|
300
|
+
when :deop
|
301
|
+
@commands.deop(v) if v
|
302
|
+
when :kick_player
|
303
|
+
@commands.kick_player(v) if v
|
304
|
+
when :kick_ip
|
305
|
+
@commands.kick_ip(v) if v
|
306
|
+
when :ban_player
|
307
|
+
@commands.ban_player(v, ARGV) if v
|
308
|
+
when :ban_ip
|
309
|
+
@commands.ban_ip(v, ARGV) if v
|
310
|
+
when :pardon_player
|
311
|
+
@commands.pardon_player(v) if v
|
312
|
+
when :pardon_ip
|
313
|
+
@commands.pardon_ip(v) if v
|
314
|
+
when :whitelist_on
|
315
|
+
@commands.whitelist("on") if v
|
316
|
+
when :whitelist_off
|
317
|
+
@commands.whitelist("off") if v
|
318
|
+
when :whitelist_add
|
319
|
+
@commands.whitelist_add(v) if v
|
320
|
+
when :whitelist_remove
|
321
|
+
@commands.whitelist_remove(v) if v
|
322
|
+
end
|
323
|
+
end
|
324
|
+
rescue => exc
|
325
|
+
STDERR.puts "An runtime error occured:\n\t#{exc.message}"
|
326
|
+
STDERR.puts
|
327
|
+
STDERR.puts "For usage options use #{__FILE__.gsub(/^\/.*\//, "")} --help"
|
328
|
+
end
|
329
|
+
|
330
|
+
begin
|
331
|
+
case ARGV[0]
|
332
|
+
when "start"
|
333
|
+
@tools.worlds_to_ramdisk
|
334
|
+
@runtime.run
|
335
|
+
when "stop"
|
336
|
+
@runtime.halt
|
337
|
+
@tools.worlds_to_disk
|
338
|
+
when "restart"
|
339
|
+
@tools.worlds_to_disk
|
340
|
+
@tools.worlds_to_ramdisk
|
341
|
+
@runtime.restart
|
342
|
+
end
|
343
|
+
rescue => exc
|
344
|
+
STDERR.puts exc.message
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
data/mclaunch.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mclaunch/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "mclaunch"
|
8
|
+
gem.version = Mclaunch::VERSION
|
9
|
+
gem.authors = ["odie"]
|
10
|
+
gem.email = ["masterodie@gmail.com"]
|
11
|
+
gem.description = "A craftbukkit server launcher"
|
12
|
+
gem.summary = "A craftbukkit server launcher"
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mclaunch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- odie
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-01 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A craftbukkit server launcher
|
15
|
+
email:
|
16
|
+
- masterodie@gmail.com
|
17
|
+
executables:
|
18
|
+
- mclaunch
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bin/mclaunch
|
28
|
+
- lib/mclaunch.rb
|
29
|
+
- lib/mclaunch/commands.rb
|
30
|
+
- lib/mclaunch/runtime.rb
|
31
|
+
- lib/mclaunch/tools.rb
|
32
|
+
- lib/mclaunch/version.rb
|
33
|
+
- mclaunch.gemspec
|
34
|
+
homepage: ''
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.24
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: A craftbukkit server launcher
|
58
|
+
test_files: []
|