Package com.sk89q.craftbook.mechanics

Source Code of com.sk89q.craftbook.mechanics.LightSwitch

// $Id$
/*
* CraftBook Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not,
* see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.craftbook.mechanics;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.SignChangeEvent;

import com.sk89q.craftbook.AbstractCraftBookMechanic;
import com.sk89q.craftbook.ChangedSign;
import com.sk89q.craftbook.LocalPlayer;
import com.sk89q.craftbook.bukkit.CraftBookPlugin;
import com.sk89q.craftbook.bukkit.util.BukkitUtil;
import com.sk89q.craftbook.util.EventUtil;
import com.sk89q.craftbook.util.HistoryHashMap;
import com.sk89q.craftbook.util.ProtectionUtil;
import com.sk89q.craftbook.util.SignUtil;
import com.sk89q.craftbook.util.events.SignClickEvent;
import com.sk89q.util.yaml.YAMLProcessor;

/**
* Handler for Light switches. Toggles all torches in the area from being redstone to normal torches. This is done
* every time a sign with [|] or [I]
* is right clicked by a player.
*
* @author fullwall
*/
public class LightSwitch extends AbstractCraftBookMechanic {

    @Override
    public boolean enable() {

        recentLightToggles = new HistoryHashMap<Location, Long>(20);
        return true;
    }

    /**
     * Store a list of recent light toggles to prevent spamming. Someone clever can just use two signs though.
     */
    private HistoryHashMap<Location, Long> recentLightToggles;

    @EventHandler(priority = EventPriority.HIGH)
    public void onSignChange(SignChangeEvent event) {

        if(!EventUtil.passesFilter(event)) return;

        if(!event.getLine(1).equalsIgnoreCase("[i]") && !event.getLine(1).equalsIgnoreCase("[|]")) return;
        LocalPlayer lplayer = CraftBookPlugin.inst().wrapPlayer(event.getPlayer());
        if(!lplayer.hasPermission("craftbook.mech.light-switch")) {
            if(CraftBookPlugin.inst().getConfiguration().showPermissionMessages)
                lplayer.printError("You don't have permission for this.");
            SignUtil.cancelSign(event);
            return;
        }

        event.setLine(1, "[I]");
        lplayer.print("mech.lightswitch.create");
    }

    @EventHandler(priority = EventPriority.HIGH)
    public void onRightClick(SignClickEvent event) {

        if(event.getAction() != Action.RIGHT_CLICK_BLOCK) return;

        ChangedSign sign = event.getSign();
        if(!sign.getLine(1).equalsIgnoreCase("[I]") && !sign.getLine(1).equalsIgnoreCase("[|]")) return;

        if (!EventUtil.passesFilter(event))
            return;

        LocalPlayer player = event.getWrappedPlayer();
        if (!player.hasPermission("craftbook.mech.light-switch.use")) {
            if(CraftBookPlugin.inst().getConfiguration().showPermissionMessages)
                player.printError("mech.use-permission");
            return;
        }

        if(!ProtectionUtil.canUse(event.getPlayer(), event.getClickedBlock().getLocation(), event.getBlockFace(), event.getAction())) {
            if(CraftBookPlugin.inst().getConfiguration().showPermissionMessages)
                player.printError("area.use-permissions");
            return;
        }

        toggleLights(event.getClickedBlock(), player);
        event.setCancelled(true);
    }

    /**
     * Toggle lights in the immediate area.
     *
     * @param block
     *
     * @return true if the block was recogized as a lightswitch; this may or may not mean that any lights were
     *         actually toggled.
     */
    private boolean toggleLights(Block block, LocalPlayer player) {

        // check if this looks at all like something we're interested in first
        if (!SignUtil.isSign(block)) return false;
        int radius = Math.min(10, maxRange);
        int maximum = Math.min(maxLights, 20);
        ChangedSign sign = BukkitUtil.toChangedSign(block);
        try {
            radius = Math.min(Integer.parseInt(sign.getLine(2)), maxRange);
        } catch (Exception ignored) {
        }
        try {
            maximum = Math.min(Integer.parseInt(sign.getLine(3)), maxLights);
        } catch (Exception ignored) {
        }

        int wx = block.getX();
        int wy = block.getY();
        int wz = block.getZ();
        Material aboveID = block.getRelative(0, 1, 0).getType();

        if (aboveID == Material.TORCH || aboveID == Material.REDSTONE_TORCH_OFF || aboveID == Material.REDSTONE_TORCH_ON) {
            // Check if block above is a redstone torch.
            // Used to get what to change torches to.
            boolean on = aboveID != Material.TORCH;
            // Prevent spam
            Long lastUse = recentLightToggles.remove(block.getLocation());
            long currTime = System.currentTimeMillis();

            if (lastUse != null && currTime - lastUse < 500) {
                recentLightToggles.put(block.getLocation(), lastUse);
                return true;
            }

            recentLightToggles.put(block.getLocation(), currTime);
            int changed = 0;
            for (int x = -radius + wx; x <= radius + wx; x++) {
                for (int y = -radius + wy; y <= radius + wy; y++) {
                    for (int z = -radius + wz; z <= radius + wz; z++) {
                        Material id = block.getWorld().getBlockAt(x, y, z).getType();
                        if (id == Material.TORCH || id == Material.REDSTONE_TORCH_OFF || id == Material.REDSTONE_TORCH_ON) {
                            // Limit the maximum number of changed lights
                            if (changed >= maximum) return true;

                            if (on) {
                                block.getWorld().getBlockAt(x, y, z).setType(Material.TORCH);
                            } else {
                                block.getWorld().getBlockAt(x, y, z).setType(Material.REDSTONE_TORCH_ON);
                            }
                            changed++;
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }

    int maxRange;
    int maxLights;

    @Override
    public void loadConfiguration (YAMLProcessor config, String path) {

        config.setComment(path + "max-range", "The maximum range that the mechanic searches for lights in.");
        maxRange = config.getInt(path + "max-range", 10);

        config.setComment(path + "max-lights", "The maximum amount of lights that a Light Switch can toggle per usage.");
        maxLights = config.getInt(path + "max-lights", 20);
    }
}
TOP

Related Classes of com.sk89q.craftbook.mechanics.LightSwitch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.