mclaunch 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|