/*
* 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.flowpowered.math.vector.Vector3d;
import com.sk89q.craftbook.core.util.CraftBookException;
import com.sk89q.craftbook.core.util.RegexUtil;
import com.sk89q.craftbook.sponge.CraftBookPlugin;
import com.sk89q.craftbook.sponge.mechanics.ics.ICSocket;
import org.apache.commons.lang3.StringUtils;
import org.spongepowered.api.block.tileentity.Sign;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
public class ParsingUtil {
public static Vector3d parseUnsafeBlockLocation(String line) throws NumberFormatException, ArrayIndexOutOfBoundsException {
line = StringUtils.replace(StringUtils.replace(StringUtils.replace(line, "!", ""), "^", ""), "&", "");
double offsetX = 0, offsetY, offsetZ = 0;
if (line.contains("="))
line = RegexUtil.EQUALS_PATTERN.split(line)[1];
String[] split = RegexUtil.COLON_PATTERN.split(line);
if (split.length > 1) {
offsetX = Double.parseDouble(split[0]);
offsetY = Double.parseDouble(split[1]);
offsetZ = Double.parseDouble(split[2]);
} else
offsetY = Double.parseDouble(line);
return new Vector3d(offsetX, offsetY, offsetZ);
}
public static Location<World> parseBlockLocation(Sign sign, String line, LocationCheckType relative) {
Location<World> target = SignUtil.getBackBlock(sign.getLocation());
if (line.contains("!"))
relative = LocationCheckType.getTypeFromChar('!');
else if (line.contains("^"))
relative = LocationCheckType.getTypeFromChar('^');
else if (line.contains("&"))
relative = LocationCheckType.getTypeFromChar('&');
Vector3d offsets = new Vector3d(0,0,0);
try {
offsets = parseUnsafeBlockLocation(line);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) {
}
if(offsets.getFloorX() == 0 && offsets.getFloorY() == 0 && offsets.getFloorZ() == 0)
return target;
if (relative == LocationCheckType.RELATIVE)
target = LocationUtil.getRelativeOffset(sign.getLocation(), offsets.getFloorX(), offsets.getFloorY(), offsets.getFloorZ());
else if (relative == LocationCheckType.OFFSET)
target = LocationUtil.getOffset(target, offsets.getFloorX(), offsets.getFloorY(), offsets.getFloorZ());
else if (relative == LocationCheckType.ABSOLUTE)
target = target.getExtent().getLocation(offsets.getX(), offsets.getY(), offsets.getZ());
return target;
}
public static Location<World> parseBlockLocation(Sign sign, int lPos, LocationCheckType relative) {
return parseBlockLocation(sign, SignUtil.getTextRaw(sign, lPos), relative);
}
public static Location<World> parseBlockLocation(Sign sign, int lPos) {
return parseBlockLocation(sign, lPos, LocationCheckType.OFFSET);
}
public static Location<World> parseBlockLocation(Sign sign) {
return parseBlockLocation(sign, 2, LocationCheckType.OFFSET);
}
public static void verifySignSyntax(Sign sign) throws CraftBookException {
verifySignLocationSyntax(sign, 2);
}
public static void verifySignLocationSyntax(Sign sign, int i) throws CraftBookException {
try {
String line = SignUtil.getTextRaw(sign, i);
String[] strings;
line = StringUtils.replace(StringUtils.replace(StringUtils.replace(line, "!", ""), "^", ""), "&", "");
if (line.contains("=")) {
String[] split = RegexUtil.EQUALS_PATTERN.split(line, 2);
if(RegexUtil.COMMA_PATTERN.split(split[0]).length > 1) {
String[] rads = RegexUtil.COMMA_PATTERN.split(split[0]);
Double.parseDouble(rads[0]);
Double.parseDouble(rads[1]);
Double.parseDouble(rads[2]);
} else
Double.parseDouble(split[0]);
strings = RegexUtil.COLON_PATTERN.split(split[1], 3);
} else
strings = RegexUtil.COLON_PATTERN.split(line);
if (strings.length > 1) {
Double.parseDouble(strings[1]);
Double.parseDouble(strings[2]);
}
Double.parseDouble(strings[0]);
} catch (Exception e) {
throw new CraftBookException("Wrong syntax! Needs to be: radius=x:y:z or radius=y or y");
}
}
// Radius
public static Vector3d parseRadius(Sign sign) {
return parseRadius(sign, 2);
}
public static Vector3d parseRadius(Sign sign, int lPos) {
return parseRadius(SignUtil.getTextRaw(sign, lPos));
}
public static Vector3d parseRadius(String line) {
Vector3d radius = new Vector3d(10,10,10);
try {
radius = parseUnsafeRadius(line);
} catch (NumberFormatException ignored) {
}
return radius;
}
public static Vector3d parseUnsafeRadius(String line) throws NumberFormatException {
String[] radians = RegexUtil.COMMA_PATTERN.split(RegexUtil.EQUALS_PATTERN.split(line, 2)[0]);
if(radians.length > 1) {
double x = verifyRadius(Double.parseDouble(radians[0]), CraftBookPlugin.spongeInst().moduleController.getModule(ICSocket.class).get().getModule().get().maxRadius.getValue());
double y = verifyRadius(Double.parseDouble(radians[1]), CraftBookPlugin.spongeInst().moduleController.getModule(ICSocket.class).get().getModule().get().maxRadius.getValue());
double z = verifyRadius(Double.parseDouble(radians[2]), CraftBookPlugin.spongeInst().moduleController.getModule(ICSocket.class).get().getModule().get().maxRadius.getValue());
return new Vector3d(x,y,z);
}
else {
double r = Double.parseDouble(radians[0]);
r = verifyRadius(r, CraftBookPlugin.spongeInst().moduleController.getModule(ICSocket.class).get().getModule().get().maxRadius.getValue());
return new Vector3d(r,r,r);
}
}
/**
* Verify that a radius is within the maximum.
*
* @param radius The radius to check
* @param maxradius The maximum possible radius
* @return The new fixed radius.
*/
public static double verifyRadius(double radius, double maxradius) {
return Math.max(0, Math.min(maxradius, radius));
}
public enum LocationCheckType {
RELATIVE('^'),
OFFSET('&'),
ABSOLUTE('!');
char c;
LocationCheckType(char c) {
this.c = c;
}
public static LocationCheckType getTypeFromChar(char c) {
for(LocationCheckType t : values())
if(t.c == c)
return t;
return RELATIVE;
}
public static LocationCheckType getTypeFromName(String name) {
if(name.length() == 1)
return getTypeFromChar(name.charAt(0));
for(LocationCheckType t : values())
if(t.name().equalsIgnoreCase(name))
return t;
return RELATIVE;
}
}
}