Package net.aufdemrand.denizen.scripts.commands.world

Source Code of net.aufdemrand.denizen.scripts.commands.world.ModifyBlockCommand

package net.aufdemrand.denizen.scripts.commands.world;

import net.aufdemrand.denizen.scripts.queues.ScriptQueue;
import net.aufdemrand.denizen.scripts.queues.core.InstantQueue;
import net.aufdemrand.denizencore.exceptions.CommandExecutionException;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.scripts.commands.AbstractCommand;

import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.scripts.commands.Holdable;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.ArrayList;
import java.util.List;

/**
* Modifies blocks based based of single block location.
* Possibility to do faux animations with blocks.
*
* @author Mason Adkins, aufdemrand, mcmonkey
*/

public class ModifyBlockCommand extends AbstractCommand implements Listener, Holdable {

    @Override
    public void parseArgs(ScriptEntry scriptEntry)throws InvalidArgumentsException {

        // Parse arguments
        for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) {

            if (arg.matchesArgumentList(dLocation.class)){
                scriptEntry.addObject("locations", arg.asType(dList.class).filter(dLocation.class));
            }

            else if (!scriptEntry.hasObject("materials")
                    && arg.matchesArgumentList(dMaterial.class)) {
                scriptEntry.addObject("materials", arg.asType(dList.class));
            }

            else if (!scriptEntry.hasObject("radius")
                    && arg.matchesPrefix("radius", "r")
                    && arg.matchesPrimitive(aH.PrimitiveType.Integer)) {
                scriptEntry.addObject("radius", new Element(arg.getValue()));
            }

            else if (!scriptEntry.hasObject("height")
                    && arg.matchesPrefix("height", "h")
                    && arg.matchesPrimitive(aH.PrimitiveType.Integer)) {
                scriptEntry.addObject("height", new Element(arg.getValue()));
            }

            else if (!scriptEntry.hasObject("depth")
                    && arg.matchesPrefix("depth", "d")
                    && arg.matchesPrimitive(aH.PrimitiveType.Integer)) {
                scriptEntry.addObject("depth", new Element(arg.getValue()));
            }

            else if (arg.matches("no_physics"))
                scriptEntry.addObject("physics", new Element(false));

            else if (arg.matches("naturally"))
                scriptEntry.addObject("natural", new Element(true));

            else if (arg.matches("delayed"))
                scriptEntry.addObject("delayed", new Element(true));

            else if (!scriptEntry.hasObject("script")
                    && arg.matchesArgumentType(dScript.class))
                scriptEntry.addObject("script", arg.asType(dScript.class));

            else
                arg.reportUnhandled();
        }

        // Must have material
        if (!scriptEntry.hasObject("materials"))
            throw new InvalidArgumentsException("Missing material argument!");

        // ..and at least one location.
        if (!scriptEntry.hasObject("locations"))
            throw new InvalidArgumentsException("Missing location argument!");

        // Set some defaults
        scriptEntry.defaultObject("radius", new Element(0))
                .defaultObject("height", new Element(0))
                .defaultObject("depth", new Element(0))
                .defaultObject("physics", new Element(true))
                .defaultObject("natural", new Element(false))
                .defaultObject("delayed", new Element(false));

    }


    @Override
    public void execute(final ScriptEntry scriptEntry) throws CommandExecutionException {

        final dList materials = (dList) scriptEntry.getObject("materials");
        final List<dObject> locations = (List<dObject>) scriptEntry.getObject("locations");
        final Element physics = scriptEntry.getElement("physics");
        final Element natural = scriptEntry.getElement("natural");
        final Element delayed = scriptEntry.getElement("delayed");
        final Element radiusElement = scriptEntry.getElement("radius");
        final Element heightElement = scriptEntry.getElement("height");
        final Element depthElement = scriptEntry.getElement("depth");
        final List<dMaterial> materialList = materials.filter(dMaterial.class);
        final dScript script = scriptEntry.getdObject("script");

        dB.report(scriptEntry, getName(), aH.debugList("locations", locations)
                                          + materials.debug()
                                          + physics.debug()
                                          + radiusElement.debug()
                                          + heightElement.debug()
                                          + depthElement.debug()
                                          + natural.debug()
                                          + delayed.debug()
                                          + (script != null ? script.debug(): ""));

        final boolean doPhysics = physics.asBoolean();
        final  boolean isNatural = natural.asBoolean();
        final int radius = radiusElement.asInt();
        final int height = heightElement.asInt();
        final int depth = depthElement.asInt();

        no_physics = !doPhysics;
        if (delayed.asBoolean()) {
            new BukkitRunnable() {
                @Override
                public void run() {
                    boolean was_static = preSetup(locations);
                    int index = 0;
                    long start = System.currentTimeMillis();
                    Location loc = (dLocation)locations.get(0);
                    while (locations.size() > 0) {
                        handleLocation((dLocation) locations.get(0), index, materialList, doPhysics, isNatural, radius, height, depth);
                        locations.remove(0);
                        if (System.currentTimeMillis() - start > 50) {
                            break;
                        }
                    }
                    postComplete(loc, was_static);
                    if (locations.size() == 0) {
                        if (script != null) {
                            List<ScriptEntry> entries = script.getContainer().getBaseEntries(scriptEntry.entryData.clone());
                            ScriptQueue queue = InstantQueue.getQueue(ScriptQueue.getNextId(script.getContainer().getName()))
                                    .addEntries(entries);
                            queue.start();
                        }
                        scriptEntry.setFinished(true);
                        cancel();
                    }
                }
            }.runTaskTimer(DenizenAPI.getCurrentInstance(), 1, 1);
        }
        else {
            boolean was_static = preSetup(locations);
            Location loc = (dLocation)locations.get(0);
            int index = 0;
            for (dObject obj : locations) {
                handleLocation((dLocation) obj, index, materialList, doPhysics, isNatural, radius, height, depth);
            }
            postComplete(loc, was_static);
            scriptEntry.setFinished(true);
        }
    }

    boolean preSetup(List<dObject> locations) {
        if (locations.size() == 0)
            return false;
        // Freeze the first world in the list.
        CraftWorld craftWorld = (CraftWorld)((dLocation)locations.get(0)).getWorld();
        boolean was_static = craftWorld.getHandle().isStatic;
        if (no_physics)
            craftWorld.getHandle().isStatic = true;
        return was_static;
    }

    void postComplete(Location loc, boolean was_static) {
        // Unfreeze the first world in the list.
        CraftWorld craftWorld = (CraftWorld)loc.getWorld();
        if (no_physics)
            craftWorld.getHandle().isStatic = was_static;
        no_physics = false;
    }

    void handleLocation(dLocation location, int index, List<dMaterial> materialList, boolean doPhysics,
                        boolean isNatural, int radius, int height, int depth) {

        dMaterial material = materialList.get(index % materialList.size());
        index++;
        World world = location.getWorld();

        location.setX(location.getBlockX());
        location.setY(location.getBlockY());
        location.setZ(location.getBlockZ());
        setBlock(location, material, doPhysics, isNatural);

        if (radius != 0){
            for (int x = 0; x  < 2 * radius + 1;  x++) {
                for (int z = 0; z < 2 * radius + 1; z++) {
                    setBlock(new Location(world, location.getX() + x - radius, location.getY(), location.getZ() + z - radius), material, doPhysics, isNatural);
                }
            }
        }

        if (height != 0){
            for (int x = 0; x  < 2 * radius + 1;  x++) {
                for (int z = 0; z < 2 * radius + 1; z++) {
                    for (int y = 1; y < height + 1; y++) {
                        setBlock(new Location(world, location.getX() + x - radius, location.getY() + y, location.getZ() + z - radius), material, doPhysics, isNatural);
                    }
                }
            }
        }

        if (depth != 0){
            for (int x = 0; x  < 2 * radius + 1;  x++) {
                for (int z = 0; z < 2 * radius + 1; z++) {
                    for (int y = 1; y < depth + 1; y++) {
                        setBlock(new Location(world, location.getX() + x - radius, location.getY() - y, location.getZ() + z - radius), material, doPhysics, isNatural);
                    }
                }
            }
        }
    }

    void setBlock(Location location, dMaterial material, boolean physics, boolean natural) {
        if (physics) {
            for (int i = 0; i < block_physics.size(); i++) {
                if (compareloc(block_physics.get(i), location))
                    block_physics.remove(i--);
            }
        }
        else {
            block_physics.add(location);
            physitick = tick;
        }
        if (natural && material.getMaterial() == Material.AIR)
            location.getBlock().breakNaturally();
        else
            location.getBlock().setTypeIdAndData(material.getMaterial().getId(), material.getMaterialData().getData(), physics);
    }

    boolean no_physics = false;

    public final List<Location> block_physics = new ArrayList<Location>();

    long tick = 0;

    long physitick = 0;

    @Override
    public void onEnable() {
        DenizenAPI.getCurrentInstance().getServer().getPluginManager()
                .registerEvents(this, DenizenAPI.getCurrentInstance());
        // Keep the list empty automatically - we don't want to still block physics so much later that something else edited the block!
        Bukkit.getScheduler().scheduleSyncRepeatingTask(DenizenAPI.getCurrentInstance(), new Runnable() {
            @Override
            public void run() {
                tick++;
                if (physitick < tick - 1)
                    block_physics.clear();
            }
        }, 2, 2);
    }


    @EventHandler
    public void blockPhysics(BlockPhysicsEvent event) {
        if (no_physics)
            event.setCancelled(true);
        for (Location loc: block_physics) {
            if (compareloc(event.getBlock().getLocation(), loc))
                event.setCancelled(true);
        }
    }

    @EventHandler
    public void blockChanges(EntityChangeBlockEvent event) {
        if (event.getEntity().getType() != EntityType.FALLING_BLOCK)
            return;
        if (no_physics)
            event.setCancelled(true);
        for (Location loc: block_physics) {
            if (compareloc(event.getBlock().getLocation(), loc))
                event.setCancelled(true);
        }
    }

    boolean compareloc(Location lone, Location ltwo) {
        return lone.getBlockX() == ltwo.getBlockX() && lone.getBlockY() == ltwo.getBlockY() &&
                lone.getBlockZ() == ltwo.getBlockZ() && lone.getWorld().getName().equalsIgnoreCase(ltwo.getWorld().getName());
    }
}
TOP

Related Classes of net.aufdemrand.denizen.scripts.commands.world.ModifyBlockCommand

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.