This repository has been archived on 2024-08-27. You can view files and clone it, but cannot push or open issues or pull requests.
redstoner-utils/tilehelper.py

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))