blockplacemods update, basecommands fix

Added settings: piston, dropper, hopper
changes to the framework
made it so you can set the default contents for all slots in
furnaces/droppers as well as furnaces.
This commit is contained in:
Dico200
2015-05-18 23:05:54 +02:00
parent 057b404b03
commit bd05374db0
2 changed files with 266 additions and 97 deletions

View File

@@ -79,8 +79,8 @@ class CommandException(Exception):
class Validate(): class Validate():
@staticmethod @staticmethod
def notNone(obj, msg): def notNone(obj, msg):
if obj == null: if obj == None:
raise Exception(msg) raise CommandException(msg)
@staticmethod @staticmethod
def isPlayer(sender): def isPlayer(sender):
@@ -93,9 +93,9 @@ class Validate():
raise CommandException("&cThat command can only be run from the console") raise CommandException("&cThat command can only be run from the console")
@staticmethod @staticmethod
def isAuthorized(sender, permission): def isAuthorized(sender, permission, msg = "that command"):
if not sender.hasPermission(permission): if not sender.hasPermission(permission):
raise CommandException("&cYou do not have permission to use that command") raise CommandException("&cYou do not have permission to use " + msg)
@staticmethod @staticmethod
def isTrue(obj, msg): def isTrue(obj, msg):

View File

@@ -1,49 +1,93 @@
from helpers import * from helpers import *
from basecommands import simplecommand from basecommands import simplecommand, Validate, CommandException
from time import sleep
from collections import deque
import thread
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.block.Furnace as Furnace import org.bukkit.block.Furnace as Furnace
import org.bukkit.inventory.ItemStack as ItemStack import org.bukkit.inventory.ItemStack as ItemStack
import org.bukkit.Material as Material import org.bukkit.Material as Material
import org.bukkit.event.block.Action as Action
import org.bukkit.block.BlockFace as BlockFace
import org.bukkit.scheduler.BukkitRunnable as Runnable
settingInformation = { settingInformation = dict( #[setting type, identifying description, detailed description, aliases, (optional) max slot id], setting types: 0 = toggle, default on. 1 = Set your setting to held itemstack, 2 = toggle, default off
"cauldron": [0, cauldron = [0,
"easy cauldron water level control", "easy cauldron water level control",
"Toggles whether cauldrons auto-fill upon placement and whether right clicking them with redstone dust or empty hand will cycle their water level" "Toggles whether cauldrons auto-fill upon placement and whether right clicking them with redstone dust or empty hand will cycle their water level",
["caul", "water"]
], ],
"slab": [0, slab = [0,
"automatically flipping placed slabs upside-down", "automatically flipping placed slabs upside-down",
"Toggles whether slabs/steps which you place should be automatically flipped upside-down" "Toggles whether slabs/steps which you place should be automatically flipped upside-down",
["step"]
], ],
"furnace": [1, furnace = [1,
"automatically filling furnaces upon placement", "automatically filling furnaces upon placement",
"Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to disable this feature. The command is &o/toggle furnace" "Sets your preferred default furnace contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
["cooker", "fillf"], 2
],
#torch = [0,
# "removal of torches you place on redstone blocks",
# "Toggles whether redstone torches which you place on redstone blocks will be deleted after a short amount of delay.",
# ["redstonetorch", "tor"]
#],
piston = [2,
"rotating pistons, droppers and hoppers to face the block you place them against",
"Toggles whether pistons or sticky pistons which you place will be rotated to face the block which you placed them against.",
["invert", "rp"]
],
dropper = [1,
"automatically filling droppers upon placement",
"Sets your preferred default dropper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
["itemshooter", "filld"], 8
],
hopper = [1,
"automatically filling hoppers upon placement",
"Sets your preferred default hopper contents to your currently held itemstack. Use an empty hand to empty a slot, or /toggle dropper clear to clear all slots.",
["itemtransporter", "fillh"], 4
] ]
)
defaults = {
0: [],
1: {},
2: []
} }
defaultPlayerSettings = { faces = {
"cauldron": [], BlockFace.DOWN : 0,
"slab": [], BlockFace.UP : 1,
"furnace": {} BlockFace.NORTH : 2,
BlockFace.SOUTH : 3,
BlockFace.WEST : 4,
BlockFace.EAST : 5
} }
playerSettings = open_json_file("blockplacemods", defaultPlayerSettings) playerSettings = open_json_file("blockplacemods", {})
for setting, details in settingInformation.iteritems():
#for setting, default in enumerate(defaultPlayerSettings): if playerSettings.get(setting) == None:
# if playerSettings.get(setting) == None: playerSettings[setting] = defaults[details[0]]
# playerSettings[setting] = default
def get(setting): def get(setting):
return playerSettings[setting] return playerSettings[setting]
def saveSettings(): def saveSettings():
save_json_file("blockplacemods", playerSettings) save_json_file("blockplacemods", playerSettings)
def getSettingDetails(arg):
try:
arg = arg.lower()
for setting, details in settingInformation.iteritems():
if setting == arg or arg in details[3]:
return (setting, details)
except:
error(trace())
raise CommandException(" &cThat setting could not be found.\n For command help, use &o/toggle &cor &o/set")
@simplecommand("toggle", @simplecommand("toggle",
aliases = ["set"], aliases = ["setting", "set", "config"],
usage = "<setting> [value|info]", usage = "<setting> [value|info]",
description = "Toggles or sets your preferences for our redstone \nutilities. The following settings are available:\n" + ", ".join([x for x in settingInformation]), description = "Toggles or sets your preferences for our redstone \nutilities. The following settings are available:\n" + ", ".join([x for x in settingInformation]),
senderLimit = 0, senderLimit = 0,
@@ -51,33 +95,113 @@ def saveSettings():
helpSubcmd = True, helpSubcmd = True,
amax = 2) amax = 2)
def toggle_command(sender, command, label, args): def toggle_command(sender, command, label, args):
setting = args[0].lower() try:
info = settingInformation.get(setting) setting, details = getSettingDetails(args[0])
if info == None: Validate.isAuthorized(sender, "utils.toggle." + setting, "that setting")
return " &cThat setting could not be found.\n For command help, use &o/toggle &cor &o/set"
values = get(setting) values = get(setting)
player = server.getPlayer(sender.getName()) player = server.getPlayer(sender.getName())
uuid = uid(player) uuid = uid(player)
arglen = len(args) arglen = len(args)
if info[0] == 0: # Toggle if details[0] in (0,2): # Toggle
enabled = uuid not in values default = details[0] == 0 # If True: toggle on if list doesn't contain the uuid
enabled = (uuid not in values) == default #Invert if details[0] == 2 (toggle disabled by default)
info("Enabled: " + str(enabled))
new = None new = None
if arglen == 1: if arglen == 1:
new = not enabled new = not enabled
else: else:
arg2 = args[1].lower() arg2 = args[1].lower()
if arg2 == "info": if arg2 == "info":
return " &aSetting %s:\n &9%s\n &6Accepted arguments: None or one of the following:\n &oon, enable, off, disable, toggle, switch" % (setting, info[2]) return " &aSetting %s:\n &9%s\n &6Accepted arguments: [on|enable|off|disable|toggle|switch|info]\n &6Aliases: %s" % (setting, details[2], ", ".join(details[3]))
elif arg2 in ("toggle", "switch"): elif arg2 in ("toggle", "switch"):
new = not enabled new = not enabled
elif arg2 in ("on", "enable"): elif arg2 in ("on", "enable"):
new = True new = True == default
info("New: " + str(new))
elif arg2 in ("off", "disable"): elif arg2 in ("off", "disable"):
new = False new = False == default
info("New: " + str(new))
else: else:
return " &cArgument '%s' was not recognized. \nTry one of the following: &oon, off, toggle" % arg2 return " &cArgument '%s' was not recognized. \n Use &o/toggle %s info &cfor more information" % (arg2, setting)
if enabled == new:
return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", details[1])
if new == default:
values.remove(uuid)
else:
values.append(uuid)
saveSettings()
return (" &aEnabled " if new else " &aDisabled ") + details[1]
elif details[0] == 1: # Save ItemStack in hand
arg2 = args[1].lower() if arglen > 1 else ""
enabled = uuid in values
if arg2 == "clear":
if enabled:
del values[uuid]
return " &aDisabled " + details[1]
if arg2 == "details":
return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2])
slot = int(arg2) if arg2.isdigit() else 0
if not (0 <= slot <= details[4]):
return " &cSlot number must be between 1 and %s!" % details[4]
item = fromStack(player.getItemInHand())
if item[0] == 0 or item[1] <= 0:
if enabled:
items = values[uuid]
if slot in items:
del items[slot]
saveSettings()
if len(items) == 0:
del values[uuid]
return " &aDisabled " + details[1]
return " &aCleared slot %s of setting %s" % (slot, setting)
return " &cSlot %s of setting %s was already cleared!" % (slot, setting)
return " &cAlready disabled: " + details[1]
if arglen == 2 and not arg2.isdigit():
return " &cArgument '%s' was not recognized. \nUse &o/toggle %s details &cfor more detailsrmation." % (arg2, setting)
if not enabled:
values[uuid] = {}
values[uuid][slot] = item
saveSettings()
return ((" &aEnabled setting %s, S" % setting) if len(values[uuid]) == 1 else "&as") + "et itemstack in slot %s to item in hand" % (slot)
return None #This shouldn't happen
except CommandException, e:
raise e
except:
error(trace())
"""
if info[0] in (0,2): # Toggle
default = info[0] == 0
enabled = (uuid not in values) == default #Invert if info[0] == 2 (toggle disabled by default)
info("Enabled": True)
new = None
if arglen == 1:
new = not enabled
else:
arg2 = args[1].lower()
if arg2 == "info":
return " &aSetting %s:\n &9%s\n &6Accepted arguments: [on|enable|off|disable|toggle|switch]\n &6Aliases: %s" % (setting, info[2], ", ".join(info[3]))
elif arg2 in ("toggle", "switch"):
new = not enabled
elif arg2 in ("on", "enable"):
new = True == default
elif arg2 in ("off", "disable"):
new = False == default
else:
return " &cArgument '%s' was not recognized. \nUse &o/toggle %s info &cfor more information" % (arg2, setting)
if enabled == new: if enabled == new:
return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", info[1]) return " &cAlready %s: &a%s" % ("enabled" if enabled else "disabled", info[1])
if new: if new:
@@ -86,23 +210,8 @@ def toggle_command(sender, command, label, args):
values.append(uuid) values.append(uuid)
saveSettings() saveSettings()
return (" &aEnabled " if new else " &aDisabled ") + info[1] return (" &aEnabled " if new else " &aDisabled ") + info[1]
"""
elif info[0] == 1: # Save ItemStack in hand
if arglen == 1:
item = fromStack(player.getItemInHand())
if 0 in (item[0], item[1]):
if uuid in values:
del values[uuid]
return " &aDisabled " + info[1]
values[uuid] = item
saveSettings()
return " &aEnabled %s, with currently held itemstack" % info[1]
arg2 = args[1].lower()
if arg2 == "info":
return " &aSetting %s:\n &9%s" % (setting, info[2])
return " &cArgument '%s' was not recognized. \nUse /toggle %s info for more information." % (arg2, setting)
return None #This shouldn't happen
def fromStack(itemStack): def fromStack(itemStack):
@@ -111,12 +220,13 @@ def toStack(lst):
return ItemStack(lst[0], lst[1], lst[2]) return ItemStack(lst[0], lst[1], lst[2])
def isEnabled(toggleSetting, uuid): def isEnabled(toggleSetting, uuid):
return uuid not in get(toggleSetting) return (uuid not in get(toggleSetting)) == (settingInformation[toggleSetting][0] == 0) #Invert if off by default
@hook.event("block.BlockPlaceEvent", "monitor") @hook.event("block.BlockPlaceEvent", "monitor")
def on_block_place(event): def on_block_place(event):
try:
if event.isCancelled(): if event.isCancelled():
return return
player = event.getPlayer() player = event.getPlayer()
@@ -125,34 +235,93 @@ def on_block_place(event):
uuid = uid(player) uuid = uid(player)
block = event.getBlockPlaced() block = event.getBlockPlaced()
material = str(block.getType()) material = block.getType()
if isEnabled("slab", uuid) and material in ("WOOD_STEP", "STEP") and block.getData() < 8:
if (material in (Material.WOOD_STEP, Material.STEP)
and isEnabled("slab", uuid)
and player.hasPermission("utils.toggle.slab")
and block.getData() < 8
):
block.setData(block.getData() + 8) # Flip upside down block.setData(block.getData() + 8) # Flip upside down
elif isEnabled("cauldron", uuid) and material == "CAULDRON":
elif (material == Material.CAULDRON
and isEnabled("cauldron", uuid)
and player.hasPermission("utils.toggle.cauldron")
):
block.setData(3) #3 layers of water, 3 signal strength block.setData(3) #3 layers of water, 3 signal strength
elif material == "FURNACE":
stack = get("furnace").get(uuid) elif ((material == Material.FURNACE and player.hasPermission("utils.toggle.furnace"))
if stack == None: or (material == Material.DROPPER and player.hasPermission("utils.toggle.dropper"))
return ):
stacks = get(str(material).lower()).get(uuid)
if stacks != None: # Enabled
state = block.getState() state = block.getState()
state.getInventory().setSmelting(toStack(stack)) inv = state.getInventory()
for slot, stack in stacks.iteritems():
inv.setItem(int(slot), toStack(stack))
state.update() state.update()
"""
elif (material == Material.REDSTONE_TORCH_ON
and event.getBlockAgainst().getType() == Material.REDSTONE_BLOCK
and isEnabled("torch", uuid)
and player.hasPermission("utils.toggle.torch")
):
torches_to_break.append(block)
"""
if (material in (Material.PISTON_BASE, Material.PISTON_STICKY_BASE) #Not elif because for droppers it can do 2 things
and isEnabled("piston", uuid)
and player.hasPermission("utils.toggle.piston")
):
block.setData(faces[block.getFace(event.getBlockAgainst())])
except:
error(trace())
@hook.event("player.PlayerInteractEvent", "monitor") @hook.event("player.PlayerInteractEvent", "monitor")
def on_interact(event): def on_interact(event):
player = event.getPlayer() player = event.getPlayer()
if (isEnabled("cauldron", uid(player)) if (isEnabled("cauldron", uid(player))
and player.hasPermission("utils.toggle.cauldron")
and is_creative(player) and is_creative(player)
and str(event.getAction()) == "RIGHT_CLICK_BLOCK" and event.getAction() == Action.RIGHT_CLICK_BLOCK
and (not event.hasItem() or str(event.getItem().getType()) == "REDSTONE") and (not event.hasItem() or event.getItem().getType() == Material.REDSTONE)
and str(event.getClickedBlock().getType()) == "CAULDRON" and event.getClickedBlock().getType() == Material.CAULDRON
): ):
block = event.getClickedBlock() block = event.getClickedBlock()
event2 = BlockBreakEvent(block, player) event2 = BlockBreakEvent(block, player)
server.getPluginManager().callEvent(event2) server.getPluginManager().callEvent(event2)
if not event2.isCancelled(): if not event2.isCancelled():
block.setData(block.getData() - 1 if block.getData() > 0 else 3) block.setData(block.getData() - 1 if block.getData() > 0 else 3)
"""
break_torches = True
torches_to_break = deque()
def stop_breaking_torches():
break_torches = False
info("Interrupted torch breaking thread")
class torch_breaker(Runnable):
def run():
try:
if break_torches:
for i in range(len(torches_to_break)):
block = torches_to_break.popleft()
mat = block.getType()
if mat == Material.REDSTONE_TORCH_OFF:
block.setTypeId(0)
elif mat == Material.REDSTONE_TORCH_ON:
torches_to_break.append(block)
except:
error(trace())
"""