Package org.spout.vanilla.command

Source Code of org.spout.vanilla.command.TestCommands

/*
* This file is part of Vanilla.
*
* Copyright (c) 2011 Spout LLC <http://www.spout.org/>
* Vanilla is licensed under the Spout License Version 1.
*
* Vanilla is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* In addition, 180 days after any changes are published, you can use the
* software, incorporating those changes, under the terms of the MIT license,
* as described in the Spout License Version 1.
*
* Vanilla 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 Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License,
* the MIT license and the Spout License Version 1 along with this program.
* If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
* License and see <http://spout.in/licensev1> for the full license, including
* the MIT license.
*/
package org.spout.vanilla.command;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;

import org.spout.api.Client;
import org.spout.api.Engine;
import org.spout.api.Platform;
import org.spout.api.command.CommandArguments;
import org.spout.api.command.CommandSource;
import org.spout.api.command.annotated.CommandDescription;
import org.spout.api.command.annotated.Filter;
import org.spout.api.command.annotated.Flag;
import org.spout.api.command.annotated.Permissible;
import org.spout.api.command.annotated.Platforms;
import org.spout.api.command.filter.PlayerFilter;
import org.spout.api.component.Component;
import org.spout.api.component.entity.InteractComponent;
import org.spout.api.entity.Entity;
import org.spout.api.entity.EntityPrefab;
import org.spout.api.entity.Player;
import org.spout.api.event.ProtocolEvent;
import org.spout.api.exception.CommandException;
import org.spout.api.generator.WorldGeneratorObject;
import org.spout.api.geo.LoadOption;
import org.spout.api.geo.World;
import org.spout.api.geo.cuboid.Block;
import org.spout.api.geo.cuboid.Chunk;
import org.spout.api.geo.discrete.Point;
import org.spout.api.geo.discrete.Transform;
import org.spout.api.inventory.ItemStack;
import org.spout.api.map.DefaultedKey;
import org.spout.api.material.BlockMaterial;
import org.spout.api.material.Material;
import org.spout.api.protocol.event.ChunkSendEvent;
import org.spout.api.protocol.event.EntityUpdateEvent;
import org.spout.api.util.BlockIterator;

import org.spout.math.imaginary.Quaternionf;
import org.spout.math.vector.Vector3f;
import org.spout.vanilla.ChatStyle;
import org.spout.vanilla.VanillaPlugin;
import org.spout.vanilla.component.block.material.chest.Chest;
import org.spout.vanilla.component.entity.VanillaEntityComponent;
import org.spout.vanilla.component.entity.inventory.PlayerInventory;
import org.spout.vanilla.component.entity.inventory.WindowHolder;
import org.spout.vanilla.component.entity.living.Ageable;
import org.spout.vanilla.component.entity.living.Human;
import org.spout.vanilla.component.entity.living.Living;
import org.spout.vanilla.component.entity.misc.Burn;
import org.spout.vanilla.component.entity.misc.Descriptor;
import org.spout.vanilla.component.entity.misc.Effects;
import org.spout.vanilla.component.entity.misc.EntityHead;
import org.spout.vanilla.component.entity.misc.Health;
import org.spout.vanilla.component.entity.misc.Hunger;
import org.spout.vanilla.component.entity.substance.FallingBlock;
import org.spout.vanilla.component.entity.substance.Item;
import org.spout.vanilla.component.entity.substance.Substance;
import org.spout.vanilla.component.entity.substance.test.ForceMessages;
import org.spout.vanilla.data.VanillaData;
import org.spout.vanilla.data.effect.EntityEffect;
import org.spout.vanilla.data.effect.EntityEffectType;
import org.spout.vanilla.data.effect.store.GeneralEffects;
import org.spout.vanilla.inventory.block.BrewingStandInventory;
import org.spout.vanilla.inventory.block.DispenserInventory;
import org.spout.vanilla.inventory.block.EnchantmentTableInventory;
import org.spout.vanilla.inventory.block.FurnaceInventory;
import org.spout.vanilla.inventory.entity.VillagerInventory;
import org.spout.vanilla.inventory.window.WindowType;
import org.spout.vanilla.inventory.window.block.BrewingStandWindow;
import org.spout.vanilla.inventory.window.block.CraftingTableWindow;
import org.spout.vanilla.inventory.window.block.DispenserWindow;
import org.spout.vanilla.inventory.window.block.EnchantmentTableWindow;
import org.spout.vanilla.inventory.window.block.FurnaceWindow;
import org.spout.vanilla.inventory.window.block.chest.ChestWindow;
import org.spout.vanilla.inventory.window.entity.VillagerWindow;
import org.spout.vanilla.material.VanillaMaterials;
import org.spout.vanilla.material.map.Map;
import org.spout.vanilla.protocol.entity.creature.CreatureType;
import org.spout.vanilla.protocol.entity.object.ObjectType;
import org.spout.vanilla.render.LightRenderEffect;
import org.spout.vanilla.render.SkyRenderEffect;
import org.spout.vanilla.scoreboard.Objective;
import org.spout.vanilla.scoreboard.ObjectiveSlot;
import org.spout.vanilla.scoreboard.Scoreboard;
import org.spout.vanilla.scoreboard.Team;
import org.spout.vanilla.util.explosion.ExplosionModels;
import org.spout.vanilla.world.generator.normal.object.tree.BigTreeObject;
import org.spout.vanilla.world.generator.object.RandomizableObject;
import org.spout.vanilla.world.generator.object.VanillaObjects;
import org.spout.vanilla.world.lighting.LightingVerification;

public class TestCommands {
  private final VanillaPlugin plugin;

  public TestCommands(VanillaPlugin plugin) {
    this.plugin = plugin;
  }

  private Engine getEngine() {
    return plugin.getEngine();
  }

  @CommandDescription (aliases = {"effect", "fx"}, usage = "<type> <duration> [amp]", desc = "Applies an effect.")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void effect(CommandSource source, CommandArguments args) throws CommandException {
    Player player = args.checkPlayer(source);
    EntityEffectType type = args.popEnumValue("type", EntityEffectType.class);
    float duration = (float) args.popDouble("duration");
    int amp = args.popInteger("amp", 2);
    args.assertCompletelyParsed();

    player.add(Effects.class).add(new EntityEffect(type, amp, duration));
    player.sendMessage(ChatStyle.GREEN + "Applied effect '" + type + "' with amplitude '" + amp + "' for '" + duration + "' seconds.");
  }

  @CommandDescription (aliases = {"testscoreboard", "tsb"}, desc = "Not to be confused with '/scoreboard'")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void scoreboard(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    String name = player.getName();
    player.sendMessage(ChatStyle.GREEN + "Displaying scoreboard...");

    Scoreboard scoreboard = player.add(Scoreboard.class);
    scoreboard.createObjective("test_obj_1")
        .setDisplayName(ChatStyle.GREEN + "Test Objective 1")
        .setScore(name, 9001)
        .setCriteria(Objective.CRITERIA_HEALTH)
        .setSlot(ObjectiveSlot.SIDEBAR);

    scoreboard.createObjective("test_obj_2")
        .setDisplayName(ChatStyle.DARK_AQUA + "Test Objective 2")
        .setScore(name, 0)
        .setCriteria(Objective.CRITERIA_TOTAL_KILL_COUNT)
        .setSlot(ObjectiveSlot.LIST);
  }

  @CommandDescription (aliases = {"testteams", "tt"}, desc = "Tests teams functionality.")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void teams(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    String name = player.getName();
    player.sendMessage("Creating team...");

    Scoreboard scoreboard = player.get(Scoreboard.class);
    if (scoreboard == null) {
      throw new CommandException("You do not have an active scoreboard.");
    }

    Team t = scoreboard.createTeam("spoutdev");
    t.setDisplayName(ChatStyle.DARK_AQUA + "Spout", false);
    t.setPrefix(ChatStyle.GREEN.toString(), true);
    t.addPlayerName(name);
  }

  @CommandDescription (aliases = "chunklight", usage = "", desc = "Tests lighting in current chunk")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void chunkLight(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    Chunk c = player.getChunk();
    if (c == null) {
      throw new CommandException("You are somenow in a null chunk. This is probably bad.");
    }
    LightingVerification.checkChunk(c, false);
  }

  @CommandDescription (aliases = "alllight", usage = "", desc = "Tests lighting in all loaded chunks in the current world")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void allLight(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    LightingVerification.checkAll(player.getWorld(), true);
  }

  @CommandDescription (aliases = "checkheight", usage = "", desc = "Finds surface height of current column")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void targetHeight(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    Point pos = player.getPhysics().getPosition();

    int height = pos.getWorld().getSurfaceHeight(pos.getBlockX(), pos.getBlockZ());

    player.sendMessage("You are at " + pos.getBlockX() + ", " + pos.getBlockY() + ", " + pos.getBlockZ());
    player.sendMessage("Surface Height " + height + " " + (pos.getBlockY() - height) + " blocks below");
  }

  @CommandDescription (aliases = "getblock", usage = "<world> <x> <y> <z>", desc = "Finds block at the given coords")
  @Permissible ("vanilla.command.debug")
  public void getBlock(CommandSource source, CommandArguments args) throws CommandException {
    Point p = args.popPoint("loc", source);
    args.assertCompletelyParsed();

    Chunk c = p.getChunk(LoadOption.NO_LOAD);
    if (c == null) {
      throw new CommandException("Chunk not loaded");
    }
    int blockState = c.getBlockFullState(p.getBlockX(), p.getBlockY(), p.getBlockZ());
    BlockMaterial m = BlockMaterial.get(blockState);
    source.sendMessage("Material at " + p.getBlockX() + ", " + p.getBlockY() + ", " + p.getBlockZ() + " is " + m.getClass().getSimpleName());
  }

  @CommandDescription (aliases = "growtree", usage = "", desc = "grows a tree at the current location")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void growTree(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    Point pos = player.getPhysics().getPosition();

    BigTreeObject tree = new BigTreeObject();
    tree.placeObject(pos.getWorld(), pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
    player.getPhysics().setPosition(pos.add(new Vector3f(0, 50, 0)));
  }

  // TODO - There needs to be a method that guarantees unique data values on a per-server basis
  private int mapId = 1;

  @CommandDescription (aliases = "map", usage = "", desc = "Creates a map")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void map(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    ItemStack i = new ItemStack(VanillaMaterials.MAP, ++mapId, 1);
    player.get(PlayerInventory.class).add(i);
  }

  @CommandDescription (aliases = "mapdraw", usage = "<bx> <by> <tx> <ty> <col>", desc = "Draws a rectangle on the current map.  The top nibble for col is the colour and the bottom nibble is the brightness")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void mapDraw(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    PlayerInventory inventory = player.get(PlayerInventory.class);
    if (inventory == null) {
      throw new CommandException("Player has no inventory.");
    }
    ItemStack i = inventory.getQuickbar().getSelectedSlot().get();
    if (i == null || !(i.getMaterial() instanceof Map)) {
      throw new CommandException("Held item is not a map");
    }
    Map m = (Map) i.getMaterial();
    int bx = args.popInteger("bx");
    int by = args.popInteger("by");
    int tx = args.popInteger("tx");
    int ty = args.popInteger("ty");
    int col = args.popInteger("col");
    args.assertCompletelyParsed();

    if (bx < 0 || bx >= m.getWidth()) {
      throw new CommandException("bx component is out of range");
    }
    if (by < 0 || by >= m.getHeight()) {
      throw new CommandException("by component is out of range");
    }
    if (tx < 0 || tx >= m.getWidth()) {
      throw new CommandException("tx component is out of range");
    }
    if (ty < 0 || ty >= m.getHeight()) {
      throw new CommandException("ty component is out of range");
    }
    if (bx > tx) {
      throw new CommandException("bx cannot be greater than tx");
    }
    if (by > ty) {
      throw new CommandException("by cannot be greater than ty");
    }
    for (ProtocolEvent e : m.drawRectangle(i, bx, by, tx, ty, col)) {
      player.getNetwork().callProtocolEvent(e);
    }
  }

  @CommandDescription (aliases = "mapflood", usage = "<col>", desc = "Floods the current map with the given color")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void mapFlood(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    PlayerInventory inventory = player.get(PlayerInventory.class);
    if (inventory == null) {
      throw new CommandException("Player has no inventory.");
    }
    ItemStack i = inventory.getQuickbar().getSelectedSlot().get();
    if (i == null || !(i.getMaterial() instanceof Map)) {
      throw new CommandException("Held item is not a map");
    }
    Map m = (Map) i.getMaterial();
    int col = args.popInteger("col");
    for (ProtocolEvent e : m.flood(i, col)) {
      player.getNetwork().callProtocolEvent(e);
    }
  }

  @CommandDescription (aliases = "respawn", usage = "", desc = "Forces the client to respawn")
  @Permissible ("vanilla.command.debug")
  @Platforms (Platform.SERVER)
  @Filter (PlayerFilter.class)
  public void respawn(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    player.getNetwork().forceRespawn();
  }

  @CommandDescription (aliases = "sun", usage = "<x> <y> <z>", desc = "Sets the sun direction.")
  @Permissible ("vanilla.command.debug")
  public void setSunDirection(CommandSource source, CommandArguments args) throws CommandException {
    Vector3f dir = args.popVector3("dir", null);
    args.assertCompletelyParsed();
    LightRenderEffect.setSun(dir);
    SkyRenderEffect.setSun(dir);
  }

  @CommandDescription (aliases = "findframe", usage = "<radius>", desc = "Find a nether portal frame.")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void findFrame(Player player, CommandArguments args) throws CommandException {
    final int radius = args.popInteger("radius");
    args.assertCompletelyParsed();

    if (VanillaObjects.NETHER_PORTAL.find(player.getPhysics().getPosition(), radius)) {
      player.sendMessage(ChatStyle.GREEN + "Found portal frame!");
    } else {
      player.sendMessage(ChatStyle.RED + "Portal frame not found.");
    }
  }

  @CommandDescription (aliases = "traceray", desc = "Set all blocks that cross your view to stone.")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void traceray(CommandSource source, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    Player player = (Player) source;

    BlockIterator blockIt;
    if (getEngine().getPlatform() != Platform.CLIENT) {
      blockIt = player.get(EntityHead.class).getBlockView();
    } else {
      blockIt = player.get(InteractComponent.class).getAlignedBlocks();
    }

    Block block;
    while (blockIt.hasNext()) {
      block = blockIt.next();
      if (block.getMaterial().isPlacementObstacle()) {
        break;
      }
      block.setMaterial(VanillaMaterials.STONE);
    }
  }

  @Permissible ("vanilla.command.debug")
  @CommandDescription (aliases = "resetpos", desc = "Resets players position")
  @Filter (PlayerFilter.class)
  public void resetPosition(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();
    player.getNetwork().callProtocolEvent(new EntityUpdateEvent(player, new Transform(player.getPhysics().getPosition(), player.getPhysics().getRotation(), Vector3f.ONE), EntityUpdateEvent.UpdateAction.TRANSFORM, player.getNetwork().getRepositionManager()), player);
  }

  @CommandDescription (aliases = "torch", desc = "Place a torch.")
  @Filter (PlayerFilter.class)
  @Permissible ("vanilla.command.debug")
  public void torch(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    BlockIterator blockIt = player.get(InteractComponent.class).getAlignedBlocks();
    Block block;
    while (blockIt.hasNext()) {
      block = blockIt.next();
      if (block.getMaterial().isPlacementObstacle()) {
        block.setMaterial(VanillaMaterials.TORCH);
        break;
      }
    }
  }

  @CommandDescription (aliases = "window", usage = "<type>", desc = "Open a window.")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void window(Player player, CommandArguments args) throws CommandException {
    WindowType type = args.popEnumValue("type", WindowType.class);
    args.assertCompletelyParsed();

    switch (type) {
      case CHEST:
        player.get(WindowHolder.class).openWindow(new ChestWindow(player, new Chest()));
        break;
      case CRAFTING_TABLE:
        player.get(WindowHolder.class).openWindow(new CraftingTableWindow(player));
        break;
      case FURNACE:
        player.get(WindowHolder.class).openWindow(new FurnaceWindow(player, null, new FurnaceInventory()));
        break;
      case DISPENSER:
        player.get(WindowHolder.class).openWindow(new DispenserWindow(player, new DispenserInventory()));
        break;
      case ENCHANTMENT_TABLE:
        player.get(WindowHolder.class).openWindow(new EnchantmentTableWindow(player, null, new EnchantmentTableInventory()));
        break;
      case BREWING_STAND:
        player.get(WindowHolder.class).openWindow(new BrewingStandWindow(player, null, new BrewingStandInventory()));
        break;
      case VILLAGER:
        player.get(WindowHolder.class).openWindow(new VillagerWindow(player, new VillagerInventory()));
        break;
      default:
        throw new CommandException("Window not supported.");
    }
  }

  @CommandDescription (aliases = "damage", usage = "<amount>", desc = "Damage yourself")
  @Filter (PlayerFilter.class)
  @Permissible ("vanilla.command.debug")
  public void damage(Player player, CommandArguments args) throws CommandException {
    final int amount = args.popInteger("amount");
    args.assertCompletelyParsed();
    player.get(Health.class).damage(amount);
  }

  @CommandDescription (aliases = "hunger", usage = "<amount> <hungry>", desc = "Modify your hunger")
  @Filter (PlayerFilter.class)
  @Permissible ("vanilla.command.debug")
  public void hunger(Player player, CommandArguments args) throws CommandException {
    final int amount = args.popInteger("amount");
    final boolean hungry = args.popBoolean("hungry");
    args.assertCompletelyParsed();

    Hunger hunger = player.get(Hunger.class);
    hunger.setHunger(amount);
    hunger.setPoisoned(hungry);
  }

  @CommandDescription (aliases = {"explode"}, usage = "<explode>", desc = "Create an explosion")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void explode(Player player, CommandArguments args) throws CommandException {
    args.assertCompletelyParsed();

    Point position = player.getPhysics().getPosition();
    ExplosionModels.SPHERICAL.execute(position, 4.0f);
  }

  @CommandDescription (aliases = {"object", "obj"}, usage = "[-f] <object>", flags = {@Flag (aliases = {"force", "f"})},
      desc = "Spawn a WorldGeneratorObject at your location. Use -f to ignore canPlace check")
  @Filter (PlayerFilter.class)
  @Permissible ("vanilla.command.debug")
  public void generateObject(Player player, CommandArguments args) throws CommandException {
    final WorldGeneratorObject object = VanillaObjects.byName(args.currentArgument("object"));
    if (object == null) {
      throw args.failure("object", "Unknown object!", false);
    } else {
      args.success("object", object);
    }
    args.assertCompletelyParsed();

    final Point loc = player.getPhysics().getPosition();
    final World world = loc.getWorld();
    final int x = loc.getBlockX();
    final int y = loc.getBlockY();
    final int z = loc.getBlockZ();
    final boolean force = args.has("force");
    if (!object.canPlaceObject(world, x, y, z)) {
      player.sendMessage("Couldn't place the object.");
      if (!force) {
        return;
      }
      player.sendMessage("Forcing placement.");
    }
    object.placeObject(world, x, y, z);
    if (object instanceof RandomizableObject) {
      ((RandomizableObject) object).randomize();
    }
  }

  @CommandDescription (aliases = {"killall", "ka"}, desc = "Kill all non-player or world entities within a world")
  @Permissible ("vanilla.command.debug")
  public void killall(CommandSource source, CommandArguments args) throws CommandException {
    World world = args.popWorld("world", source);
    args.assertCompletelyParsed();

    List<Entity> entities = world.getAll();
    int count = 0;
    for (Entity entity : entities) {
      if (entity instanceof Player || (entity.get(VanillaEntityComponent.class) == null)) {
        continue;
      }
      count++;
      /*VanillaEntityComponent comp = entity.get(VanillaEntityComponent.class); // This has the potential to be REALLY spammy!
      if (comp instanceof Item) {
        Item item = (Item) comp;
        ItemStack stack = item.getItemStack();
        getEngine().getLogger().info("Removing item (" + stack + ") at " + entity.getPhysics().getTransform().getPosition().toBlockString());
      } else {
        getEngine().getLogger().info("Killing " + comp.getClass().getSimpleName() + " at " + entity.getPhysics().getTransform().getPosition().toBlockString());
      }*/
      entity.remove();
    }
    if (count > 0) {
      if (count == 1) {
        args.logAndNotify(plugin, source, "1 entity has been killed by " + source.getName() + ".");
      } else {
        args.logAndNotify(plugin, source, count + " entities have been killed by " + source.getName() + ".");
      }
    } else {
      source.sendMessage("No valid entities found to kill");
    }
  }

  @CommandDescription (aliases = "debug", usage = "<resend|resendall|look|packets)", desc = "Debug commands")
  @Permissible ("vanilla.command.debug")
  public void debug(CommandSource source, CommandArguments args) throws CommandException {
    String action = args.popString("action");
    Player player = args.popPlayerOrMe("player", source);
    args.assertCompletelyParsed();

    if (action.contains("look")) {
      Quaternionf rotation = player.getData().get(VanillaData.HEAD_ROTATION);
      Point startPosition = player.getPhysics().getPosition();
      Vector3f offset = rotation.getDirection().mul(0.1);
      for (int i = 0; i < 100; i++) {
        startPosition = startPosition.add(offset);
        GeneralEffects.NOTE_PARTICLE.playGlobal(startPosition);
      }
      final Vector3f axesAngles = rotation.getAxesAngleDeg();
      player.sendMessage("Yaw = " + axesAngles.getY());
      player.sendMessage("Pitch = " + axesAngles.getX());
    } else if (action.contains("packets")) {
      player.add(ForceMessages.class);
    } else {
      if (getEngine() instanceof Client) {
        throw new CommandException("You cannot resend chunks in client mode.");
      }
      if (action.contains("resendall")) {
        Set<Chunk> chunks = player.getNetwork().getActiveChunks();
        for (Chunk c : chunks) {
          player.getNetwork().callProtocolEvent(new ChunkSendEvent(c, true));
        }

        source.sendMessage("All chunks resent");
      } else if (action.contains("resend")) {
        player.getNetwork().callProtocolEvent(new ChunkSendEvent(player.getChunk(), true));
        source.sendMessage("Chunk resent");
      }
    }
  }

  @CommandDescription (aliases = "data", usage = "<key> <value>", desc = "Change Entity data value")
  @Permissible ("vanilla.command.data")
  public void data(CommandSource source, CommandArguments args) throws CommandException {
    String key = args.popString("key");
    String value = args.popRemainingStrings("value");
    Player player = args.popPlayerOrMe("player", source);
    args.assertCompletelyParsed();

    // Figure out what entity to affect
    // Note: this could be put in a method in the Vanilla human component instead
    // This version is rather inaccurate...
    double lastDistanceToEntity = 5.0;
    Point point = player.getPhysics().getPosition();
    Human human = player.get(Human.class);
    Vector3f direction;
    if (human == null) {
      direction = player.getPhysics().getRotation().getDirection();
    } else {
      direction = human.getHead().getLookingAt();
    }
    Entity nearest = null;
    for (double d = 0.0; d <= 50.0; d += 0.25) {
      Point pos = point.add(direction.mul(d));
      Entity near = point.getWorld().getNearestEntity(pos, player, (int) lastDistanceToEntity);
      if (near == null) {
        continue;
      }
      double distance = pos.distance(near.getPhysics().getPosition());
      if (distance < lastDistanceToEntity) {
        lastDistanceToEntity = distance;
        nearest = near;
        if (distance < 0.5) {
          break;
        }
      }
    }
    if (nearest == null) {
      player.sendMessage("Could not find a near Entity you are looking at.");
      return;
    }

    // Send entity information
    Descriptor desc = nearest.get(Descriptor.class);
    if (desc == null) {
      player.sendMessage("Selected Entity: Unknown");
    } else {
      player.sendMessage("Selected Entity: " + desc.getDescription());
    }

    Object currentValue = nearest.getData().get(key);
    if (value == null || value.isEmpty()) {
      if (nearest.getData().containsKey(key)) {
        player.sendMessage(key + " = " + currentValue);
      } else {
        player.sendMessage("No value is mapped to " + key + " for this Entity");
      }
      return;
    }

    // Figure out what type the key is using VanillaData
    Class<?> valueType = null;
    for (Field field : VanillaData.class.getDeclaredFields()) {
      if (!Modifier.isStatic(field.getModifiers())) {
        continue;
      }
      try {
        Object fieldValue = field.get(null);
        if (fieldValue instanceof DefaultedKey) {
          DefaultedKey<?> defKey = (DefaultedKey<?>) fieldValue;
          if (!defKey.getKeyString().equals(key)) {
            continue;
          }
          Object defValue = defKey.getDefaultValue();
          if (defValue != null) {
            // We found our type!
            valueType = defValue.getClass();
            break;
          }
        }
      } catch (Throwable t) {
        // Ignore any field access issues
      }
    }
    // Try using the current value in the datamap
    if (valueType == null) {
      if (currentValue == null) {
        player.sendMessage("Could not figure out the type of value stored by " + key);
        return;
      } else {
        valueType = currentValue.getClass();
      }
    }

    // Set the value in the datamap if possible
    try {
      Serializable newValue;
      if (Double.class.isAssignableFrom(valueType)) {
        newValue = Double.parseDouble(value);
      } else if (Float.class.isAssignableFrom(valueType)) {
        newValue = Float.parseFloat(value);
      } else if (Long.class.isAssignableFrom(valueType)) {
        newValue = Long.parseLong(value);
      } else if (Integer.class.isAssignableFrom(valueType)) {
        newValue = Integer.parseInt(value);
      } else if (Short.class.isAssignableFrom(valueType)) {
        newValue = Short.parseShort(value);
      } else if (Byte.class.isAssignableFrom(valueType)) {
        newValue = Byte.parseByte(value);
      } else if (String.class.isAssignableFrom(valueType)) {
        newValue = value;
      } else {
        player.sendMessage("No idea how to turn " + value + " into " + valueType.getSimpleName());
        return;
      }
      nearest.getData().put(key, newValue);
      player.sendMessage("Value of " + key + " set to " + newValue);
    } catch (Throwable t) {
      player.sendMessage("Error occurred while parsing value " + value);
      player.sendMessage(t.getMessage());
    }
  }

  @CommandDescription (aliases = "spawn", desc = "Spawns a living entity at your location")
  @Filter (PlayerFilter.class)
  public void spawn(Player player, CommandArguments args) throws CommandException {
    final String name = args.popString("name");

    Class<? extends Component> clazz;
    boolean child = false;
    //See if it is a living?
    try {
      clazz = CreatureType.valueOf(name.toUpperCase()).getComponentType();
      if (Ageable.class.isAssignableFrom(clazz) && args.flags().hasFlag("child")) {
        child = true;
      }
    } catch (Exception e1) {
      try {
        //Living failed? Try object
        clazz = ObjectType.valueOf(name.toUpperCase()).getComponentType();
      } catch (Exception e2) {
        throw new CommandException(name + " is neither a living or substance entity!");
      }
    }
    //if (!player.hasPermission("vanilla.command.spawn." + clazz.getName().toLowerCase())) {
    //  throw new CommandException("You do not have permission to spawn a(n) " + clazz.getSimpleName().toLowerCase());
    //}
    //TODO ServerEntityPrefab!
    //How about some client support?
    final Entity entity;
    if (getEngine() instanceof Client) {
      final EntityPrefab prefab = getEngine().getFileSystem().getResource("entity://Vanilla/entities/" + clazz.getSimpleName().toLowerCase() + "/" + clazz.getSimpleName().toLowerCase() + ".sep");
      entity = prefab.createEntity(player.getPhysics().getPosition());
    } else {
      entity = player.getWorld().createEntity(player.getPhysics().getPosition(), clazz);
    }
    //Optional param was provided (ie the block material for a falling block).
    if (args.length() == 2) {
      //Now we know its either a living or substance. Lets figure out which.
      if (Living.class.isAssignableFrom(clazz)) {
        final Living living = entity.get(Living.class);
        if (name.equalsIgnoreCase("human")) {
          ((Human) living).setName(args.popString("disp_name"));
        }
      } else if (Substance.class.isAssignableFrom(clazz)) {
        final Substance substance = entity.get(Substance.class);
        switch (ObjectType.valueOf(name.toUpperCase())) {
          case ITEM:
            Material item = VanillaArgumentTypes.popMaterial("item", args);
            ((Item) substance).setItemStack(new ItemStack(item, 1));
            break;
          case FALLING_OBJECT:
            Material block = VanillaArgumentTypes.popMaterial("block", args);
            if (!(block instanceof BlockMaterial)) {
              throw new CommandException("Material " + block.getDisplayName() + " is not a block!");
            }
            ((FallingBlock) substance).setMaterial((BlockMaterial) block);
            break;
        }
      }
    }
    args.assertCompletelyParsed();
    player.getWorld().spawnEntity(entity);
    if (child) {
      entity.get(Ageable.class).setAge(Ageable.MIN_AGE);
    }
  }

  @CommandDescription (aliases = "fire", usage = "<time> [hurt]", desc = "Set you on fire")
  @Permissible ("vanilla.command.debug")
  @Filter (PlayerFilter.class)
  public void fire(Player player, CommandArguments args) throws CommandException {
    final float time = args.popFloat("time");
    final boolean hurt = args.popBoolean("hurt", false);
    args.assertCompletelyParsed();

    Burn fire = player.add(Burn.class);
    fire.setOnFire(time, hurt);
  }
}
TOP

Related Classes of org.spout.vanilla.command.TestCommands

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.