Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

95 lines (82 sloc) 3.609 kb
# Allow placed signs to behave as a teleporter when right clicked on. The format
# for the sign is line one containing 'Teleporter' and line two containing either:
# a) x, y, z (base 36 offset by +32000) b) {locs_plus_waypoint_name}. In the case of b it
# will substitute that name with the loc it represents when the sign is placed. You can write
# anything on lines 3 or lower and it will not affect how the sign works as a teleporter.
class PortsPlugin
include Purugin::Plugin, Purugin::Colors
description 'Ports', 0.3
required :LocsPlus, :include => :CoordinateEncoding
def teleporter_loc(state)
return nil if state.lines.length < 2 || state.get_line(0) != "Teleporter"
state.get_line(1)
end
SAFE_BLOCKS = [:air, :water]
def safe_loc?(me, bottom_block)
top_block = bottom_block.block_at(:up)
floor_block = bottom_block.block_at(:down)
top_block.is?(*SAFE_BLOCKS) && bottom_block.is?(*SAFE_BLOCKS) &&
floor_block.solid?
end
# Attempts to find a safe location when block under your feet is solid
# and where both blocks your player occupies are either air or water.
# The algorithm is to try the location you want. If it does not work then
# try all adjacent squares. If that does not work go _direction_ one and
# repeat. This will fail after limit tries.
def safe_loc(me, world, location, limit = 3, direction = -1)
return nil if limit <= 0
bottom_block = world.block_at(location)
return location if safe_loc?(me, bottom_block)
[:north, :east, :west, :south].each do |direction|
alt_block = bottom_block.block_at(direction)
return alt_block.location if safe_loc?(me, alt_block)
end
return safe_loc(me, world, org.bukkit.Location.new(world, location.x, location.y + direction, location.z), limit - 1, direction)
end
def on_enable
event(:player_interact) do |e|
if e.right_click_block? && e.clicked_block.is?(:sign_post, :wall_sign)
loc = teleporter_loc e.clicked_block.state
return unless loc
if loc =~ /([^\x00-\x7F].)?([0-9a-z]+)\s*,\s*([0-9a-z]+)\s*,\s*([0-9a-z]+)/u
x, y, z = $2, $3, $4
loc = org.bukkit.Location.new e.player.world, decode(x), decode(y), decode(z)
# Look from waypoint down
destination = safe_loc(e.player, e.player.world, loc, 5, -1)
# If no safe point then look up
destination = safe_loc(e.player, e.player.world, loc, 5, 1) unless destination
if destination
server.scheduler.schedule_sync_delayed_task(self) { e.player.teleport destination }
else
e.player.msg red("Crud at destination!")
end
end
end
end
# When signs are placed it will look for {my_waypoint} on the loc line. If it finds
# this it will ask LocsPlus plugin if such a waypoint exists. If so it substitures the
# the loc in for the name.
event(:sign_change) do |e|
loc = teleporter_loc e
return unless loc
if loc =~ /\{([^}]+)\}/
waypoint = $1
begin
loc = LocsPlus().location(e.player, waypoint).to_a
rescue ArgumentError
e.player.msg red($!.message)
break
end
end
e.lines.to_a.each_with_index do |line, i|
if i == 1 && loc
e.set_line i, gray(loc[0..2].to_a.map {|l| encode(l) }.join(","))
elsif i == 2 and line == "" && waypoint
e.set_line i, green(waypoint)
else
e.set_line i, colorize(line)
end
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.