package com.sk89q.worldedit.command; import com.boydti.fawe.object.mask.AdjacentAnyMask; import com.boydti.fawe.object.mask.AdjacentMask; import com.boydti.fawe.object.mask.AngleMask; import com.boydti.fawe.object.mask.BiomeMask; import com.boydti.fawe.object.mask.BlockLightMask; import com.boydti.fawe.object.mask.BrightnessMask; import com.boydti.fawe.object.mask.DataMask; import com.boydti.fawe.object.mask.ExtremaMask; import com.boydti.fawe.object.mask.IdDataMask; import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.mask.LightMask; import com.boydti.fawe.object.mask.OpacityMask; import com.boydti.fawe.object.mask.ROCAngleMask; import com.boydti.fawe.object.mask.RadiusMask; import com.boydti.fawe.object.mask.RandomMask; import com.boydti.fawe.object.mask.SimplexMask; import com.boydti.fawe.object.mask.SkyLightMask; import com.boydti.fawe.object.mask.SurfaceMask; import com.boydti.fawe.object.mask.WallMask; import com.boydti.fawe.object.mask.XAxisMask; import com.boydti.fawe.object.mask.YAxisMask; import com.boydti.fawe.object.mask.ZAxisMask; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.BlockMaskBuilder; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.ExpressionMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.mask.MaskUnion; import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.OffsetMask; import com.sk89q.worldedit.function.mask.RegionMask; import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionEnvironment; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.session.request.RequestSelection; import com.sk89q.worldedit.world.biome.BiomeType; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Switch; //@Command(aliases = {"masks"}, // desc = "Help for the various masks. [More Info](https://git.io/v9r4K)", // descFooter = "Masks determine if a block can be placed\n" + // " - Use [brackets] for arguments\n" + // " - Use , to OR multiple\n" + // " - Use & to AND multiple\n" + // "e.g. >[stone,dirt],#light[0][5],$jungle\n" + // "More Info: https://git.io/v9r4K" //) @CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class MaskCommands { private final WorldEdit worldEdit; public MaskCommands(WorldEdit worldEdit) { this.worldEdit = worldEdit; } @Command( name = "#simplex", desc = "Use simplex noise as the mask" ) public Mask simplex(@Arg(desc = "double scale") double scale, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { scale = 1d / Math.max(1, scale); minInt = (minInt - 50) / 50; maxInt = (maxInt - 50) / 50; return new SimplexMask(scale, minInt, maxInt); } @Command( name = "#light", desc = "Restrict to specific light levels" ) public Mask light(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { return new LightMask(extent, (int) minInt, (int) maxInt); } @Command( name = "#false", desc = "Always false" ) public Mask falseMask(Extent extent) { return Masks.alwaysFalse(); } @Command( name = "#true", desc = "Always true" ) public Mask trueMask(Extent extent) { return Masks.alwaysTrue(); } @Command( name = "#skylight", desc = "Restrict to specific sky light levels" ) public Mask skylight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { return new SkyLightMask(extent, (int) minInt, (int) maxInt); } @Command( name = "#blocklight", aliases = {"#emittedlight"}, desc = "Restrict to specific block light levels" ) public Mask blocklight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { return new BlockLightMask(extent, (int) minInt, (int) maxInt); } @Command( name = "#opacity", desc = "Restrict to specific opacity levels" ) public Mask opacity(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { return new OpacityMask(extent, (int) minInt, (int) maxInt); } @Command( name = "#brightness", desc = "Restrict to specific block brightness" ) public Mask brightness(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) { return new BrightnessMask(extent, (int) minInt, (int) maxInt); } @Command( name = "#offset", desc = "Offset a mask" ) public Mask offset(@Arg(desc = "double x") double x, @Arg(desc = "double y") double y, @Arg(desc = "double z") double z, @Arg(desc = "Mask") Mask mask) { return new OffsetMask(mask, BlockVector3.at(x, y, z)); } @Command( name = "#haslight", desc = "Restricts to blocks with light (sky or emitted)" ) public Mask haslight(Extent extent) { return new LightMask(extent, 1, Integer.MAX_VALUE); } @Command( name = "#nolight", desc = "Restrict to blocks without light (sky or emitted)" ) public Mask nolight(Extent extent) { return new LightMask(extent, 0, 0); } @Command( name = "#existing", desc = "If there is a non air block" ) public Mask existing(Extent extent) { return new ExistingBlockMask(extent); } @Command( name = "#solid", desc = "If there is a solid block" ) public Mask solid(Extent extent) { return new SolidBlockMask(extent); } @Command( name = "#liquid", desc = "If there is a solid block" ) public Mask liquid(Extent extent) { return new BlockMaskBuilder().addAll(b -> b.getMaterial().isLiquid()).build(extent); } @Command( name = "#dregion", aliases = {"#dselection", "#dsel"}, desc = "inside the player's selection" ) public Mask dregion() { return new RegionMask(new RequestSelection()); } @Command( name = "#region", aliases = {"#selection", "#sel"}, desc = "inside the provided selection" ) public Mask selection(Player player, LocalSession session) throws IncompleteRegionException { return new RegionMask(session.getSelection(player.getWorld()).clone()); } @Command( name = "#xaxis", desc = "Restrict to initial x axis" ) public Mask xaxis() { return new XAxisMask(); } @Command( name = "#yaxis", desc = "Restrict to initial y axis" ) public Mask yaxis() { return new YAxisMask(); } @Command( name = "#zaxis", desc = "Restrict to initial z axis" ) public Mask zaxis() { return new ZAxisMask(); } @Command( name = "#id", desc = "Restrict to initial id" ) public Mask id(Extent extent) { return new IdMask(extent); } @Command( name = "#data", desc = "Restrict to initial data" ) public Mask data(Extent extent) { return new DataMask(extent); } @Command( name = "#iddata", desc = "Restrict to initial block id and data" ) public Mask iddata(Extent extent) { return new IdDataMask(extent); } @Command( name = "#air", desc = "Restrict to types of air" ) public Mask air(Extent extent) { return new BlockMaskBuilder().addAll(b -> b.getMaterial().isAir()).build(extent); } @Command( name = "#wall", desc = "Restrict to walls (any block n,e,s,w of air)" ) public Mask wall(Extent extent) { Mask blockMask = air(extent); return new MaskUnion(new ExistingBlockMask(extent), new WallMask(blockMask, 1, 8)); } @Command( name = "#surface", desc = "Restrict to surfaces (any solid block touching air)" ) public Mask surface(Extent extent) { return new SurfaceMask(extent); } @Command( name = "\\", aliases = {"/", "#angle", "#\\", "#/"}, desc = "Restrict to specific terrain angle", descFooter = "Restrict to specific terrain angle\n" + "The -o flag will only overlay\n" + "Example: /[0d][45d]\n" + "Explanation: Allows any block where the adjacent block is between 0 and 45 degrees.\n" + "Example: /[3][20]\n" + "Explanation: Allows any block where the adjacent block is between 3 and 20 blocks below" ) public Mask angle(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "1") int distanceOpt) throws ExpressionException { double y1, y2; boolean override; if (maxStr.endsWith("d")) { double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); y1 = Math.tan(y1d * (Math.PI / 180)); y2 = Math.tan(y2d * (Math.PI / 180)); } else { y1 = Expression.compile(minStr).evaluate(); y2 = Expression.compile(maxStr).evaluate(); } return new AngleMask(extent, y1, y2, overlay, distanceOpt); } @Command( name = "(", aliases = {")", "#roc", "#(", "#)"}, desc = "Restrict to near specific terrain slope rate of change", descFooter = "Restrict to near specific terrain slope rate of change\n" + "The -o flag will only overlay\n" + "Example: ([0d][45d][5]\n" + "Explanation: Restrict near where the angle changes between 0-45 degrees within 5 blocks\n" + "Note: Use negatives for decreasing slope" ) public Mask roc(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "4") int distanceOpt) throws ExpressionException { double y1, y2; boolean override; if (maxStr.endsWith("d")) { double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); y1 = Math.tan(y1d * (Math.PI / 180)); y2 = Math.tan(y2d * (Math.PI / 180)); } else { y1 = Expression.compile(minStr).evaluate(); y2 = Expression.compile(maxStr).evaluate(); } return new ROCAngleMask(extent, y1, y2, overlay, distanceOpt); } @Command( name = "^", aliases = {"#extrema", "#^"}, desc = "Restrict to near specific terrain extrema", descFooter = "Restrict to near specific terrain extrema\n" + "The -o flag will only overlay\n" + "Example: ([0d][45d][5]\n" + "Explanation: Restrict to near 45 degrees of local maxima\n" + "Note: Use negatives for local minima" ) public Mask extrema(Extent extent, @Arg(name="min", desc = "min angle") String minStr, @Arg(name="max", desc = "max angle") String maxStr, @Switch(name = 'o', desc = "TODO") boolean overlay, @Arg(name = "distance", desc = "int", def = "4") int distanceOpt) throws ExpressionException { double y1, y2; boolean override; if (maxStr.endsWith("d")) { double y1d = Expression.compile(minStr.substring(0, minStr.length() - 1)).evaluate(); double y2d = Expression.compile(maxStr.substring(0, maxStr.length() - 1)).evaluate(); y1 = Math.tan(y1d * (Math.PI / 180)); y2 = Math.tan(y2d * (Math.PI / 180)); } else { y1 = Expression.compile(minStr).evaluate(); y2 = Expression.compile(maxStr).evaluate(); } return new ExtremaMask(extent, y1, y2, overlay, distanceOpt); } @Command( name = "{", aliases = {"#{"}, desc = "Restricts blocks to within a specific radius range of the initial block" ) public Mask radius(@Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) throws ExpressionException { return new RadiusMask((int) minInt, (int) maxInt); } @Command( name = "|", aliases = {"#|", "#side"}, desc = "sides with a specific number of other blocks" ) public Mask wall(@Arg(desc = "Mask") Mask mask, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) throws ExpressionException { return new WallMask(mask, (int) minInt, (int) maxInt); } @Command( name = "~", aliases = {"#~", "#adjacent"}, desc = "Adjacent to a specific number of other blocks" ) public Mask adjacent(@Arg(desc = "Mask") Mask mask, @Arg(name = "min", desc = "double", def = "-1") double min, @Arg(name = "max", desc = "double", def = "-1") double max) throws ExpressionException { if (min == -1 && max == -1) { min = 1; max = 8; } else if (max == -1) max = min; if (max >= 8 && min == 1) { return new AdjacentAnyMask(mask); } return new AdjacentMask(mask, (int) min, (int) max); } @Command( name = "<", aliases = {"#<", "#below"}, desc = "below a specific block" ) public Mask below(@Arg(desc = "Mask") Mask mask) throws ExpressionException { OffsetMask offsetMask = new OffsetMask(mask, BlockVector3.at(0, 1, 0)); return new MaskIntersection(offsetMask, Masks.negate(mask)); } @Command( name = ">", aliases = {"#>", "#above"}, desc = "above a specific block" ) public Mask above(@Arg(desc = "Mask") Mask mask) throws ExpressionException { OffsetMask offsetMask = new OffsetMask(mask, BlockVector3.at(0, -1, 0)); return new MaskIntersection(offsetMask, Masks.negate(mask)); } @Command( name = "$", aliases = {"#biome", "#$"}, desc = "in a specific biome", descFooter = "in a specific biome. For a list of biomes use //biomelist" ) public Mask biome(Extent extent, @Arg(desc = "BiomeType") BiomeType biome) throws ExpressionException { return new BiomeMask(extent, biome); } @Command( name = "%", aliases = {"#%", "#percent"}, desc = "percentage chance" ) public Mask random(@Arg(desc = "double chance") double chance) throws ExpressionException { chance = chance / 100; return new RandomMask(chance); } @Command( name = "=", aliases = {"#=", "#expression"}, desc = "expression mask" ) public Mask expression(Extent extent, @Arg(desc = "String expression") String input) throws ExpressionException { Expression exp = Expression.compile(input, "x", "y", "z"); ExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO); exp.setEnvironment(env); return new ExpressionMask(exp); } @Command( name = "!", aliases = {"#not", "#negate", "#!"}, desc = "Negate another mask" ) public Mask negate(@Arg(desc = "Mask") Mask mask) throws ExpressionException { return Masks.negate(mask); } }