-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspout_boost.rb
338 lines (329 loc) · 11.1 KB
/
spout_boost.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# SpoutBoost
# A list of useful functions and tools for any server running spout.
#### Plugin Info ####
Plugin.is {
name "SpoutBoost"
version "0.3"
author "d4l3k"
description "A pack of useful tools for any Spout Server."
commands :title => {
:description => "Sets a title for a player.",
:usage => "/title <player> <title>\n/title <title>",
:aliases => [ :settitle]
}
commands :spreload => {
:description => "Reloads the SpoutBoost.",
:usage => "/spreload",
}
}
#### Requires ####
# Adds default jruby libraries to path so you can easily require them.
# (This should be done by default, but requires more than just the jruby.jar.)
# TODO: Fix this in RubyBukkit source & push the changes.
# This plugin requires 1.9 for easy Psych compatibility.
file = File.join(File.dirname(__FILE__),"./jruby-1.6.5/lib/ruby/1.9/")
$: << file unless $:.include? file
#### Imports ####
# Java Imports
import 'java.util.logging.Logger'
import 'java.util.logging.Level'
# Spout imports
import 'org.getspout.spoutapi.gui.Widget'
import 'org.getspout.spoutapi.gui.WidgetAnchor'
import 'org.getspout.spoutapi.gui.GenericPopup'
import 'org.getspout.spoutapi.gui.GenericLabel'
import 'org.getspout.spoutapi.SpoutManager'
import 'org.getspout.spoutapi.player.SpoutPlayer'
import 'org.getspout.spoutapi.event.spout.SpoutListener'
# Bukkit imports
import 'org.bukkit.Location'
import 'org.bukkit.event.Event'
import 'org.bukkit.event.player.PlayerMoveEvent'
import 'org.bukkit.GameMode'
import 'org.bukkit.inventory.ItemStack'
# WorldGuard imports
import 'com.sk89q.worldguard.protection.managers.RegionManager'
import 'com.sk89q.worldguard.protection.ApplicableRegionSet'
import 'com.sk89q.worldguard.bukkit.BukkitUtil'
# Ruby Libraries
require 'yaml'
# Libraries
require 'SpoutBoost/lib/data'
require 'SpoutBoost/lib/permissions'
require 'SpoutBoost/lib/inventory_listener'
#### Main Plugin ####
# Pretty much everything happens here.
class SpoutBoost < RubyPlugin
#### I/O to Console ####
# TODO: Set logger prefix & use @log.info, @log.debug, etc.
def info msg # Standard output to console.
# Uses bash escape codes for pretty colors.
@logger.info "\e[36m[\e[32mSpoutCraft\e[36m] #{msg}\e[0m"
end
def debug msg # Debug output to console.
# Uses bash escape codes for pretty colors.
@logger.info "\e[33m[\e[32mSpoutCraft\e[33m] #{msg}\e[0m"
end
def err msg # Used for error messages.
# Uses bash escape codes for pretty colors.
@logger.log Level::WARNING, "\e[31m[\e[32mSpoutCraft\e[31m] #{msg}\e[0m"
end
# Housekeeping for directories.
def check_dirs
files = ["./SpoutBoost","./SpoutBoost/inventory","./SpoutBoost/inventory/creative","./SpoutBoost/inventory/survival"]
files.each do |object|
file_path = File.join(File.dirname(__FILE__),object)
if !File.exists?(file_path)
info "Mkdir: #{file_path}"
Dir.mkdir(file_path)
end
end
end
def load_config
config_file = File.join(File.dirname(__FILE__),"./SpoutBoost/config.yml")
if File.exists?(config_file)
File.open(config_file, "r") do |object|
debug "loading config"
@conf = YAML::load(object)
end
debug "Config loaded."
else
@conf = ConfigBase.new
debug "Created new config file."
save_config
end
end
def save_config
config_file = File.join(File.dirname(__FILE__),"./SpoutBoost/config.yml")
File.open(config_file, "w") do |file|
file.print YAML::dump(@conf)
end
end
def save_inv player, dir
inv_file = File.join(File.dirname(__FILE__),"./SpoutBoost/inventory/#{dir}/#{player.getName}.yml")
File.open(inv_file, "w") do |file|
file.print YAML::dump(PlayerInv.new(player.getInventory.getContents))
end
end
def load_inv player, dir
config_file = File.join(File.dirname(__FILE__),"./SpoutBoost/inventory/#{dir}/#{player.getName}.yml")
if File.exists?(config_file)
File.open(config_file, "r") do |object|
debug "loading config"
player.getInventory.setContents YAML::load(object).get_inv.to_java(ItemStack)
end
debug "Inventory loaded."
else
debug "No inventory found! Setting to blank."
end
end
def onEnable
@logger = Logger.getLogger("Minecraft")
check_dirs
load_config
@pm = getServer.getPluginManager
# TODO: Add password security. Below is a method stub.
if false
info "Password enabled."
registerEvent(Event::Type::PLAYER_LOGIN, Event::Priority::Normal) do |infoinEvent|
scheduleSyncDelayedTask(1) do
player = SpoutManager::getPlayer(infoinEvent.getPlayer)
popup = GenericPopup.new
text = GenericLabel.new @conf.motd
text.setAuto(true)
text.setResize(true)
text.setFixed(false)
text.setAlign(WidgetAnchor::TOP_CENTER)
text.setAnchor(WidgetAnchor::TOP_CENTER)
text.doResize()
esc = GenericLabel.new "Press ESC to close"
esc.setAlign(WidgetAnchor::BOTTOM_CENTER)
esc.setAnchor(WidgetAnchor::BOTTOM_CENTER)
esc.setFixed(false)
esc.setResize(true)
esc.doResize()
popup.attachWidget(self, text)
popup.attachWidget(self, esc)
player.getMainScreen().attachPopupScreen(popup)
info "Created MOTD for #{player.getDisplayName()}"
end
end
end
# MOTD handling code.
# TODO: Add close button or Rules Accept/Deny button.
if @conf.motd
info "MOTD enabled."
registerEvent(Event::Type::PLAYER_JOIN, Event::Priority::Normal) do |infoinEvent|
scheduleSyncDelayedTask(1) do
player = SpoutManager::getPlayer(infoinEvent.getPlayer)
popup = GenericPopup.new
text = GenericLabel.new @conf.motd
text.setAuto(true)
text.setResize(true)
text.setFixed(false)
text.setAlign(WidgetAnchor::TOP_CENTER)
text.setAnchor(WidgetAnchor::TOP_CENTER)
text.doResize()
esc = GenericLabel.new "Press ESC to close"
esc.setAlign(WidgetAnchor::BOTTOM_CENTER)
esc.setAnchor(WidgetAnchor::BOTTOM_CENTER)
esc.setFixed(false)
esc.setResize(true)
esc.doResize()
popup.attachWidget(self, text)
popup.attachWidget(self, esc)
player.getMainScreen().attachPopupScreen(popup)
info "Created MOTD for #{player.getDisplayName()}"
end
end
end
# Extra player data handling code.
registerEvent(Event::Type::PLAYER_JOIN, Event::Priority::Normal) do |event|
scheduleSyncDelayedTask(1) do
player = SpoutManager::getPlayer(event.getPlayer)
player_data = PlayerData.new player
@players.store(player,player_data)
player_data.set_texture_pack(@conf.default_texture_pack)
info "Set texture pack for #{player.getDisplayName()}"
update_region player
end
end
# Region move events.
# TODO: Region persistence via YAML w/ ingame commands.
if @conf.regions
info "Regions are enabled."
registerEvent(Event::Type::PLAYER_MOVE, Event::Priority::Normal) do |event|
player = SpoutManager::getPlayer(event.getPlayer)
update_region player
end
registerEvent(Event::Type::PLAYER_DROP_ITEM, Event::Priority::Normal) do |event|
if event.getPlayer.getGameMode == GameMode::CREATIVE
event.getItemDrop.remove
event.setCancelled(true)
end
end
registerEvent(Event::Type::BLOCK_PLACE, Event::Priority::Normal) do |event|
if event.getPlayer.getGameMode == GameMode::CREATIVE
pt = BukkitUtil.toVector(player.getBlockPlaced.getLocation)
rm = @wg.getRegionManager(player.getWorld)
set = rm.getApplicableRegions(pt).iterator
player_data = @players[player]
in_region = false
while set.hasNext
elem = set.next
region = @conf.regions[elem.getId]
if region
in_region = true
# Player entered/switched region.
if region.id!=player_data.region
if !region.creative
event.setCancelled true
end
end
end
end
if !in_region && !@conf.default_creative
event.setCancelled true
end
end
end
@pm.registerEvent(Event::Type::CUSTOM_EVENT, BoostListener.new, Event::Priority::Normal, self)
end
# Attempt to find worldguard. May later pop errors if worldguard is reloaded. (Spout doesn't like being reloaded.)
# TODO: Better error handling (may not need it).
@wg = @pm.getPlugin("WorldGuard")
if !@wg
err "Worldguard not found. Errors will probably occur!"
end
@players = {}
info "Enabled."
end
def onDisable
# TODO: Save yamls for players/regions (seperate function?).
info "Disabled."
end
def onCommand(sender, cmd, label, args)
# TODO: Region commands.
player = SpoutManager::getPlayer(sender.getPlayer)
if cmd.getName()=="title"||cmd.getName()=="settitle"
if args.length==1&&player.has("SpoutBoost.title.self")
player.setTitle args[0]
info "Set #{player.getDisplayName}'s title."
return true
elsif args.length==2&&player.has("SpoutBoost.title.other")
player.setTitle args[0]
info "#{sender.getPlayer.getDisplayName} set #{player.getDisplayName}'s title."
return true
end
end
if cmd.getName()=="spreload"&&player.has("SpoutBoost.reload")
load_config
return true
end
return false
end
# Easy method to update region info (used during move events & player join)
def update_region player
if !@conf.regions
return
end
# TODO: Consider switching from event driven to time driven for less server impact.
pt = BukkitUtil.toVector(player.getLocation)
rm = @wg.getRegionManager(player.getWorld)
set = rm.getApplicableRegions(pt).iterator
player_data = @players[player]
in_region = false
while set.hasNext
elem = set.next
region = @conf.regions[elem.getId]
if region
in_region = true
# Player entered/switched region.
if region.id!=player_data.region
if player_data.region==""
info "#{player.getDisplayName} has entered region: #{region.id}."
player.sendMessage("You have entered region: #{region.id}.")
elsif
info "#{player.getDisplayName} has left region: #{player_data.region}; to enter region: #{region.id}."
player.sendMessage "You have left region #{player_data.region}; to enter region: #{region.id}."
end
player_data.region = region.id
region_mode = GameMode::SURVIVAL
if region.creative
region_mode = GameMode::CREATIVE
end
mode = player.getGameMode
if region_mode != mode
set_gamemode player, region_mode
end
player_data.set_texture_pack region.texture_pack
end
end
end
# Player left region.
if !in_region && player_data.region!=""
info "#{player.getDisplayName} has left region: #{player_data.region}."
player.sendMessage("You have left region: #{player_data.region}.")
player_data.region = ""
default_mode = GameMode::SURVIVAL
if @conf.default_creative
default_mode = GameMode::CREATIVE
end
if default_mode != player.getGameMode
set_gamemode player, default_mode
end
player_data.set_texture_pack @conf.default_texture_pack
end
end
def set_gamemode player, gamemode
old_dir = "creative"
dir = "survival"
if gamemode == GameMode::CREATIVE
dir = "creative"
old_dir = "survival"
end
save_inv player, old_dir
load_inv player, dir
player.setGameMode gamemode
end
end