/*
* CraftBook Copyright (C) 2010-2017 sk89q <http://www.sk89q.com>
* CraftBook Copyright (C) 2011-2017 me4502 <http://www.me4502.com>
* CraftBook Copyright (C) Contributors
*
* 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.sponge.util;
import com.google.common.collect.Lists;
import com.sk89q.craftbook.core.CraftBookAPI;
import com.sk89q.craftbook.sponge.mechanics.variable.Variables;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.block.tileentity.Sign;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.data.manipulator.mutable.tileentity.SignData;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.util.Direction;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import java.util.List;
import java.util.Optional;
/**
* Convenience methods for dealing with some sign block data.
*/
public final class SignUtil {
/**
* Gets whether or not the block at this location is a sign.
*
* @param block The location to check
* @return If it is a sign
*/
public static boolean isSign(Location<World> block) {
if (isSign(block.getBlock())) {
if (!block.getTileEntity().isPresent()) {
CraftBookAPI.inst().getLogger().warn("Corrupted tile entity (Sign) at " + block.getBlockPosition() + " in world " + block.getExtent().getName());
return false;
}
return true;
}
return false;
}
/**
* If this blockstate is a sign.
*
* @param block The blockstate to check
* @return If it is a sign
*/
public static boolean isSign(BlockState block) {
return block.getType() == BlockTypes.STANDING_SIGN || block.getType() == BlockTypes.WALL_SIGN;
}
public static List<Location<World>> getAttachedSigns(Location<World> block) {
List<Location<World>> attachedSigns = Lists.newArrayList();
for (Direction directFace : BlockUtil.getDirectFaces()) {
if (SignUtil.isSign(block.getRelative(directFace))) {
attachedSigns.add(block.getRelative(directFace));
}
}
return attachedSigns;
}
/**
* @param sign treated as sign post if it is such, or else assumed to be a wall sign (i.e.,
* if you ask about a stone block, it's considered a wall
* sign).
* @return the direction a player would be facing when reading the sign; i.e. the face that is actually the back
* side of the sign.
*/
public static Direction getFacing(Location<World> sign) {
return getBack(sign);
}
/**
* @param sign treated as sign post if it is such, or else assumed to be a wall sign (i.e.,
* if you ask about a stone block, it's considered a wall
* sign).
* @return the side of the sign containing the text (in other words, when a player places a new sign,
* while facing north, this will return south).
*/
public static Direction getFront(Location<World> sign) {
Optional<Direction> data = sign.get(Keys.DIRECTION);
return data.orElse(Direction.NONE);
}
public static Location<World> getFrontBlock(Location<World> sign) {
return sign.getRelative(getFront(sign));
}
/**
* @param sign treated as sign post if it is such, or else assumed to be a wall sign (i.e.,
* if you ask about a stone block, it's considered a wall
* sign).
* @return the blank side of the sign opposite the text. In the case of a wall sign,
* the block in this direction is the block to which the sign is
* attached. This is also the direction a player would be facing when reading the sign; see {@link #getFront(Location)}.
*/
public static Direction getBack(Location<World> sign) {
Direction front = getFront(sign);
if (front == null) return Direction.NONE;
return front.getOpposite();
}
public static Location<World> getBackBlock(Location<World> sign) {
return sign.getRelative(getBack(sign));
}
public static Location<World> getNextSign(Location<World> sign, String criterea, int searchRadius) {
Location<World> otherBlock = sign;
Direction way = getBack(sign);
boolean found = false;
for (int i = 0; i < searchRadius; i++) {
if (isSign(otherBlock.getRelative(way))) {
otherBlock = otherBlock.getRelative(way);
if(getTextRaw((Sign) otherBlock.getTileEntity().get(), 1).equalsIgnoreCase(criterea)) {
found = true;
break;
}
} else otherBlock = otherBlock.getRelative(way);
}
if (!found) return null;
return otherBlock;
}
/**
* @param sign treated as sign post if it is such, or else assumed to be a wall sign (i.e.,
* if you ask about a stone block, it's considered a wall
* sign).
* @return the cardinal or ordinal direction to a player's left as they face the sign to read it; if the sign is
* oriented in a further direction,
* the result is rounded to the nearest ordinal direction.
*/
public static Direction getRight(Location<World> sign) {
Direction front = getFront(sign);
if (front == null) return Direction.NONE;
return getClockWise(front);
}
public static Location<World> getLeftBlock(Location<World> sign) {
return sign.getRelative(getLeft(sign));
}
/**
* @param sign treated as sign post if it is such, or else assumed to be a wall sign (i.e.,
* if you ask about a stone block, it's considered a wall
* sign).
* @return the cardinal or ordinal direction to a player's right they face the sign to read it; if the sign is
* oriented in a further direction, the
* result is rounded to the nearest ordinal direction.
*/
public static Direction getLeft(Location<World> sign) {
Direction front = getFront(sign);
if (front == null) return Direction.NONE;
return getCounterClockWise(front);
}
public static Location<World> getRightBlock(Location<World> sign) {
return sign.getRelative(getRight(sign));
}
/**
* @param face Start from direction
* @return clockwise direction
*/
public static Direction getClockWise(Direction face) {
switch (face) {
case NORTH:
return Direction.EAST;
case EAST:
return Direction.SOUTH;
case SOUTH:
return Direction.WEST;
case WEST:
return Direction.NORTH;
default:
return face;
}
}
/**
* @param face Start from direction
* @return clockwise direction
*/
public static Direction getCounterClockWise(Direction face) {
switch (face) {
case NORTH:
return Direction.WEST;
case EAST:
return Direction.NORTH;
case SOUTH:
return Direction.EAST;
case WEST:
return Direction.SOUTH;
default:
return face;
}
}
/* From this point on - replacements for ChangedSign in CB 3.x */
public static String getTextRaw(Sign sign, int line) {
return getTextRaw(sign.get(SignData.class).get(), line);
}
public static String getTextRaw(SignData sign, int line) {
return getTextRaw(getText(sign, line));
}
public static String getTextRaw(Text text) {
String raw = text.toPlain();
if(Variables.instance != null)
raw = Variables.instance.parseVariables(raw, null);
return raw;
}
public static Text getText(SignData sign, int line) {
return sign.lines().get(line);
}
}