mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-14 23:48:36 +00:00
Switch to Gradle. Use git log --follow for history.
This converts the project into a multi-module Gradle build. By default, Git does not show history past a rename, so use git log --follow to see further history.
This commit is contained in:
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A registry of known {@link BaseBlock}s. Provides methods to instantiate
|
||||
* new blocks from input.
|
||||
*
|
||||
* <p>Instances of this class can be taken from
|
||||
* {@link WorldEdit#getBlockFactory()}.</p>
|
||||
*/
|
||||
public class BlockFactory extends AbstractFactory<BaseBlock> {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance.
|
||||
*/
|
||||
public BlockFactory(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
|
||||
parsers.add(new DefaultBlockParser(worldEdit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of blocks from a comma-delimited list of blocks.
|
||||
*
|
||||
* @param input the input
|
||||
* @param context the context
|
||||
* @return a set of blocks
|
||||
* @throws InputParseException thrown in error with the input
|
||||
*/
|
||||
public Set<BaseBlock> parseFromListInput(String input, ParserContext context) throws InputParseException {
|
||||
Set<BaseBlock> blocks = new HashSet<BaseBlock>();
|
||||
for (String token : input.split(",")) {
|
||||
blocks.add(parseFromInput(token, context));
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
import com.sk89q.worldedit.blocks.metadata.MobType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* Parses block input strings.
|
||||
*/
|
||||
class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
|
||||
protected DefaultBlockParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
private static BaseBlock getBlockInHand(Actor actor) throws InputParseException {
|
||||
if (actor instanceof Player) {
|
||||
try {
|
||||
return ((Player) actor).getBlockInHand();
|
||||
} catch (NotABlockException e) {
|
||||
throw new InputParseException("You're not holding a block!");
|
||||
} catch (WorldEditException e) {
|
||||
throw new InputParseException("Unknown error occurred: " + e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
throw new InputParseException("The user is not a player!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
BlockType blockType;
|
||||
input = input.replace("_", " ");
|
||||
input = input.replace(";", "|");
|
||||
String[] blockAndExtraData = input.split("\\|");
|
||||
String[] typeAndData = blockAndExtraData[0].split(":", 2);
|
||||
String testID = typeAndData[0];
|
||||
|
||||
int blockId = -1;
|
||||
|
||||
int data = -1;
|
||||
|
||||
boolean parseDataValue = true;
|
||||
|
||||
if ("hand".equalsIgnoreCase(testID)) {
|
||||
// Get the block type from the item in the user's hand.
|
||||
final BaseBlock blockInHand = getBlockInHand(context.requireActor());
|
||||
if (blockInHand.getClass() != BaseBlock.class) {
|
||||
return blockInHand;
|
||||
}
|
||||
|
||||
blockId = blockInHand.getId();
|
||||
blockType = BlockType.fromID(blockId);
|
||||
data = blockInHand.getData();
|
||||
} else if ("pos1".equalsIgnoreCase(testID)) {
|
||||
// Get the block type from the "primary position"
|
||||
final World world = context.requireWorld();
|
||||
final BlockVector primaryPosition;
|
||||
try {
|
||||
primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition();
|
||||
} catch (IncompleteRegionException e) {
|
||||
throw new InputParseException("Your selection is not complete.");
|
||||
}
|
||||
final BaseBlock blockInHand = world.getBlock(primaryPosition);
|
||||
if (blockInHand.getClass() != BaseBlock.class) {
|
||||
return blockInHand;
|
||||
}
|
||||
|
||||
blockId = blockInHand.getId();
|
||||
blockType = BlockType.fromID(blockId);
|
||||
data = blockInHand.getData();
|
||||
} else {
|
||||
// Attempt to parse the item ID or otherwise resolve an item/block
|
||||
// name to its numeric ID
|
||||
try {
|
||||
blockId = Integer.parseInt(testID);
|
||||
blockType = BlockType.fromID(blockId);
|
||||
} catch (NumberFormatException e) {
|
||||
blockType = BlockType.lookup(testID);
|
||||
if (blockType == null) {
|
||||
int t = worldEdit.getServer().resolveItem(testID);
|
||||
if (t > 0) {
|
||||
blockType = BlockType.fromID(t); // Could be null
|
||||
blockId = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blockId == -1 && blockType == null) {
|
||||
// Maybe it's a cloth
|
||||
ClothColor col = ClothColor.lookup(testID);
|
||||
if (col == null) {
|
||||
throw new NoMatchException("Unknown wool color '" + input + "'");
|
||||
}
|
||||
|
||||
blockType = BlockType.CLOTH;
|
||||
data = col.getID();
|
||||
|
||||
// Prevent overriding the data value
|
||||
parseDataValue = false;
|
||||
}
|
||||
|
||||
// Read block ID
|
||||
if (blockId == -1) {
|
||||
blockId = blockType.getID();
|
||||
}
|
||||
|
||||
if (!context.requireWorld().isValidBlockType(blockId)) {
|
||||
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.isPreferringWildcard() && data == -1) {
|
||||
// No wildcards allowed => eliminate them.
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if (parseDataValue) { // Block data not yet detected
|
||||
// Parse the block data (optional)
|
||||
try {
|
||||
if (typeAndData.length > 1 && !typeAndData[1].isEmpty()) {
|
||||
data = Integer.parseInt(typeAndData[1]);
|
||||
}
|
||||
|
||||
if (data > 15) {
|
||||
throw new NoMatchException("Invalid data value '" + typeAndData[1] + "'");
|
||||
}
|
||||
|
||||
if (data < 0 && (context.isRestricted() || data != -1)) {
|
||||
data = 0;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
if (blockType == null) {
|
||||
throw new NoMatchException("Unknown data value '" + typeAndData[1] + "'");
|
||||
}
|
||||
|
||||
switch (blockType) {
|
||||
case CLOTH:
|
||||
case STAINED_CLAY:
|
||||
case CARPET:
|
||||
ClothColor col = ClothColor.lookup(typeAndData[1]);
|
||||
if (col == null) {
|
||||
throw new NoMatchException("Unknown wool color '" + typeAndData[1] + "'");
|
||||
}
|
||||
|
||||
data = col.getID();
|
||||
break;
|
||||
|
||||
case STEP:
|
||||
case DOUBLE_STEP:
|
||||
BlockType dataType = BlockType.lookup(typeAndData[1]);
|
||||
|
||||
if (dataType == null) {
|
||||
throw new NoMatchException("Unknown step type '" + typeAndData[1] + "'");
|
||||
}
|
||||
|
||||
switch (dataType) {
|
||||
case STONE:
|
||||
data = 0;
|
||||
break;
|
||||
case SANDSTONE:
|
||||
data = 1;
|
||||
break;
|
||||
case WOOD:
|
||||
data = 2;
|
||||
break;
|
||||
case COBBLESTONE:
|
||||
data = 3;
|
||||
break;
|
||||
case BRICK:
|
||||
data = 4;
|
||||
break;
|
||||
case STONE_BRICK:
|
||||
data = 5;
|
||||
break;
|
||||
case NETHER_BRICK:
|
||||
data = 6;
|
||||
break;
|
||||
case QUARTZ_BLOCK:
|
||||
data = 7;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NoMatchException("Invalid step type '" + typeAndData[1] + "'");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NoMatchException("Unknown data value '" + typeAndData[1] + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the item is allowed
|
||||
Actor actor = context.requireActor();
|
||||
if (context.isRestricted() && actor != null && !actor.hasPermission("worldedit.anyblock")
|
||||
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockId)) {
|
||||
throw new DisallowedUsageException("You are not allowed to use '" + input + "'");
|
||||
}
|
||||
|
||||
if (blockType == null) {
|
||||
return new BaseBlock(blockId, data);
|
||||
}
|
||||
|
||||
switch (blockType) {
|
||||
case SIGN_POST:
|
||||
case WALL_SIGN:
|
||||
// Allow special sign text syntax
|
||||
String[] text = new String[4];
|
||||
text[0] = blockAndExtraData.length > 1 ? blockAndExtraData[1] : "";
|
||||
text[1] = blockAndExtraData.length > 2 ? blockAndExtraData[2] : "";
|
||||
text[2] = blockAndExtraData.length > 3 ? blockAndExtraData[3] : "";
|
||||
text[3] = blockAndExtraData.length > 4 ? blockAndExtraData[4] : "";
|
||||
return new SignBlock(blockType.getID(), data, text);
|
||||
|
||||
case MOB_SPAWNER:
|
||||
// Allow setting mob spawn type
|
||||
if (blockAndExtraData.length > 1) {
|
||||
String mobName = blockAndExtraData[1];
|
||||
for (MobType mobType : MobType.values()) {
|
||||
if (mobType.getName().toLowerCase().equals(mobName.toLowerCase())) {
|
||||
mobName = mobType.getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!worldEdit.getServer().isValidMobType(mobName)) {
|
||||
throw new NoMatchException("Unknown mob type '" + mobName + "'");
|
||||
}
|
||||
return new MobSpawnerBlock(data, mobName);
|
||||
} else {
|
||||
return new MobSpawnerBlock(data, MobType.PIG.getName());
|
||||
}
|
||||
|
||||
case NOTE_BLOCK:
|
||||
// Allow setting note
|
||||
if (blockAndExtraData.length <= 1) {
|
||||
return new NoteBlock(data, (byte) 0);
|
||||
}
|
||||
|
||||
byte note = Byte.parseByte(blockAndExtraData[1]);
|
||||
if (note < 0 || note > 24) {
|
||||
throw new InputParseException("Out of range note value: '" + blockAndExtraData[1] + "'");
|
||||
}
|
||||
|
||||
return new NoteBlock(data, note);
|
||||
|
||||
case HEAD:
|
||||
// allow setting type/player/rotation
|
||||
if (blockAndExtraData.length <= 1) {
|
||||
return new SkullBlock(data);
|
||||
}
|
||||
|
||||
byte rot = 0;
|
||||
String type = "";
|
||||
try {
|
||||
rot = Byte.parseByte(blockAndExtraData[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
type = blockAndExtraData[1];
|
||||
if (blockAndExtraData.length > 2) {
|
||||
try {
|
||||
rot = Byte.parseByte(blockAndExtraData[2]);
|
||||
} catch (NumberFormatException e2) {
|
||||
throw new InputParseException("Second part of skull metadata should be a number.");
|
||||
}
|
||||
}
|
||||
}
|
||||
byte skullType = 0;
|
||||
// type is either the mob type or the player name
|
||||
// sorry for the four minecraft accounts named "skeleton", "wither", "zombie", or "creeper"
|
||||
if (!type.isEmpty()) {
|
||||
if (type.equalsIgnoreCase("skeleton")) skullType = 0;
|
||||
else if (type.equalsIgnoreCase("wither")) skullType = 1;
|
||||
else if (type.equalsIgnoreCase("zombie")) skullType = 2;
|
||||
else if (type.equalsIgnoreCase("creeper")) skullType = 4;
|
||||
else skullType = 3;
|
||||
}
|
||||
if (skullType == 3) {
|
||||
return new SkullBlock(data, rot, type.replace(" ", "_")); // valid MC usernames
|
||||
} else {
|
||||
return new SkullBlock(data, skullType, rot);
|
||||
}
|
||||
|
||||
default:
|
||||
return new BaseBlock(blockId, data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BiomeMask2D;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
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.Masks;
|
||||
import com.sk89q.worldedit.function.mask.NoiseFilter;
|
||||
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.ExpressionException;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.math.noise.RandomNoise;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.session.request.RequestSelection;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.biome.Biomes;
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Parses mask input strings.
|
||||
*/
|
||||
class DefaultMaskParser extends InputParser<Mask> {
|
||||
|
||||
protected DefaultMaskParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
List<Mask> masks = new ArrayList<Mask>();
|
||||
|
||||
for (String component : input.split(" ")) {
|
||||
if (component.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Mask current = getBlockMaskComponent(masks, component, context);
|
||||
|
||||
masks.add(current);
|
||||
}
|
||||
|
||||
switch (masks.size()) {
|
||||
case 0:
|
||||
return null;
|
||||
|
||||
case 1:
|
||||
return masks.get(0);
|
||||
|
||||
default:
|
||||
return new MaskIntersection(masks);
|
||||
}
|
||||
}
|
||||
|
||||
private Mask getBlockMaskComponent(List<Mask> masks, String component, ParserContext context) throws InputParseException {
|
||||
Extent extent = Request.request().getEditSession();
|
||||
|
||||
final char firstChar = component.charAt(0);
|
||||
switch (firstChar) {
|
||||
case '#':
|
||||
if (component.equalsIgnoreCase("#existing")) {
|
||||
return new ExistingBlockMask(extent);
|
||||
} else if (component.equalsIgnoreCase("#solid")) {
|
||||
return new SolidBlockMask(extent);
|
||||
} else if (component.equalsIgnoreCase("#dregion")
|
||||
|| component.equalsIgnoreCase("#dselection")
|
||||
|| component.equalsIgnoreCase("#dsel")) {
|
||||
return new RegionMask(new RequestSelection());
|
||||
} else if (component.equalsIgnoreCase("#selection")
|
||||
|| component.equalsIgnoreCase("#region")
|
||||
|| component.equalsIgnoreCase("#sel")) {
|
||||
try {
|
||||
return new RegionMask(context.requireSession().getSelection(context.requireWorld()).clone());
|
||||
} catch (IncompleteRegionException e) {
|
||||
throw new InputParseException("Please make a selection first.");
|
||||
}
|
||||
} else {
|
||||
throw new NoMatchException("Unrecognized mask '" + component + "'");
|
||||
}
|
||||
|
||||
case '>':
|
||||
case '<':
|
||||
Mask submask;
|
||||
if (component.length() > 1) {
|
||||
submask = getBlockMaskComponent(masks, component.substring(1), context);
|
||||
} else {
|
||||
submask = new ExistingBlockMask(extent);
|
||||
}
|
||||
OffsetMask offsetMask = new OffsetMask(submask, new Vector(0, firstChar == '>' ? -1 : 1, 0));
|
||||
return new MaskIntersection(offsetMask, Masks.negate(submask));
|
||||
|
||||
case '$':
|
||||
Set<BaseBiome> biomes = new HashSet<BaseBiome>();
|
||||
String[] biomesList = component.substring(1).split(",");
|
||||
BiomeRegistry biomeRegistry = context.requireWorld().getWorldData().getBiomeRegistry();
|
||||
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
|
||||
for (String biomeName : biomesList) {
|
||||
BaseBiome biome = Biomes.findBiomeByName(knownBiomes, biomeName, biomeRegistry);
|
||||
if (biome == null) {
|
||||
throw new InputParseException("Unknown biome '" + biomeName + "'");
|
||||
}
|
||||
biomes.add(biome);
|
||||
}
|
||||
|
||||
return Masks.asMask(new BiomeMask2D(context.requireExtent(), biomes));
|
||||
|
||||
case '%':
|
||||
int i = Integer.parseInt(component.substring(1));
|
||||
return new NoiseFilter(new RandomNoise(), ((double) i) / 100);
|
||||
|
||||
case '=':
|
||||
try {
|
||||
return new ExpressionMask(component.substring(1));
|
||||
} catch (ExpressionException e) {
|
||||
throw new InputParseException("Invalid expression: " + e.getMessage());
|
||||
}
|
||||
|
||||
case '!':
|
||||
if (component.length() > 1) {
|
||||
return Masks.negate(getBlockMaskComponent(masks, component.substring(1), context));
|
||||
}
|
||||
|
||||
default:
|
||||
ParserContext tempContext = new ParserContext(context);
|
||||
tempContext.setRestricted(false);
|
||||
tempContext.setPreferringWildcard(true);
|
||||
return new BlockMask(extent, worldEdit.getBlockFactory().parseFromListInput(component, tempContext));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.EmptyClipboardException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
|
||||
class HashTagPatternParser extends InputParser<Pattern> {
|
||||
|
||||
HashTagPatternParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
if (input.charAt(0) == '#') {
|
||||
if (!input.equals("#clipboard") && !input.equals("#copy")) {
|
||||
throw new InputParseException("#clipboard or #copy is acceptable for patterns starting with #");
|
||||
}
|
||||
|
||||
LocalSession session = context.requireSession();
|
||||
|
||||
if (session != null) {
|
||||
try {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
return new ClipboardPattern(clipboard);
|
||||
} catch (EmptyClipboardException e) {
|
||||
throw new InputParseException("To use #clipboard, please first copy something to your clipboard");
|
||||
}
|
||||
} else {
|
||||
throw new InputParseException("No session is available, so no clipboard is available");
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||
|
||||
/**
|
||||
* A registry of known {@link Mask}s. Provides methods to instantiate
|
||||
* new masks from input.
|
||||
*
|
||||
* <p>Instances of this class can be taken from
|
||||
* {@link WorldEdit#getMaskFactory()}.</p>
|
||||
*/
|
||||
public final class MaskFactory extends AbstractFactory<Mask> {
|
||||
|
||||
/**
|
||||
* Create a new mask registry.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
public MaskFactory(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
|
||||
parsers.add(new DefaultMaskParser(worldEdit));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||
|
||||
/**
|
||||
* A registry of known {@link Pattern}s. Provides methods to instantiate
|
||||
* new patterns from input.
|
||||
*
|
||||
* <p>Instances of this class can be taken from
|
||||
* {@link WorldEdit#getPatternFactory()}.</p>
|
||||
*/
|
||||
public final class PatternFactory extends AbstractFactory<Pattern> {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
public PatternFactory(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
|
||||
parsers.add(new HashTagPatternParser(worldEdit));
|
||||
parsers.add(new SingleBlockPatternParser(worldEdit));
|
||||
parsers.add(new RandomPatternParser(worldEdit));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
|
||||
class RandomPatternParser extends InputParser<Pattern> {
|
||||
|
||||
RandomPatternParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
BlockFactory blockRegistry = worldEdit.getBlockFactory();
|
||||
RandomPattern randomPattern = new RandomPattern();
|
||||
|
||||
for (String token : input.split(",")) {
|
||||
BaseBlock block;
|
||||
|
||||
double chance;
|
||||
|
||||
// Parse special percentage syntax
|
||||
if (token.matches("[0-9]+(\\.[0-9]*)?%.*")) {
|
||||
String[] p = token.split("%");
|
||||
|
||||
if (p.length < 2) {
|
||||
throw new InputParseException("Missing the type after the % symbol for '" + input + "'");
|
||||
} else {
|
||||
chance = Double.parseDouble(p[0]);
|
||||
block = blockRegistry.parseFromInput(p[1], context);
|
||||
}
|
||||
} else {
|
||||
chance = 1;
|
||||
block = blockRegistry.parseFromInput(token, context);
|
||||
}
|
||||
|
||||
randomPattern.add(new BlockPattern(block), chance);
|
||||
}
|
||||
|
||||
return randomPattern;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
|
||||
class SingleBlockPatternParser extends InputParser<Pattern> {
|
||||
|
||||
SingleBlockPatternParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
String[] items = input.split(",");
|
||||
|
||||
if (items.length == 1) {
|
||||
return new BlockPattern(worldEdit.getBlockFactory().parseFromInput(items[0], context));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.input;
|
||||
|
||||
/**
|
||||
* Thrown when usage is disallowed.
|
||||
*/
|
||||
public class DisallowedUsageException extends InputParseException {
|
||||
|
||||
/**
|
||||
* Create with a message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public DisallowedUsageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with a message and a cause.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public DisallowedUsageException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.input;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
/**
|
||||
* Thrown when parsed input results in an error.
|
||||
*/
|
||||
public class InputParseException extends WorldEditException {
|
||||
|
||||
/**
|
||||
* Throw with a message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public InputParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw with a message and a cause.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public InputParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.input;
|
||||
|
||||
/**
|
||||
* Thrown when a match fails when input is parsed.
|
||||
*/
|
||||
public class NoMatchException extends InputParseException {
|
||||
|
||||
/**
|
||||
* Create with a message.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public NoMatchException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with a message and a cause.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public NoMatchException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.input;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.extension.factory.MaskFactory;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Contains contextual information that may be useful when constructing
|
||||
* objects from a registry (such as {@link MaskFactory}).
|
||||
*
|
||||
* <p>By default, {@link #isRestricted()} will return true.</p>
|
||||
*/
|
||||
public class ParserContext {
|
||||
|
||||
private @Nullable Extent extent;
|
||||
private @Nullable LocalSession session;
|
||||
private @Nullable World world;
|
||||
private @Nullable Actor actor;
|
||||
private boolean restricted = true;
|
||||
private boolean preferringWildcard;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*/
|
||||
public ParserContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of another instance.
|
||||
*
|
||||
* @param other the other instance
|
||||
*/
|
||||
public ParserContext(ParserContext other) {
|
||||
setExtent(other.getExtent());
|
||||
setSession(other.getSession());
|
||||
setWorld(other.getWorld());
|
||||
setActor(other.getActor());
|
||||
setRestricted(other.isRestricted());
|
||||
setPreferringWildcard(other.isPreferringWildcard());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Extent} set on this context.
|
||||
*
|
||||
* @return an extent
|
||||
*/
|
||||
public @Nullable Extent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the extent.
|
||||
*
|
||||
* @param extent an extent, or null if none is available
|
||||
*/
|
||||
public void setExtent(@Nullable Extent extent) {
|
||||
this.extent = extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link LocalSession}.
|
||||
*
|
||||
* @return a session
|
||||
*/
|
||||
public @Nullable LocalSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the session.
|
||||
*
|
||||
* @param session a session, or null if none is available
|
||||
*/
|
||||
public void setSession(@Nullable LocalSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link World} set on this context.
|
||||
*
|
||||
* @return a world
|
||||
*/
|
||||
public @Nullable World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the world.
|
||||
*
|
||||
* @param world a world, or null if none is available
|
||||
*/
|
||||
public void setWorld(@Nullable World world) {
|
||||
this.world = world;
|
||||
setExtent(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Actor} set on this context.
|
||||
*
|
||||
* @return an actor, or null
|
||||
*/
|
||||
public @Nullable Actor getActor() {
|
||||
return actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the actor.
|
||||
*
|
||||
* @param actor an actor, or null if none is available
|
||||
*/
|
||||
public void setActor(@Nullable Actor actor) {
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Extent} set on this context.
|
||||
*
|
||||
* @return an extent
|
||||
* @throws InputParseException thrown if no {@link Extent} is set
|
||||
*/
|
||||
public Extent requireExtent() throws InputParseException {
|
||||
Extent extent = getExtent();
|
||||
if (extent == null) {
|
||||
throw new InputParseException("No Extent is known");
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link LocalSession}.
|
||||
*
|
||||
* @return a session
|
||||
* @throws InputParseException thrown if no {@link LocalSession} is set
|
||||
*/
|
||||
public LocalSession requireSession() throws InputParseException {
|
||||
LocalSession session = getSession();
|
||||
if (session == null) {
|
||||
throw new InputParseException("No LocalSession is known");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link World} set on this context.
|
||||
*
|
||||
* @return a world
|
||||
* @throws InputParseException thrown if no {@link World} is set
|
||||
*/
|
||||
public World requireWorld() throws InputParseException {
|
||||
World world = getWorld();
|
||||
if (world == null) {
|
||||
throw new InputParseException("No world is known");
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Actor} set on this context.
|
||||
*
|
||||
* @return an actor
|
||||
* @throws InputParseException thrown if no {@link Actor} is set
|
||||
*/
|
||||
public Actor requireActor() throws InputParseException {
|
||||
Actor actor = getActor();
|
||||
if (actor == null) {
|
||||
throw new InputParseException("No actor is known");
|
||||
}
|
||||
return actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there should be restrictions (as a result of
|
||||
* limits or permissions) considered when parsing the input.
|
||||
*
|
||||
* @return true if restricted
|
||||
*/
|
||||
public boolean isRestricted() {
|
||||
return restricted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether there should be restrictions (as a result of
|
||||
* limits or permissions) considered when parsing the input.
|
||||
*
|
||||
* @param restricted true if restricted
|
||||
*/
|
||||
public void setRestricted(boolean restricted) {
|
||||
this.restricted = restricted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether wildcards are preferred.
|
||||
*
|
||||
* @return true if wildcards are preferred
|
||||
*/
|
||||
public boolean isPreferringWildcard() {
|
||||
return preferringWildcard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether wildcards are preferred.
|
||||
*
|
||||
* @param preferringWildcard true if wildcards are preferred
|
||||
*/
|
||||
public void setPreferringWildcard(boolean preferringWildcard) {
|
||||
this.preferringWildcard = preferringWildcard;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An abstract implementation of {@link Platform}.
|
||||
*/
|
||||
public abstract class AbstractPlatform implements Platform {
|
||||
|
||||
@Override
|
||||
public int schedule(long delay, long period, Runnable task) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends World> getWorlds() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,494 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||
import com.sk89q.worldedit.BlockWorldVector;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.NotABlockException;
|
||||
import com.sk89q.worldedit.PlayerDirection;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.WorldVectorFace;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.blocks.ItemID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.util.TargetBlock;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* An abstract implementation of both a {@link Actor} and a {@link Player}
|
||||
* that is intended for implementations of WorldEdit to use to wrap
|
||||
* players that make use of WorldEdit.
|
||||
*/
|
||||
public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
|
||||
|
||||
@Override
|
||||
public final Extent getExtent() {
|
||||
return getWorld();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns direction according to rotation. May return null.
|
||||
*
|
||||
* @param rot yaw
|
||||
* @return the direction
|
||||
*/
|
||||
private static PlayerDirection getDirection(double rot) {
|
||||
if (0 <= rot && rot < 22.5) {
|
||||
return PlayerDirection.SOUTH;
|
||||
} else if (22.5 <= rot && rot < 67.5) {
|
||||
return PlayerDirection.SOUTH_WEST;
|
||||
} else if (67.5 <= rot && rot < 112.5) {
|
||||
return PlayerDirection.WEST;
|
||||
} else if (112.5 <= rot && rot < 157.5) {
|
||||
return PlayerDirection.NORTH_WEST;
|
||||
} else if (157.5 <= rot && rot < 202.5) {
|
||||
return PlayerDirection.NORTH;
|
||||
} else if (202.5 <= rot && rot < 247.5) {
|
||||
return PlayerDirection.NORTH_EAST;
|
||||
} else if (247.5 <= rot && rot < 292.5) {
|
||||
return PlayerDirection.EAST;
|
||||
} else if (292.5 <= rot && rot < 337.5) {
|
||||
return PlayerDirection.SOUTH_EAST;
|
||||
} else if (337.5 <= rot && rot < 360.0) {
|
||||
return PlayerDirection.SOUTH;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHoldingPickAxe() {
|
||||
int item = getItemInHand();
|
||||
return item == ItemID.IRON_PICK
|
||||
|| item == ItemID.WOOD_PICKAXE
|
||||
|| item == ItemID.STONE_PICKAXE
|
||||
|| item == ItemID.DIAMOND_PICKAXE
|
||||
|| item == ItemID.GOLD_PICKAXE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findFreePosition(WorldVector searchPos) {
|
||||
World world = searchPos.getWorld();
|
||||
int x = searchPos.getBlockX();
|
||||
int y = Math.max(0, searchPos.getBlockY());
|
||||
int origY = y;
|
||||
int z = searchPos.getBlockZ();
|
||||
|
||||
byte free = 0;
|
||||
|
||||
while (y <= world.getMaxY() + 2) {
|
||||
if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) {
|
||||
++free;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
if (y - 1 != origY) {
|
||||
final Vector pos = new Vector(x, y - 2, z);
|
||||
final int id = world.getBlockType(pos);
|
||||
final int data = world.getBlockData(pos);
|
||||
setPosition(new Vector(x + 0.5, y - 2 + BlockType.centralTopLimit(id, data), z + 0.5));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnGround(WorldVector searchPos) {
|
||||
World world = searchPos.getWorld();
|
||||
int x = searchPos.getBlockX();
|
||||
int y = Math.max(0, searchPos.getBlockY());
|
||||
int z = searchPos.getBlockZ();
|
||||
|
||||
while (y >= 0) {
|
||||
final Vector pos = new Vector(x, y, z);
|
||||
final int id = world.getBlockType(pos);
|
||||
final int data = world.getBlockData(pos);
|
||||
if (!BlockType.canPassThrough(id, data)) {
|
||||
setPosition(new Vector(x + 0.5, y + BlockType.centralTopLimit(id, data), z + 0.5));
|
||||
return;
|
||||
}
|
||||
|
||||
--y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findFreePosition() {
|
||||
findFreePosition(getBlockIn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ascendLevel() {
|
||||
final WorldVector pos = getBlockIn();
|
||||
final int x = pos.getBlockX();
|
||||
int y = Math.max(0, pos.getBlockY());
|
||||
final int z = pos.getBlockZ();
|
||||
final World world = pos.getWorld();
|
||||
|
||||
byte free = 0;
|
||||
byte spots = 0;
|
||||
|
||||
while (y <= world.getMaxY() + 2) {
|
||||
if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) {
|
||||
++free;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
++spots;
|
||||
if (spots == 2) {
|
||||
final Vector platform = new Vector(x, y - 2, z);
|
||||
final BaseBlock block = world.getBlock(platform);
|
||||
final int type = block.getId();
|
||||
|
||||
// Don't get put in lava!
|
||||
if (type == BlockID.LAVA || type == BlockID.STATIONARY_LAVA) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
++y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean descendLevel() {
|
||||
final WorldVector pos = getBlockIn();
|
||||
final int x = pos.getBlockX();
|
||||
int y = Math.max(0, pos.getBlockY() - 1);
|
||||
final int z = pos.getBlockZ();
|
||||
final World world = pos.getWorld();
|
||||
|
||||
byte free = 0;
|
||||
|
||||
while (y >= 1) {
|
||||
if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) {
|
||||
++free;
|
||||
} else {
|
||||
free = 0;
|
||||
}
|
||||
|
||||
if (free == 2) {
|
||||
// So we've found a spot, but we have to drop the player
|
||||
// lightly and also check to see if there's something to
|
||||
// stand upon
|
||||
while (y >= 0) {
|
||||
final Vector platform = new Vector(x, y, z);
|
||||
final BaseBlock block = world.getBlock(platform);
|
||||
final int type = block.getId();
|
||||
|
||||
// Don't want to end up in lava
|
||||
if (type != BlockID.AIR && type != BlockID.LAVA && type != BlockID.STATIONARY_LAVA) {
|
||||
// Found a block!
|
||||
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5));
|
||||
return true;
|
||||
}
|
||||
|
||||
--y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
--y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ascendToCeiling(int clearance) {
|
||||
return ascendToCeiling(clearance, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ascendToCeiling(int clearance, boolean alwaysGlass) {
|
||||
Vector pos = getBlockIn();
|
||||
int x = pos.getBlockX();
|
||||
int initialY = Math.max(0, pos.getBlockY());
|
||||
int y = Math.max(0, pos.getBlockY() + 2);
|
||||
int z = pos.getBlockZ();
|
||||
World world = getPosition().getWorld();
|
||||
|
||||
// No free space above
|
||||
if (world.getBlockType(new Vector(x, y, z)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (y <= world.getMaxY()) {
|
||||
// Found a ceiling!
|
||||
if (!BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) {
|
||||
int platformY = Math.max(initialY, y - 3 - clearance);
|
||||
floatAt(x, platformY + 1, z, alwaysGlass);
|
||||
return true;
|
||||
}
|
||||
|
||||
++y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ascendUpwards(int distance) {
|
||||
return ascendUpwards(distance, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ascendUpwards(int distance, boolean alwaysGlass) {
|
||||
final Vector pos = getBlockIn();
|
||||
final int x = pos.getBlockX();
|
||||
final int initialY = Math.max(0, pos.getBlockY());
|
||||
int y = Math.max(0, pos.getBlockY() + 1);
|
||||
final int z = pos.getBlockZ();
|
||||
final int maxY = Math.min(getWorld().getMaxY() + 1, initialY + distance);
|
||||
final World world = getPosition().getWorld();
|
||||
|
||||
while (y <= world.getMaxY() + 2) {
|
||||
if (!BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) {
|
||||
break; // Hit something
|
||||
} else if (y > maxY + 1) {
|
||||
break;
|
||||
} else if (y == maxY + 1) {
|
||||
floatAt(x, y - 1, z, alwaysGlass);
|
||||
return true;
|
||||
}
|
||||
|
||||
++y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void floatAt(int x, int y, int z, boolean alwaysGlass) {
|
||||
getPosition().getWorld().setBlockType(new Vector(x, y - 1, z), BlockID.GLASS);
|
||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getBlockIn() {
|
||||
WorldVector pos = getPosition();
|
||||
return WorldVector.toBlockPoint(pos.getWorld(), pos.getX(),
|
||||
pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getBlockOn() {
|
||||
WorldVector pos = getPosition();
|
||||
return WorldVector.toBlockPoint(pos.getWorld(), pos.getX(),
|
||||
pos.getY() - 1, pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getBlockTrace(int range, boolean useLastBlock) {
|
||||
TargetBlock tb = new TargetBlock(this, range, 0.2);
|
||||
return (useLastBlock ? tb.getAnyTargetBlock() : tb.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVectorFace getBlockTraceFace(int range, boolean useLastBlock) {
|
||||
TargetBlock tb = new TargetBlock(this, range, 0.2);
|
||||
return (useLastBlock ? tb.getAnyTargetBlockFace() : tb.getTargetBlockFace());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getBlockTrace(int range) {
|
||||
return getBlockTrace(range, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getSolidBlockTrace(int range) {
|
||||
TargetBlock tb = new TargetBlock(this, range, 0.2);
|
||||
return tb.getSolidTargetBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerDirection getCardinalDirection() {
|
||||
return getCardinalDirection(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerDirection getCardinalDirection(int yawOffset) {
|
||||
if (getPitch() > 67.5) {
|
||||
return PlayerDirection.DOWN;
|
||||
}
|
||||
if (getPitch() < -67.5) {
|
||||
return PlayerDirection.UP;
|
||||
}
|
||||
|
||||
// From hey0's code
|
||||
double rot = (getYaw() + yawOffset) % 360; //let's use real yaw now
|
||||
if (rot < 0) {
|
||||
rot += 360.0;
|
||||
}
|
||||
return getDirection(rot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockInHand() throws WorldEditException {
|
||||
final int typeId = getItemInHand();
|
||||
if (!getWorld().isValidBlockType(typeId)) {
|
||||
throw new NotABlockException(typeId);
|
||||
}
|
||||
return new BaseBlock(typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player's view yaw.
|
||||
*
|
||||
* @return yaw
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean passThroughForwardWall(int range) {
|
||||
int searchDist = 0;
|
||||
TargetBlock hitBlox = new TargetBlock(this, range, 0.2);
|
||||
World world = getPosition().getWorld();
|
||||
BlockWorldVector block;
|
||||
boolean firstBlock = true;
|
||||
int freeToFind = 2;
|
||||
boolean inFree = false;
|
||||
|
||||
while ((block = hitBlox.getNextBlock()) != null) {
|
||||
boolean free = BlockType.canPassThrough(world.getBlock(block));
|
||||
|
||||
if (firstBlock) {
|
||||
firstBlock = false;
|
||||
|
||||
if (!free) {
|
||||
--freeToFind;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
++searchDist;
|
||||
if (searchDist > 20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inFree != free) {
|
||||
if (free) {
|
||||
--freeToFind;
|
||||
}
|
||||
}
|
||||
|
||||
if (freeToFind == 0) {
|
||||
setOnGround(block);
|
||||
return true;
|
||||
}
|
||||
|
||||
inFree = free;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos) {
|
||||
setPosition(pos, (float) getPitch(), (float) getYaw());
|
||||
}
|
||||
|
||||
@Override
|
||||
public File openFileOpenDialog(String[] extensions) {
|
||||
printError("File dialogs are not supported in your environment.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File openFileSaveDialog(String[] extensions) {
|
||||
printError("File dialogs are not supported in your environment.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDestroyBedrock() {
|
||||
return hasPermission("worldedit.override.bedrock");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof LocalPlayer)) {
|
||||
return false;
|
||||
}
|
||||
LocalPlayer other2 = (LocalPlayer) other;
|
||||
return other2.getName().equals(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(String permission) throws AuthorizationException {
|
||||
if (!hasPermission(permission)) {
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCreativeMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("CloneDoesntCallSuperClone")
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
throw new CloneNotSupportedException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionOwner;
|
||||
import com.sk89q.worldedit.util.Identifiable;
|
||||
import com.sk89q.worldedit.util.auth.Subject;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* An object that can perform actions in WorldEdit.
|
||||
*/
|
||||
public interface Actor extends Identifiable, SessionOwner, Subject {
|
||||
|
||||
/**
|
||||
* Get the name of the actor.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Print a message.
|
||||
*
|
||||
* @param msg The message text
|
||||
*/
|
||||
void printRaw(String msg);
|
||||
|
||||
/**
|
||||
* Print a WorldEdit message.
|
||||
*
|
||||
* @param msg The message text
|
||||
*/
|
||||
void printDebug(String msg);
|
||||
|
||||
/**
|
||||
* Print a WorldEdit message.
|
||||
*
|
||||
* @param msg The message text
|
||||
*/
|
||||
void print(String msg);
|
||||
|
||||
/**
|
||||
* Print a WorldEdit error.
|
||||
*
|
||||
* @param msg The error message text
|
||||
*/
|
||||
void printError(String msg);
|
||||
|
||||
/**
|
||||
* Returns true if the actor can destroy bedrock.
|
||||
*
|
||||
* @return true if bedrock can be broken by the actor
|
||||
*/
|
||||
boolean canDestroyBedrock();
|
||||
|
||||
/**
|
||||
* Return whether this actor is a player.
|
||||
*
|
||||
* @return true if a player
|
||||
*/
|
||||
boolean isPlayer();
|
||||
|
||||
/**
|
||||
* Open a file open dialog.
|
||||
*
|
||||
* @param extensions null to allow all
|
||||
* @return the selected file or null if something went wrong
|
||||
*/
|
||||
File openFileOpenDialog(String[] extensions);
|
||||
|
||||
/**
|
||||
* Open a file save dialog.
|
||||
*
|
||||
* @param extensions null to allow all
|
||||
* @return the selected file or null if something went wrong
|
||||
*/
|
||||
File openFileSaveDialog(String[] extensions);
|
||||
|
||||
/**
|
||||
* Send a CUI event.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
void dispatchCUIEvent(CUIEvent event);
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
/**
|
||||
* A collection of capabilities that a {@link Platform} may support.
|
||||
*/
|
||||
public enum Capability {
|
||||
|
||||
/**
|
||||
* The capability of registering game hooks to catch events such as
|
||||
* a player clicking a block.
|
||||
*/
|
||||
GAME_HOOKS {
|
||||
@Override
|
||||
void initialize(PlatformManager platformManager, Platform platform) {
|
||||
platform.registerGameHooks();
|
||||
}
|
||||
|
||||
@Override
|
||||
void unload(PlatformManager platformManager, Platform platform) {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The capability of providing configuration.
|
||||
*/
|
||||
CONFIGURATION,
|
||||
|
||||
/**
|
||||
* The capability of handling user commands entered in chat or console.
|
||||
*/
|
||||
USER_COMMANDS {
|
||||
@Override
|
||||
void initialize(PlatformManager platformManager, Platform platform) {
|
||||
platformManager.getCommandManager().register(platform);
|
||||
}
|
||||
|
||||
@Override
|
||||
void unload(PlatformManager platformManager, Platform platform) {
|
||||
platformManager.getCommandManager().unregister();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The capability of a platform to assess whether a given
|
||||
* {@link Actor} has sufficient authorization to perform a task.
|
||||
*/
|
||||
PERMISSIONS,
|
||||
|
||||
/**
|
||||
* The capability of a platform to dispatch WorldEditCUI events.
|
||||
*/
|
||||
WORLDEDIT_CUI,
|
||||
|
||||
/**
|
||||
* The capability of a platform to perform modifications to a world.
|
||||
*/
|
||||
WORLD_EDITING;
|
||||
|
||||
void initialize(PlatformManager platformManager, Platform platform) {
|
||||
|
||||
}
|
||||
|
||||
void unload(PlatformManager platformManager, Platform platform) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.*;
|
||||
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
|
||||
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
|
||||
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
|
||||
import com.sk89q.worldedit.internal.command.UserCommandCompleter;
|
||||
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
||||
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.InvalidUsageException;
|
||||
import com.sk89q.worldedit.util.command.fluent.CommandGraph;
|
||||
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Handles the registration and invocation of commands.
|
||||
*
|
||||
* <p>This class is primarily for internal usage.</p>
|
||||
*/
|
||||
public final class CommandManager {
|
||||
|
||||
public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+");
|
||||
private static final Logger log = Logger.getLogger(CommandManager.class.getCanonicalName());
|
||||
private static final Logger commandLog = Logger.getLogger(CommandManager.class.getCanonicalName() + ".CommandLog");
|
||||
private static final java.util.regex.Pattern numberFormatExceptionPattern = java.util.regex.Pattern.compile("^For input string: \"(.*)\"$");
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final PlatformManager platformManager;
|
||||
private final Dispatcher dispatcher;
|
||||
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
CommandManager(final WorldEdit worldEdit, PlatformManager platformManager) {
|
||||
checkNotNull(worldEdit);
|
||||
checkNotNull(platformManager);
|
||||
this.worldEdit = worldEdit;
|
||||
this.platformManager = platformManager;
|
||||
|
||||
// Register this instance for command events
|
||||
worldEdit.getEventBus().register(this);
|
||||
|
||||
// Setup the logger
|
||||
commandLog.addHandler(dynamicHandler);
|
||||
dynamicHandler.setFormatter(new LogFormat());
|
||||
|
||||
// Set up the commands manager
|
||||
ParametricBuilder builder = new ParametricBuilder();
|
||||
builder.setAuthorizer(new ActorAuthorizer());
|
||||
builder.setDefaultCompleter(new UserCommandCompleter(platformManager));
|
||||
builder.addBinding(new WorldEditBinding(worldEdit));
|
||||
builder.addExceptionConverter(new WorldEditExceptionConverter(worldEdit));
|
||||
builder.addInvokeListener(new LegacyCommandsHandler());
|
||||
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog));
|
||||
|
||||
dispatcher = new CommandGraph()
|
||||
.builder(builder)
|
||||
.commands()
|
||||
.registerMethods(new BiomeCommands(worldEdit))
|
||||
.registerMethods(new ChunkCommands(worldEdit))
|
||||
.registerMethods(new ClipboardCommands(worldEdit))
|
||||
.registerMethods(new GeneralCommands(worldEdit))
|
||||
.registerMethods(new GenerationCommands(worldEdit))
|
||||
.registerMethods(new HistoryCommands(worldEdit))
|
||||
.registerMethods(new NavigationCommands(worldEdit))
|
||||
.registerMethods(new RegionCommands(worldEdit))
|
||||
.registerMethods(new ScriptingCommands(worldEdit))
|
||||
.registerMethods(new SelectionCommands(worldEdit))
|
||||
.registerMethods(new SnapshotUtilCommands(worldEdit))
|
||||
.registerMethods(new ToolUtilCommands(worldEdit))
|
||||
.registerMethods(new ToolCommands(worldEdit))
|
||||
.registerMethods(new UtilityCommands(worldEdit))
|
||||
.group("worldedit", "we")
|
||||
.describeAs("WorldEdit commands")
|
||||
.registerMethods(new WorldEditCommands(worldEdit))
|
||||
.parent()
|
||||
.group("schematic", "schem", "/schematic", "/schem")
|
||||
.describeAs("Schematic commands for saving/loading areas")
|
||||
.registerMethods(new SchematicCommands(worldEdit))
|
||||
.parent()
|
||||
.group("snapshot", "snap")
|
||||
.describeAs("Schematic commands for saving/loading areas")
|
||||
.registerMethods(new SnapshotCommands(worldEdit))
|
||||
.parent()
|
||||
.group("brush", "br")
|
||||
.describeAs("Brushing commands")
|
||||
.registerMethods(new BrushCommands(worldEdit))
|
||||
.parent()
|
||||
.group("superpickaxe", "pickaxe", "sp")
|
||||
.describeAs("Super-pickaxe commands")
|
||||
.registerMethods(new SuperPickaxeCommands(worldEdit))
|
||||
.parent()
|
||||
.group("tool")
|
||||
.describeAs("Bind functions to held items")
|
||||
.registerMethods(new ToolCommands(worldEdit))
|
||||
.parent()
|
||||
.graph()
|
||||
.getDispatcher();
|
||||
}
|
||||
|
||||
void register(Platform platform) {
|
||||
log.log(Level.FINE, "Registering commands with " + platform.getClass().getCanonicalName());
|
||||
|
||||
LocalConfiguration config = platform.getConfiguration();
|
||||
boolean logging = config.logCommands;
|
||||
String path = config.logFile;
|
||||
|
||||
// Register log
|
||||
if (!logging || path.isEmpty()) {
|
||||
dynamicHandler.setHandler(null);
|
||||
commandLog.setLevel(Level.OFF);
|
||||
} else {
|
||||
File file = new File(config.getWorkingDirectory(), path);
|
||||
commandLog.setLevel(Level.ALL);
|
||||
|
||||
log.log(Level.INFO, "Logging WorldEdit commands to " + file.getAbsolutePath());
|
||||
|
||||
try {
|
||||
dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true));
|
||||
} catch (IOException e) {
|
||||
log.log(Level.WARNING, "Could not use command log file " + path + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
platform.registerCommands(dispatcher);
|
||||
}
|
||||
|
||||
void unregister() {
|
||||
dynamicHandler.setHandler(null);
|
||||
}
|
||||
|
||||
public String[] commandDetection(String[] split) {
|
||||
// Quick script shortcut
|
||||
if (split[0].matches("^[^/].*\\.js$")) {
|
||||
String[] newSplit = new String[split.length + 1];
|
||||
System.arraycopy(split, 0, newSplit, 1, split.length);
|
||||
newSplit[0] = "cs";
|
||||
newSplit[1] = newSplit[1];
|
||||
split = newSplit;
|
||||
}
|
||||
|
||||
String searchCmd = split[0].toLowerCase();
|
||||
|
||||
// Try to detect the command
|
||||
if (!dispatcher.contains(searchCmd)) {
|
||||
if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
|
||||
split[0] = "/" + split[0];
|
||||
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) {
|
||||
split[0] = split[0].substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommand(CommandEvent event) {
|
||||
Request.reset();
|
||||
|
||||
Actor actor = platformManager.createProxyActor(event.getActor());
|
||||
String[] split = commandDetection(event.getArguments().split(" "));
|
||||
|
||||
// No command found!
|
||||
if (!dispatcher.contains(split[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, actor);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
|
||||
} catch (CommandPermissionsException e) {
|
||||
actor.printError("You don't have permission to do this.");
|
||||
} catch (InvalidUsageException e) {
|
||||
if (e.isFullHelpSuggested()) {
|
||||
actor.printRaw(ColorCodeBuilder.asColorCodes(new CommandUsageBox(e.getCommand(), e.getCommandUsed("/", ""), locals)));
|
||||
String message = e.getMessage();
|
||||
if (message != null) {
|
||||
actor.printError(message);
|
||||
}
|
||||
} else {
|
||||
String message = e.getMessage();
|
||||
actor.printError(message != null ? message : "The command was not used properly (no more help available).");
|
||||
actor.printError("Usage: " + e.getSimpleUsageString("/"));
|
||||
}
|
||||
} catch (WrappedCommandException e) {
|
||||
Throwable t = e.getCause();
|
||||
actor.printError("Please report this error: [See console]");
|
||||
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
||||
log.log(Level.SEVERE, "An unexpected error while handling a WorldEdit command", t);
|
||||
} catch (CommandException e) {
|
||||
String message = e.getMessage();
|
||||
if (message != null) {
|
||||
actor.printError(e.getMessage());
|
||||
} else {
|
||||
actor.printError("An unknown error has occurred! Please see console.");
|
||||
log.log(Level.SEVERE, "An unknown error occurred", e);
|
||||
}
|
||||
} finally {
|
||||
EditSession editSession = locals.get(EditSession.class);
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushQueue();
|
||||
|
||||
if (config.profile) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
int changed = editSession.getBlockChangeCount();
|
||||
if (time > 0) {
|
||||
double throughput = changed / (time / 1000.0);
|
||||
actor.printDebug((time / 1000.0) + "s elapsed (history: "
|
||||
+ changed + " changed; "
|
||||
+ Math.round(throughput) + " blocks/sec).");
|
||||
} else {
|
||||
actor.printDebug((time / 1000.0) + "s elapsed.");
|
||||
}
|
||||
}
|
||||
|
||||
worldEdit.flushBlockBag(actor, editSession);
|
||||
}
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
||||
try {
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, event.getActor());
|
||||
event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals));
|
||||
} catch (CommandException e) {
|
||||
event.getActor().printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command dispatcher instance.
|
||||
*
|
||||
* @return the command dispatcher
|
||||
*/
|
||||
public Dispatcher getDispatcher() {
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
public static Logger getLogger() {
|
||||
return commandLog;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Implements a platform with multiple connected users.
|
||||
*/
|
||||
public interface MultiUserPlatform extends Platform {
|
||||
|
||||
/**
|
||||
* Get a list of connected users.
|
||||
*
|
||||
* @return a list of connected users
|
||||
*/
|
||||
Collection<Actor> getConnectedUsers();
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
/**
|
||||
* Thrown when no capable platform is found.
|
||||
*/
|
||||
public class NoCapablePlatformException extends RuntimeException {
|
||||
|
||||
public NoCapablePlatformException() {
|
||||
}
|
||||
|
||||
public NoCapablePlatformException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NoCapablePlatformException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public NoCapablePlatformException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a platform that WorldEdit has been implemented for.
|
||||
*
|
||||
* <p>It is strongly recommended that implementations extend from
|
||||
* {@link AbstractPlatform}.</p>
|
||||
*/
|
||||
public interface Platform {
|
||||
|
||||
/**
|
||||
* Resolves an item name to its ID.
|
||||
*
|
||||
* @param name The name to look up
|
||||
* @return The id that corresponds to the name, or -1 if no such ID exists
|
||||
*/
|
||||
int resolveItem(String name);
|
||||
|
||||
/**
|
||||
* Checks if a mob type is valid.
|
||||
*
|
||||
* @param type The mob type name to check
|
||||
* @return Whether the name is a valid mod bype
|
||||
*/
|
||||
boolean isValidMobType(String type);
|
||||
|
||||
/**
|
||||
* Reload WorldEdit configuration.
|
||||
*/
|
||||
void reload();
|
||||
|
||||
/**
|
||||
* Schedules the given {@code task} to be invoked once every
|
||||
* {@code period} ticks after an initial delay of {@code delay} ticks.
|
||||
*
|
||||
* @param delay Delay in server ticks before executing first repeat
|
||||
* @param period Period in server ticks of the task
|
||||
* @param task Task to be executed
|
||||
* @return Task id number (-1 if scheduling failed)
|
||||
*/
|
||||
int schedule(long delay, long period, Runnable task);
|
||||
|
||||
/**
|
||||
* Get a list of available or loaded worlds.
|
||||
*
|
||||
* @return a list of worlds
|
||||
*/
|
||||
List<? extends World> getWorlds();
|
||||
|
||||
/**
|
||||
* Create a duplicate of the given player.
|
||||
*
|
||||
* <p>The given player may have been provided by a different platform.</p>
|
||||
*
|
||||
* @param player the player to match
|
||||
* @return a matched player, otherwise null
|
||||
*/
|
||||
@Nullable Player matchPlayer(Player player);
|
||||
|
||||
/**
|
||||
* Create a duplicate of the given world.
|
||||
*
|
||||
* <p>The given world may have been provided by a different platform.</p>
|
||||
*
|
||||
* @param world the world to match
|
||||
* @return a matched world, otherwise null
|
||||
*/
|
||||
@Nullable World matchWorld(World world);
|
||||
|
||||
/**
|
||||
* Register the commands contained within the given command dispatcher.
|
||||
*
|
||||
* @param dispatcher the dispatcher
|
||||
*/
|
||||
void registerCommands(Dispatcher dispatcher);
|
||||
|
||||
/**
|
||||
* Register game hooks.
|
||||
*/
|
||||
void registerGameHooks();
|
||||
|
||||
/**
|
||||
* Get the configuration from this platform.
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
LocalConfiguration getConfiguration();
|
||||
|
||||
/**
|
||||
* Get the version of WorldEdit that this platform provides.
|
||||
*
|
||||
* <p>This version should match WorldEdit releases because it may be
|
||||
* checked to match.</p>
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Get a friendly name of the platform.
|
||||
*
|
||||
* <p>The name can be anything (reasonable). An example name may be
|
||||
* "Bukkit" or "Forge".</p>
|
||||
*
|
||||
* @return the platform name
|
||||
*/
|
||||
String getPlatformName();
|
||||
|
||||
/**
|
||||
* Get the version of the platform, which can be anything.
|
||||
*
|
||||
* @return the platform version
|
||||
*/
|
||||
String getPlatformVersion();
|
||||
|
||||
/**
|
||||
* Get a map of advertised capabilities of this platform, where each key
|
||||
* in the given map is a supported capability and the respective value
|
||||
* indicates the preference for this platform for that given capability.
|
||||
*
|
||||
* @return a map of capabilities
|
||||
*/
|
||||
Map<Capability, Preference> getCapabilities();
|
||||
|
||||
}
|
@ -0,0 +1,466 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.ServerInterface;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.command.tool.BlockTool;
|
||||
import com.sk89q.worldedit.command.tool.DoubleActionBlockTool;
|
||||
import com.sk89q.worldedit.command.tool.DoubleActionTraceTool;
|
||||
import com.sk89q.worldedit.command.tool.Tool;
|
||||
import com.sk89q.worldedit.command.tool.TraceTool;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
|
||||
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||
import com.sk89q.worldedit.event.platform.Interaction;
|
||||
import com.sk89q.worldedit.event.platform.PlatformInitializeEvent;
|
||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
|
||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||
import com.sk89q.worldedit.internal.ServerInterfaceAdapter;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Manages registered {@link Platform}s for WorldEdit. Platforms are
|
||||
* implementations of WorldEdit.
|
||||
*
|
||||
* <p>This class is thread-safe.</p>
|
||||
*/
|
||||
public class PlatformManager {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PlatformManager.class.getCanonicalName());
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final CommandManager commandManager;
|
||||
private final List<Platform> platforms = new ArrayList<Platform>();
|
||||
private final Map<Capability, Platform> preferences = new EnumMap<Capability, Platform>(Capability.class);
|
||||
private @Nullable String firstSeenVersion;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final AtomicBoolean configured = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
* Create a new platform manager.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
public PlatformManager(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
this.commandManager = new CommandManager(worldEdit, this);
|
||||
|
||||
// Register this instance for events
|
||||
worldEdit.getEventBus().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a platform with WorldEdit.
|
||||
*
|
||||
* @param platform the platform
|
||||
*/
|
||||
public synchronized void register(Platform platform) {
|
||||
checkNotNull(platform);
|
||||
|
||||
logger.log(Level.FINE, "Got request to register " + platform.getClass() + " with WorldEdit [" + super.toString() + "]");
|
||||
|
||||
// Just add the platform to the list of platforms: we'll pick favorites
|
||||
// once all the platforms have been loaded
|
||||
platforms.add(platform);
|
||||
|
||||
// Make sure that versions are in sync
|
||||
if (firstSeenVersion != null) {
|
||||
if (!firstSeenVersion.equals(platform.getVersion())) {
|
||||
logger.log(Level.WARNING, "Multiple ports of WorldEdit are installed but they report different versions ({0} and {1}). " +
|
||||
"If these two versions are truly different, then you may run into unexpected crashes and errors.",
|
||||
new Object[]{ firstSeenVersion, platform.getVersion() });
|
||||
}
|
||||
} else {
|
||||
firstSeenVersion = platform.getVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a platform from WorldEdit.
|
||||
*
|
||||
* <p>If the platform has been chosen for any capabilities, then a new
|
||||
* platform will be found.</p>
|
||||
*
|
||||
* @param platform the platform
|
||||
*/
|
||||
public synchronized boolean unregister(Platform platform) {
|
||||
checkNotNull(platform);
|
||||
|
||||
boolean removed = platforms.remove(platform);
|
||||
|
||||
if (removed) {
|
||||
logger.log(Level.FINE, "Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
|
||||
|
||||
boolean choosePreferred = false;
|
||||
|
||||
// Check whether this platform was chosen to be the preferred one
|
||||
// for any capability and be sure to remove it
|
||||
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<Capability, Platform> entry = it.next();
|
||||
if (entry.getValue().equals(platform)) {
|
||||
entry.getKey().unload(this, entry.getValue());
|
||||
it.remove();
|
||||
choosePreferred = true; // Have to choose new favorites
|
||||
}
|
||||
}
|
||||
|
||||
if (choosePreferred) {
|
||||
choosePreferred();
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred platform for handling a certain capability. Returns
|
||||
* null if none is available.
|
||||
*
|
||||
* @param capability the capability
|
||||
* @return the platform
|
||||
* @throws NoCapablePlatformException thrown if no platform is capable
|
||||
*/
|
||||
public synchronized Platform queryCapability(Capability capability) throws NoCapablePlatformException {
|
||||
Platform platform = preferences.get(checkNotNull(capability));
|
||||
if (platform != null) {
|
||||
return platform;
|
||||
} else {
|
||||
throw new NoCapablePlatformException("No platform was found supporting " + capability.name());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose preferred platforms and perform necessary initialization.
|
||||
*/
|
||||
private synchronized void choosePreferred() {
|
||||
for (Capability capability : Capability.values()) {
|
||||
Platform preferred = findMostPreferred(capability);
|
||||
if (preferred != null) {
|
||||
preferences.put(capability, preferred);
|
||||
capability.initialize(this, preferred);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire configuration event
|
||||
if (preferences.containsKey(Capability.CONFIGURATION) && configured.compareAndSet(false, true)) {
|
||||
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the most preferred platform for a given capability from the list of
|
||||
* platforms. This does not use the map of preferred platforms.
|
||||
*
|
||||
* @param capability the capability
|
||||
* @return the most preferred platform, or null if no platform was found
|
||||
*/
|
||||
private synchronized @Nullable Platform findMostPreferred(Capability capability) {
|
||||
Platform preferred = null;
|
||||
Preference highest = null;
|
||||
|
||||
for (Platform platform : platforms) {
|
||||
Preference preference = platform.getCapabilities().get(capability);
|
||||
if (preference != null && (highest == null || preference.isPreferredOver(highest))) {
|
||||
preferred = platform;
|
||||
highest = preference;
|
||||
}
|
||||
}
|
||||
|
||||
return preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of loaded platforms.
|
||||
*
|
||||
* <p>The returned list is a copy of the original and is mutable.</p>
|
||||
*
|
||||
* @return a list of platforms
|
||||
*/
|
||||
public synchronized List<Platform> getPlatforms() {
|
||||
return new ArrayList<Platform>(platforms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a world, possibly return the same world but using a different
|
||||
* platform preferred for world editing operations.
|
||||
*
|
||||
* @param base the world to match
|
||||
* @return the preferred world, if one was found, otherwise the given world
|
||||
*/
|
||||
public World getWorldForEditing(World base) {
|
||||
checkNotNull(base);
|
||||
World match = queryCapability(Capability.WORLD_EDITING).matchWorld(base);
|
||||
return match != null ? match : base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an actor, return a new one that may use a different platform
|
||||
* for permissions and world editing.
|
||||
*
|
||||
* @param base the base actor to match
|
||||
* @return a new delegate actor
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Actor> T createProxyActor(T base) {
|
||||
checkNotNull(base);
|
||||
|
||||
if (base instanceof Player) {
|
||||
Player player = (Player) base;
|
||||
|
||||
Player permActor = queryCapability(Capability.PERMISSIONS).matchPlayer(player);
|
||||
if (permActor == null) {
|
||||
permActor = player;
|
||||
}
|
||||
|
||||
Player cuiActor = queryCapability(Capability.WORLDEDIT_CUI).matchPlayer(player);
|
||||
if (cuiActor == null) {
|
||||
cuiActor = player;
|
||||
}
|
||||
|
||||
return (T) new PlayerProxy(player, permActor, cuiActor, getWorldForEditing(player.getWorld()));
|
||||
} else {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command manager.
|
||||
*
|
||||
* @return the command manager
|
||||
*/
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current configuration.
|
||||
*
|
||||
* <p>If no platform has been registered yet, then a default configuration
|
||||
* will be returned.</p>
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public LocalConfiguration getConfiguration() {
|
||||
return queryCapability(Capability.CONFIGURATION).getConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a legacy {@link ServerInterface}.
|
||||
*
|
||||
* @return a {@link ServerInterface}
|
||||
* @throws IllegalStateException if no platform has been registered
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public ServerInterface getServerInterface() throws IllegalStateException {
|
||||
return ServerInterfaceAdapter.adapt(queryCapability(Capability.USER_COMMANDS));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handlePlatformReady(PlatformReadyEvent event) {
|
||||
choosePreferred();
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
worldEdit.getEventBus().post(new PlatformInitializeEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Subscribe
|
||||
public void handleBlockInteract(BlockInteractEvent event) {
|
||||
// Create a proxy actor with a potentially different world for
|
||||
// making changes to the world
|
||||
Actor actor = createProxyActor(event.getCause());
|
||||
|
||||
Location location = event.getLocation();
|
||||
Vector vector = location.toVector();
|
||||
|
||||
// At this time, only handle interaction from players
|
||||
if (actor instanceof Player) {
|
||||
Player player = (Player) actor;
|
||||
LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||
|
||||
if (event.getType() == Interaction.HIT) {
|
||||
if (player.getItemInHand() == getConfiguration().wandItem) {
|
||||
if (!session.isToolControlEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!actor.hasPermission("worldedit.selection.pos")) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
|
||||
if (selector.selectPrimary(location.toVector(), ActorSelectorLimits.forActor(player))) {
|
||||
selector.explainPrimarySelection(actor, session, vector);
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.isHoldingPickAxe() && session.hasSuperPickAxe()) {
|
||||
final BlockTool superPickaxe = session.getSuperPickaxe();
|
||||
if (superPickaxe != null && superPickaxe.canUse(player)) {
|
||||
event.setCancelled(superPickaxe.actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool != null && tool instanceof DoubleActionBlockTool) {
|
||||
if (tool.canUse(player)) {
|
||||
((DoubleActionBlockTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (event.getType() == Interaction.OPEN) {
|
||||
if (player.getItemInHand() == getConfiguration().wandItem) {
|
||||
if (!session.isToolControlEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!actor.hasPermission("worldedit.selection.pos")) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
if (selector.selectSecondary(vector, ActorSelectorLimits.forActor(player))) {
|
||||
selector.explainSecondarySelection(actor, session, vector);
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool != null && tool instanceof BlockTool) {
|
||||
if (tool.canUse(player)) {
|
||||
((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session, location);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Subscribe
|
||||
public void handlePlayerInput(PlayerInputEvent event) {
|
||||
// Create a proxy actor with a potentially different world for
|
||||
// making changes to the world
|
||||
Player player = createProxyActor(event.getPlayer());
|
||||
|
||||
switch (event.getInputType()) {
|
||||
case PRIMARY: {
|
||||
if (player.getItemInHand() == getConfiguration().navigationWand) {
|
||||
if (getConfiguration().navigationWandMaxDistance <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("worldedit.navigation.jumpto.tool")) {
|
||||
return;
|
||||
}
|
||||
|
||||
WorldVector pos = player.getSolidBlockTrace(getConfiguration().navigationWandMaxDistance);
|
||||
if (pos != null) {
|
||||
player.findFreePosition(pos);
|
||||
} else {
|
||||
player.printError("No block in sight (or too far)!");
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
LocalSession session = worldEdit.getSessionManager().get(player);
|
||||
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool != null && tool instanceof DoubleActionTraceTool) {
|
||||
if (tool.canUse(player)) {
|
||||
((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SECONDARY: {
|
||||
if (player.getItemInHand() == getConfiguration().navigationWand) {
|
||||
if (getConfiguration().navigationWandMaxDistance <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("worldedit.navigation.thru.tool")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.passThroughForwardWall(40)) {
|
||||
player.printError("Nothing to pass through!");
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
LocalSession session = worldEdit.getSessionManager().get(player);
|
||||
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool != null && tool instanceof TraceTool) {
|
||||
if (tool.canUse(player)) {
|
||||
((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
class PlayerProxy extends AbstractPlayerActor {
|
||||
|
||||
private final Player basePlayer;
|
||||
private final Actor permActor;
|
||||
private final Actor cuiActor;
|
||||
private final World world;
|
||||
|
||||
PlayerProxy(Player basePlayer, Actor permActor, Actor cuiActor, World world) {
|
||||
checkNotNull(basePlayer);
|
||||
checkNotNull(permActor);
|
||||
checkNotNull(cuiActor);
|
||||
checkNotNull(world);
|
||||
this.basePlayer = basePlayer;
|
||||
this.permActor = permActor;
|
||||
this.cuiActor = cuiActor;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return basePlayer.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
return basePlayer.getItemInHand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amount) {
|
||||
basePlayer.giveItem(type, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return basePlayer.getInventoryBlockBag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return basePlayer.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Can't getState() on a player");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return basePlayer.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
return basePlayer.getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return basePlayer.getPitch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return basePlayer.getYaw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
basePlayer.setPosition(pos, pitch, yaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
basePlayer.printRaw(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
basePlayer.printDebug(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
basePlayer.print(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
basePlayer.printError(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return permActor.getGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return permActor.hasPermission(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
cuiActor.dispatchCUIEvent(event);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return basePlayer.getFacet(cls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return basePlayer.getSessionKey();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Indicates the preference of a platform for a particular
|
||||
* {@link Capability}.
|
||||
*/
|
||||
public enum Preference {
|
||||
|
||||
/**
|
||||
* Indicates that the platform should be preferred for a given capability.
|
||||
*/
|
||||
PREFERRED,
|
||||
|
||||
/**
|
||||
* Indicates that preference for a platform is neutral for a given
|
||||
* capability.
|
||||
*/
|
||||
NORMAL,
|
||||
|
||||
/**
|
||||
* Indicates that there should not be a preference for the platform for
|
||||
* a given capability.
|
||||
*/
|
||||
PREFER_OTHERS;
|
||||
|
||||
/**
|
||||
* Returns whether this given preference is preferred over the given
|
||||
* other preference.
|
||||
*
|
||||
* @param other the other preference
|
||||
* @return true if this preference is greater
|
||||
*/
|
||||
public boolean isPreferredOver(Preference other) {
|
||||
checkNotNull(other);
|
||||
return ordinal() < other.ordinal();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform.permission;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ActorSelectorLimits implements SelectorLimits {
|
||||
|
||||
private final LocalConfiguration configuration;
|
||||
private final Actor actor;
|
||||
|
||||
public ActorSelectorLimits(LocalConfiguration configuration, Actor actor) {
|
||||
checkNotNull(configuration);
|
||||
checkNotNull(actor);
|
||||
|
||||
this.configuration = configuration;
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> getPolygonVertexLimit() {
|
||||
int limit;
|
||||
|
||||
if (actor.hasPermission(OverridePermissions.NO_LIMITS) || configuration.maxPolygonalPoints < 0) {
|
||||
limit = configuration.defaultMaxPolygonalPoints;
|
||||
} else if (configuration.defaultMaxPolygonalPoints < 0) {
|
||||
limit = configuration.maxPolygonalPoints;
|
||||
} else {
|
||||
limit = Math.min(configuration.defaultMaxPolygonalPoints, configuration.maxPolygonalPoints);
|
||||
}
|
||||
|
||||
if (limit > 0) {
|
||||
return Optional.of(limit);
|
||||
} else {
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> getPolyhedronVertexLimit() {
|
||||
int limit;
|
||||
|
||||
if (actor.hasPermission(OverridePermissions.NO_LIMITS) || configuration.maxPolyhedronPoints < 0) {
|
||||
limit = configuration.defaultMaxPolyhedronPoints;
|
||||
} else if (configuration.defaultMaxPolyhedronPoints < 0) {
|
||||
limit = configuration.maxPolyhedronPoints;
|
||||
} else {
|
||||
limit = Math.min(configuration.defaultMaxPolyhedronPoints, configuration.maxPolyhedronPoints);
|
||||
}
|
||||
|
||||
if (limit > 0) {
|
||||
return Optional.of(limit);
|
||||
} else {
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
public static ActorSelectorLimits forActor(Actor actor) {
|
||||
return new ActorSelectorLimits(WorldEdit.getInstance().getConfiguration(), actor);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform.permission;
|
||||
|
||||
/**
|
||||
* Standard override permissions.
|
||||
*/
|
||||
public final class OverridePermissions {
|
||||
|
||||
public static final String NO_LIMITS = "worldedit.limit.unrestricted";
|
||||
|
||||
private OverridePermissions() {
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user