minecraft 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -29,23 +29,27 @@ Current Features
29
29
  - Give the user an item with a quantity of up to 2560 (by default Minecraft
30
30
  will cap at 64).
31
31
  - Use the item ID or item name. http://minecraftwiki.net/wiki/Data_values
32
+ - !giveall <item> <quantity>
32
33
  - !tp <target_user>
34
+ - !tpall
33
35
  - !nom
34
- - !kit
36
+ - !nomall
37
+ - !kit <group>
35
38
  - Diamond
36
39
  - Gold armour
37
40
  - Armour
38
41
  - Ranged
39
42
  - Nether
40
43
  - Portal
44
+ - !kitall <group>
45
+ - !addtimer <item> <frequency>
46
+ - !deltimer <item>
47
+ - !printtimer
48
+ - !list
41
49
 
42
50
  TODO
43
51
  ----
44
52
 
45
- - Improved error handling.
46
- - Log time users have spent on the server.
47
- - !give timers (give user A an item every X seconds).
48
-
49
53
  Contributors
50
54
  ------------
51
55
 
@@ -1,5 +1,6 @@
1
1
  require "minecraft/tools"
2
2
  require "minecraft/data"
3
+ require "minecraft/commands"
3
4
  require "minecraft/extensions"
4
5
  require "minecraft/server"
5
6
 
@@ -0,0 +1,143 @@
1
+ module Minecraft
2
+ module Commands
3
+ include Data
4
+
5
+ def give(user, *args)
6
+ item, quantity = items_arg(1, args)
7
+ item = resolve_item(item)
8
+
9
+ quantify(user, item, quantity)
10
+ end
11
+
12
+ def validate_kit(group = "")
13
+ return true if KITS.include? group.to_sym
14
+ @server.puts "say #{group} is not a valid kit."
15
+ kitlist
16
+ end
17
+
18
+ def kit(user, group)
19
+ KITS[group.to_sym].each do |item|
20
+ if item.is_a? Array
21
+ @server.puts quantify(user, item.first, item.last)
22
+ else
23
+ @server.puts "give #{user} #{item} 1"
24
+ end
25
+ end
26
+ end
27
+
28
+ def tp(user, target)
29
+ @server.puts "tp #{user} #{target}"
30
+ end
31
+
32
+ def tpall(user, *args)
33
+ @users.each { |u| tp(u, user) }
34
+ end
35
+
36
+ def nom(user)
37
+ @server.puts "give #{user} 322 1"
38
+ end
39
+
40
+ def list(user)
41
+ l = @users.inject("") do |s, u|
42
+ if u == user
43
+ pre = "["
44
+ suf = "]"
45
+ end
46
+ suf = "*" + (suf || "") if is_op? u
47
+ s + "#{", " unless s.empty?}#{pre}#{u}#{suf}"
48
+ end
49
+ @server.puts "say #{l}"
50
+ end
51
+
52
+ def addtimer(user, *args)
53
+ item, duration = items_arg(30, args)
54
+ item = resolve_item(item)
55
+ @timers[user] ||= {}
56
+ @timers[user][item] = duration
57
+ @server.puts "say Timer added for #{user}. Giving #{item} every #{duration} seconds."
58
+ end
59
+
60
+ def deltimer(user, *args)
61
+ item = args.join(" ")
62
+ item = resolve_item(item)
63
+ @timers[user][item] = nil if @timers.has_key? user
64
+ end
65
+
66
+ def printtimer(user)
67
+ @server.puts "say Timer is at #{@counter}."
68
+ end
69
+
70
+ def help(*args)
71
+ @server.puts <<-eof
72
+ say !tp target_user
73
+ say !kit kit_name
74
+ say !give item quantity
75
+ say !nom
76
+ say !list
77
+ say !addtimer item frequency
78
+ say !deltimer item
79
+ eof
80
+ end
81
+
82
+ def kitlist(*args)
83
+ @server.puts "say Kits: #{KITS.keys.join(", ")}"
84
+ end
85
+
86
+ def quantify(user, item, quantity)
87
+ if quantity <= 64
88
+ @server.puts "give #{user} #{item} #{quantity}"
89
+ return
90
+ end
91
+
92
+ quantity = 2560 if quantity > 2560
93
+ full_quantity = (quantity / 64.0).floor
94
+ sub_quantity = quantity % 64
95
+ @server.puts "give #{user} #{item} 64\n" * full_quantity
96
+ @server.puts "give #{user} #{item} #{sub_quantity}" if sub_quantity > 0
97
+ end
98
+
99
+ def items_arg(default, args)
100
+ if args.length == 1
101
+ second = default
102
+ first = args.first
103
+ else
104
+ if args.last.to_i.to_s == args.last # Last argument is an integer.
105
+ second = args.last.to_i
106
+ first = args[0..-2].join(" ")
107
+ else
108
+ second = default
109
+ first = args[0..-1].join(" ")
110
+ end
111
+ end
112
+ return [first, second]
113
+ end
114
+
115
+ def resolve_item(item)
116
+ item.to_i.to_s == item ? item.to_i : DATA_VALUE_HASH[resolve_key(item.downcase)]
117
+ end
118
+
119
+ def resolve_key(key)
120
+ bucket = key[0]
121
+ return key if ITEM_BUCKETS[bucket].include? key
122
+
123
+ puts "Finding #{key} approximate in #{ITEM_BUCKETS[bucket]}"
124
+ shortest_diff = nil
125
+ shortest_key = nil
126
+ ITEM_BUCKETS[bucket].each do |test_key|
127
+ if test_key.length > key.length
128
+ diff = test_key.length - key.length if test_key.index(key)
129
+ else
130
+ diff = key.length - test_key.length if key.index(test_key)
131
+ end
132
+ next if diff.nil?
133
+
134
+ if shortest_diff.nil? or diff < shortest_diff
135
+ shortest_key = test_key
136
+ shortest_diff = diff
137
+ end
138
+ end
139
+
140
+ return shortest_key
141
+ end
142
+ end
143
+ end
@@ -70,7 +70,7 @@ module Minecraft
70
70
  "lava" => "10",
71
71
  "dead shrubs" => "32",
72
72
  "double stone slab" => "43",
73
- "furnace " => "61",
73
+ "furnace" => "61",
74
74
  "fence" => "85",
75
75
  "stationary lava " => "11",
76
76
  "piston" => "33",
@@ -246,5 +246,12 @@ module Minecraft
246
246
  "saddle" => "329",
247
247
  "cocoa beans" => "351"
248
248
  }
249
+
250
+ ITEM_BUCKETS = {}
251
+ DATA_VALUE_HASH.each_key do |key|
252
+ bucket = key[0]
253
+ ITEM_BUCKETS[bucket] ||= []
254
+ ITEM_BUCKETS[bucket] << key
255
+ end
249
256
  end
250
257
  end
@@ -1,31 +1,108 @@
1
+ require "json/pure"
2
+
1
3
  module Minecraft
2
4
  class Extensions
3
- include Data
5
+ include Commands
4
6
 
5
- def initialize
6
- @ops = File.readlines("ops.txt").map { |s| s.chop }
7
+ def initialize(server)
8
+ @ops = File.readlines("ops.txt").map { |s| s.chomp }
9
+ @userlog = get_user_log
7
10
  @users = []
11
+ @timers = {}
12
+ @counter = 0
13
+ @logon_time = {}
14
+ @server = server
15
+
16
+ # Command set.
17
+ @commands = {}
18
+ add_command(:give, :ops => true, :all => true, :all_message => "is putting out.")
19
+ add_command(:tp, :ops => false, :all => true, :all_message => "is teleporting all users to their location.")
20
+ add_command(:kit, :ops => true, :all => true, :all_message => "is providing kits to all.")
21
+ add_command(:help, :ops => false, :all => false)
22
+ add_command(:nom, :ops => true, :all => true, :all_message => "is providing noms to all.")
23
+ add_command(:list, :ops => false, :all => false)
24
+ add_command(:addtimer, :ops => true, :all => false)
25
+ add_command(:deltimer, :ops => true, :all => false)
26
+ add_command(:printtimer, :ops => true, :all => false)
27
+ add_command(:kitlist, :ops => false, :all => false)
28
+ end
29
+
30
+ def get_user_log
31
+ if File.exists? "user.log"
32
+ JSON.parse(File.read("user.log"))
33
+ else
34
+ {}
35
+ end
36
+ end
37
+
38
+ def write_log
39
+ File.open("user.log", "w") { |f| f.print @userlog.to_json }
40
+ end
41
+
42
+ def call_command(user, command, *args)
43
+ is_all = command.to_s.end_with? "all"
44
+ root = command.to_s.chomp("all").to_sym
45
+ return invalid_command(command) unless @commands.include? root
46
+
47
+ # Any `all` suffixed command requires ops.
48
+ if @commands[root][:ops] or (is_all and @commands[root][:all])
49
+ return if !validate_ops(user, command)
50
+ end
51
+
52
+ if respond_to? "validate_" + root.to_s
53
+ return unless send("validate_" + root.to_s, *args)
54
+ end
55
+
56
+ if is_all
57
+ @server.puts "say #{user} #{@commands[root][:all_message]}"
58
+ if respond_to? command
59
+ send(command, user, *args)
60
+ else
61
+ @users.each { |u| send(root, u, *args) }
62
+ end
63
+ else
64
+ send(root, user, *args)
65
+ end
66
+ end
67
+
68
+ def add_command(command, opts)
69
+ @commands[command] = opts
8
70
  end
9
71
 
10
72
  def process(line)
11
73
  puts line
12
74
  return info_command(line) if line.index "INFO"
75
+ rescue Exception => e
76
+ puts "An error has occurred."
77
+ puts e
78
+ puts e.backtrace
79
+ end
80
+
81
+ def periodic
82
+ @counter += 1
83
+ @users.each do |user|
84
+ next unless @timers.has_key? user
85
+ @timers[user].each do |item, duration|
86
+ next if duration.nil?
87
+ @server.puts "give #{user} #{item} 64" if @counter % duration == 0
88
+ end
89
+ end
13
90
  end
14
91
 
15
92
  def info_command(line)
16
93
  line.gsub! /^.*?\[INFO\]\s+/, ''
17
- meta_check(line)
94
+ return if meta_check(line)
18
95
  match_data = line.match /^\<(.*?)\>\s+!(.*?)$/
19
96
  return if match_data.nil?
20
97
 
21
98
  user = match_data[1]
22
99
  args = match_data[2].split(" ")
23
- return send(args.slice!(0), user, *args)
100
+ call_command(user, args.slice!(0).to_sym, *args)
24
101
  end
25
102
 
26
103
  def meta_check(line)
27
- return if check_ops(line)
28
- return if check_join_part(line)
104
+ return true if check_ops(line)
105
+ return true if check_join_part(line)
29
106
  end
30
107
 
31
108
  def check_ops(line)
@@ -43,111 +120,44 @@ module Minecraft
43
120
  user = line.split(" ").first
44
121
  if line.index "lost connection"
45
122
  @users.reject! { |u| u == user }
123
+ log_time(user)
46
124
  return true
47
125
  elsif line.index "logged in"
48
126
  @users << user
127
+ @logon_time[user] = Time.now
49
128
  return true
50
129
  end
51
130
  end
52
131
 
53
132
  def method_missing(sym, *args)
54
- if DATA_VALUE_HASH.has_key? sym.downcase
133
+ if DATA_VALUE_HASH.has_key? sym.downcase and is_op? args.first
55
134
  give(args.first, sym, args.last)
56
135
  else
57
136
  puts "Invalid command given."
58
137
  end
59
138
  end
60
139
 
61
- def giveall(user, *args)
62
- return privilege_error(user, "giveall") unless is_op? user
63
- ret = "say #{user} is putting out!\n"
64
- @users.each do |u|
65
- ret += mc_give(u, *args)
66
- end
67
-
68
- return ret
69
- end
70
-
71
- def give(user, *args)
72
- return privilege_error(user, "give") unless is_op? user
73
- return mc_give(user, *args)
74
- end
75
-
76
- def mc_give(user, *args)
77
- if args.length == 1
78
- quantity = 1
79
- item = args.first
80
- else
81
- quantity = args.last.to_i || 1
82
- item = args[0..-2].join(" ")
83
- end
84
- item = (item.to_i.to_s == item) ? item.to_i : DATA_VALUE_HASH[item.downcase]
85
-
86
- return quantify(user, item, quantity)
87
- end
88
-
89
- def kit(user, group)
90
- return privilege_error(user, "kit") unless is_op? user
91
- return "say #{group} is not a valid kit." unless KITS.has_key? group.to_sym
92
- ret = ""
93
-
94
- KITS[group.to_sym].each do |item|
95
- if item.is_a? Array
96
- ret += quantify(user, item.first, item.last)
97
- else
98
- ret += "give #{user} #{item} 1\n"
99
- end
100
- end
101
- return ret.chop
102
- end
103
-
104
- def tp(user, target)
105
- "tp #{user} #{target}"
106
- end
107
-
108
- def tpall(user)
109
- return privilege_error(user, "tpall", "Wow, #{user} actually tried to pull that...") unless is_op? user
110
- ret = "say #{user} is teleporting all users to their location.\n"
111
- @users.each do |u|
112
- ret += tp(u, user)
113
- end
114
- return ret
115
- end
116
-
117
- def nom(user)
118
- return privilege_error(user, "nom", "No noms for you!") unless is_op? user
119
- "give #{user} 322 1"
120
- end
121
-
122
- def help(*args)
123
- <<-eof
124
- say !tp target_user
125
- say !tpall
126
- say !kit kit_name
127
- say !give item quantity
128
- say !giveall item quantity
129
- say !nom
130
- say /help
131
- eof
132
- end
133
-
134
- def quantify(user, item, quantity)
135
- return "give #{user} #{item} #{quantity}" if quantity <= 64
136
-
137
- quantity = 2560 if quantity > 2560
138
- full_quantity = (quantity / 64.0).floor
139
- sub_quantity = quantity % 64
140
- ret = "give #{user} #{item} 64\n" * full_quantity
141
- ret += "give #{user} #{item} #{sub_quantity}"
142
- return ret
140
+ def log_time(user)
141
+ logoff = Time.now
142
+ logon = @logon_time[user]
143
+ time_spent = logoff - logon
144
+ @userlog[user] ||= 0
145
+ @userlog[user] += time_spent
146
+ @server.puts "say #{user} spent #{time_spent} seconds the server, totalling to #{@userlog[user]}."
147
+ write_log
143
148
  end
144
149
 
145
150
  def is_op?(user)
146
151
  @ops.include? user
147
152
  end
148
153
 
149
- def privilege_error(user, command, suffix = "S/he must be humiliated!")
150
- "say #{user} is not an op, cannot use !#{command}. #{suffix}"
154
+ def validate_ops(user, command)
155
+ return true if is_op? user
156
+ @server.puts "say #{user} is not an op, cannot use !#{command}."
157
+ end
158
+
159
+ def invalid_command(command)
160
+ @server.puts "say #{command} is invalid."
151
161
  end
152
162
  end
153
163
  end
@@ -5,18 +5,14 @@ module Minecraft
5
5
  attr_accessor :sin
6
6
 
7
7
  def initialize(command)
8
- @extensions = Extensions.new
9
8
  @sin, @sout, @serr = Open3.popen3(command)
9
+ @extensions = Extensions.new(@sin)
10
10
  threads = []
11
- threads << Thread.new { loop { process(@sout.gets) } }
12
- threads << Thread.new { loop { process(@serr.gets) } }
11
+ threads << Thread.new { loop { @extensions.process(@sout.gets) } }
12
+ threads << Thread.new { loop { @extensions.process(@serr.gets) } }
13
+ threads << Thread.new { loop { @extensions.periodic; sleep 1 } }
13
14
  threads << Thread.new { loop { @sin.puts gets } }
14
15
  threads.each(&:join)
15
16
  end
16
-
17
- def process(line)
18
- result = @extensions.process(line)
19
- @sin.puts(result) unless result.nil?
20
- end
21
17
  end
22
18
  end
@@ -1,3 +1,3 @@
1
1
  module Minecraft
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: minecraft
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Andrew Horsman
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-13 00:00:00 -04:00
13
+ date: 2011-08-14 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -40,6 +40,7 @@ files:
40
40
  - Rakefile
41
41
  - bin/minecraft
42
42
  - lib/minecraft.rb
43
+ - lib/minecraft/commands.rb
43
44
  - lib/minecraft/data.rb
44
45
  - lib/minecraft/extensions.rb
45
46
  - lib/minecraft/server.rb