137 lines
6.1 KiB
Python
137 lines
6.1 KiB
Python
#pylint: disable = F0401
|
|
"""
|
|
A plugin that automatically tiles (stacks) blocks inside a selected region in configurable directions.
|
|
"""
|
|
import org.bukkit.event.block.BlockPlaceEvent as BlockPlaceEvent
|
|
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
|
|
import org.bukkit.event.player.PlayerInteractEvent as PlayerInteractEvent
|
|
import thread
|
|
from time import sleep
|
|
from helpers import *
|
|
|
|
tilehelpers = open_json_file("tilehelpers", [])
|
|
|
|
dirmap = {
|
|
# [x, y, z]
|
|
"n": [0, 0, -1],
|
|
"e": [+1, 0, 0],
|
|
"s": [0, 0, +1],
|
|
"w": [-1, 0, 0],
|
|
"u": [0, +1, 0],
|
|
"d": [0, -1, 0]
|
|
}
|
|
|
|
# FIXME: disallow multiple regions by single person.
|
|
# FIXME: could lead to two regions updating each other forever -> server freezes
|
|
|
|
|
|
@hook.event("block.BlockPlaceEvent", "low")
|
|
def on_place_block(event):
|
|
if not event.isCancelled():
|
|
player = event.getPlayer()
|
|
block = event.getBlockPlaced()
|
|
for th in tilehelpers:
|
|
area = th.get("area")
|
|
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1) and event.canBuild():
|
|
|
|
# stack block in directions
|
|
for direction in th.get("directions"):
|
|
directions = dirmap[direction]
|
|
size = [
|
|
1 + abs(area[0][1] - area[0][0]),
|
|
1 + abs(area[1][1] - area[1][0]),
|
|
1 + abs(area[2][1] - area[2][0])
|
|
]
|
|
against = event.getBlockAgainst()
|
|
|
|
newblock = block.getWorld().getBlockAt(
|
|
block.getX() + size[0] * directions[0],
|
|
block.getY() + size[1] * directions[1],
|
|
block.getZ() + size[2] * directions[2]
|
|
)
|
|
|
|
newagainst = against.getWorld().getBlockAt(
|
|
against.getX() + size[0] * directions[0],
|
|
against.getY() + size[1] * directions[1],
|
|
against.getZ() + size[2] * directions[2]
|
|
)
|
|
newstate = newblock.getState()
|
|
newstate.setType(block.getType())
|
|
newstate.setData(block.getState().getData())
|
|
|
|
event = BlockPlaceEvent(newstate.getBlock(), newblock.getState(), newagainst, event.getItemInHand(), player, event.canBuild())
|
|
server.getPluginManager().callEvent(event)
|
|
if not event.isCancelled():
|
|
newblock.setType(block.getType())
|
|
newblock.setData(block.getData())
|
|
|
|
|
|
@hook.event("block.BlockBreakEvent", "low")
|
|
def on_break_block(event):
|
|
if not event.isCancelled():
|
|
player = event.getPlayer()
|
|
block = event.getBlock()
|
|
for th in tilehelpers:
|
|
area = th.get("area")
|
|
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1):
|
|
|
|
# stack block in directions
|
|
for direction in th.get("directions"):
|
|
directions = dirmap[direction]
|
|
size = [
|
|
1 + abs(area[0][1] - area[0][0]),
|
|
1 + abs(area[1][1] - area[1][0]),
|
|
1 + abs(area[2][1] - area[2][0])
|
|
]
|
|
|
|
newblock = block.getWorld().getBlockAt(
|
|
block.getX() + size[0] * directions[0],
|
|
block.getY() + size[1] * directions[1],
|
|
block.getZ() + size[2] * directions[2]
|
|
)
|
|
|
|
event = BlockBreakEvent(newblock, player)
|
|
server.getPluginManager().callEvent(event)
|
|
if not event.isCancelled():
|
|
newblock.setTypeId(0)
|
|
|
|
|
|
@hook.event("player.PlayerInteractEvent", "low")
|
|
def on_block_interact(event):
|
|
action = event.getAction()
|
|
if not event.isCancelled() and str(action) == "RIGHT_CLICK_BLOCK":
|
|
player = event.getPlayer()
|
|
block = event.getClickedBlock()
|
|
for th in tilehelpers:
|
|
area = th.get("area")
|
|
if th.get("owner") == uid(player) and str(block.getWorld().getUID()) == th.get("world") and block.getX() in range(area[0][0], area[0][1]+1) and block.getY() in range(area[1][0], area[1][1]+1) and block.getZ() in range(area[2][0], area[2][1]+1):
|
|
|
|
# stack block in directions
|
|
for direction in th.get("directions"):
|
|
directions = dirmap[direction]
|
|
size = [
|
|
1 + abs(area[0][1] - area[0][0]),
|
|
1 + abs(area[1][1] - area[1][0]),
|
|
1 + abs(area[2][1] - area[2][0])
|
|
]
|
|
|
|
newblock = block.getWorld().getBlockAt(
|
|
block.getX() + size[0] * directions[0],
|
|
block.getY() + size[1] * directions[1],
|
|
block.getZ() + size[2] * directions[2]
|
|
)
|
|
|
|
event = PlayerInteractEvent(event.getPlayer(), action, event.getItem(), newblock, event.getBlockFace())
|
|
server.getPluginManager().callEvent(event)
|
|
if not event.isCancelled():
|
|
# FIXME: do not use bukkit API calls outside main thread
|
|
thread.start_new_thread(update_block, (block, newblock))
|
|
|
|
|
|
def update_block(block, newblock):
|
|
try: # we're in a thread, the universe may hace collapsed in another thread
|
|
sleep(0.2)
|
|
newblock.setType(block.getType())
|
|
newblock.setData(block.getData())
|
|
except Exception, e:
|
|
error("Failed to update %s block in %s at %s,%s,%s: '%s'" % (str(block.getType()), block.getWorld().getName(), block.getX(), block.getY(), block.getZ(), e)) |