This commit is contained in:
Jesse Boyd 2018-08-17 18:27:48 +10:00
parent 29a364865d
commit 36ede1b27d
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
10 changed files with 186 additions and 72 deletions

View File

@ -49,7 +49,7 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
public BlockMaterial getMaterial(BlockType blockType) {
Material type = BukkitAdapter.adapt(blockType);
if (type == null) {
type = Material.AIR;
return new PassthroughBlockMaterial(null);
}
return materialMap.computeIfAbsent(type, m -> new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), m));
}

View File

@ -123,6 +123,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
}
public WorldEditPlugin(JavaPluginLoader loader, PluginDescriptionFile desc, File dataFolder, File jarFile) {
super(loader, desc, dataFolder, jarFile);
init();
}

View File

@ -69,8 +69,13 @@ public abstract class FaweParser<T> extends InputParser<T> {
switch (c) {
case ',':
case '&':
inputs.add(toParse.substring(last, i));
and.add(c == '&');
String result = toParse.substring(last, i);
if (!result.isEmpty()) {
inputs.add(result);
and.add(c == '&');
} else {
throw new InputParseException("Invalid dangling character " + c);
}
last = i + 1;
continue outer;
default:

View File

@ -2519,6 +2519,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int makePumpkinPatches(final Vector position, final int apothem) {
return makePumpkinPatches(position, apothem, 0.02);
}
/**
* Makes pumpkin patches randomly in an area around the given position.
*
* @param position the base position
* @param apothem the apothem of the (square) area
* @return number of patches created
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int makePumpkinPatches(final Vector position, final int apothem, double density) {
// We want to generate pumpkins
final GardenPatchGenerator generator = new GardenPatchGenerator(EditSession.this);
generator.setPlant(GardenPatchGenerator.getPumpkinPattern());
@ -2526,7 +2538,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
// In a region of the given radius
final FlatRegion region = new CuboidRegion(EditSession.this.getWorld(), // Causes clamping of Y range
position.add(-apothem, -5, -apothem), position.add(apothem, 10, apothem));
final double density = 0.02;
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator);
final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground);

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.registry.state.PropertyGroup;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import jdk.nashorn.internal.ir.Block;
import java.util.EnumMap;
@ -45,8 +46,70 @@ public class BlockType {
return centralTopLimit(type.getDefaultState());
}
public static double centralBottomLimit(BlockStateHolder block) {
checkNotNull(block);
BlockTypes type = block.getBlockType();
switch (type) {
case CREEPER_WALL_HEAD:
case DRAGON_WALL_HEAD:
case PLAYER_WALL_HEAD:
case ZOMBIE_WALL_HEAD: return 0.25;
case ACACIA_SLAB:
case BIRCH_SLAB:
case BRICK_SLAB:
case COBBLESTONE_SLAB:
case DARK_OAK_SLAB:
case DARK_PRISMARINE_SLAB:
case JUNGLE_SLAB:
case NETHER_BRICK_SLAB:
case OAK_SLAB:
case PETRIFIED_OAK_SLAB:
case PRISMARINE_BRICK_SLAB:
case PRISMARINE_SLAB:
case PURPUR_SLAB:
case QUARTZ_SLAB:
case RED_SANDSTONE_SLAB:
case SANDSTONE_SLAB:
case SPRUCE_SLAB:
case STONE_BRICK_SLAB:
case STONE_SLAB: {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0;
switch (state) {
case "double":
case "bottom":
return 0;
case "top":
return 0.5;
}
}
case ACACIA_TRAPDOOR:
case BIRCH_TRAPDOOR:
case DARK_OAK_TRAPDOOR:
case IRON_TRAPDOOR:
case JUNGLE_TRAPDOOR:
case OAK_TRAPDOOR:
case SPRUCE_TRAPDOOR:
if (block.getState(PropertyKey.OPEN) == Boolean.TRUE) {
return 1;
} else if ("bottom".equals(block.getState(PropertyKey.HALF))) {
return 0.8125;
} else {
return 0;
}
case ACACIA_FENCE_GATE:
case BIRCH_FENCE_GATE:
case DARK_OAK_FENCE_GATE:
case JUNGLE_FENCE_GATE:
case OAK_FENCE_GATE:
case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 1 : 0;
default:
if (type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
/**
* TODO FIXME use registry
* Returns the y offset a player falls to when falling onto the top of a block at xp+0.5/zp+0.5.
*
* @param block the block
@ -54,7 +117,8 @@ public class BlockType {
*/
public static double centralTopLimit(BlockStateHolder block) {
checkNotNull(block);
switch (block.getBlockType().getTypeEnum()) {
BlockTypes type = block.getBlockType();
switch (type) {
case BLACK_BED:
case BLUE_BED:
case BROWN_BED:
@ -111,7 +175,17 @@ public class BlockType {
case SANDSTONE_SLAB:
case SPRUCE_SLAB:
case STONE_BRICK_SLAB:
case STONE_SLAB: return 0.5;
case STONE_SLAB: {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0.5;
switch (state) {
case "bottom":
return 0.5;
case "top":
case "double":
return 1;
}
}
case LILY_PAD: return 0.015625;
case REPEATER: return 0.125;
case SOUL_SAND: return 0.875;
@ -142,7 +216,12 @@ public class BlockType {
case OAK_FENCE_GATE:
case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 0 : 1.5;
default:
return PropertyGroup.LEVEL.get(block);
if (type.hasProperty(PropertyKey.LAYERS)) {
return PropertyGroup.LEVEL.get(block) * 0.0625;
}
if (!type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
}

View File

@ -284,20 +284,20 @@ public class GenerationCommands extends MethodCommands {
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException, ParameterException {
density = density / 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type);
player.print(affected + " trees created.");
player.print(BBC.getPrefix() + affected + " trees created.");
}
@Command(
aliases = {"pumpkins"},
usage = "[size]",
usage = "[size=10] [density=0.02]",
desc = "Generate pumpkin patches",
min = 0,
max = 1
max = 2
)
@CommandPermissions("worldedit.generation.pumpkins")
@Logging(POSITION)
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException, ParameterException {
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem);
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem, @Optional("0.02") double density) throws WorldEditException, ParameterException {
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem, density);
BBC.COMMAND_PUMPKIN.send(player, affected);
}

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.PlayerDirection;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -157,36 +158,47 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
final int z = pos.getBlockZ();
final Extent world = pos.getExtent();
byte free = 0;
byte spots = 0;
int maxY = world.getMaxY();
if (y >= maxY) return false;
while (y <= world.getMaximumPoint().getY() + 2) {
if (!world.getBlock(new Vector(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
++free;
} else {
free = 0;
}
BlockMaterial initialMaterial = world.getBlockType(new Vector(x, y, z)).getMaterial();
if (free == 2) {
++spots;
if (spots == 2) {
final Vector platform = new Vector(x, y - 2, z);
final BlockStateHolder block = world.getBlock(platform);
final com.sk89q.worldedit.world.block.BlockType type = block.getBlockType();
boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube();
// Don't get put in lava!
if (type == BlockTypes.LAVA) {
return false;
}
double height = 1.85;
double freeStart = -1;
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5));
return true;
for (int level = y + 1; level <= maxY + 2; level++) {
BlockState state;
if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState();
else state = world.getBlock(new Vector(x, level, z));
BlockTypes type = state.getBlockType();
BlockMaterial material = type.getMaterial();
if (!material.isFullCube() || !material.isMovementBlocker()) {
if (!lastState) {
lastState = BlockType.centralBottomLimit(state) != 1;
continue;
}
if (freeStart == -1) {
freeStart = level + BlockType.centralTopLimit(state);
} else {
double bottomLimit = BlockType.centralBottomLimit(state);
double space = level + bottomLimit - freeStart;
if (space >= height) {
setPosition(new Vector(x + 0.5, freeStart, z + 0.5));
return true;
}
// Not enough room, reset the free position
if (bottomLimit != 1) {
freeStart = -1;
}
}
} else {
freeStart = -1;
lastState = true;
}
++y;
}
return false;
}
@ -194,48 +206,52 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
public boolean descendLevel() {
final Location pos = getBlockIn();
final int x = pos.getBlockX();
int y = Math.max(0, pos.getBlockY() - 1);
int y = Math.max(0, pos.getBlockY());
final int z = pos.getBlockZ();
final Extent world = pos.getExtent();
byte free = 0;
BlockMaterial initialMaterial = world.getBlockType(new Vector(x, y, z)).getMaterial();
while (y >= 1) {
if (!world.getBlock(new Vector(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
++free;
} else {
free = 0;
}
boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube();
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 BlockStateHolder block = world.getBlock(platform);
final com.sk89q.worldedit.world.block.BlockTypes type = block.getBlockType();
double height = 1.85;
double freeEnd = -1;
// Don't want to end up in lava
switch (type) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
case LAVA:
--y;
continue;
default:
// Found a block!
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5));
return true;
int maxY = world.getMaxY();
if (y <= 2) return false;
for (int level = y + 1; level > 0; level--) {
BlockState state;
if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState();
else state = world.getBlock(new Vector(x, level, z));
BlockTypes type = state.getBlockType();
BlockMaterial material = type.getMaterial();
if (!material.isFullCube() || !material.isMovementBlocker()) {
if (!lastState) {
lastState = BlockType.centralTopLimit(state) != 0;
continue;
}
if (freeEnd == -1) {
freeEnd = level + BlockType.centralBottomLimit(state);
} else {
double topLimit = BlockType.centralTopLimit(state);
double freeStart = level + topLimit;
double space = freeEnd - freeStart;
if (space >= height) {
setPosition(new Vector(x + 0.5, freeStart, z + 0.5));
return true;
}
// Not enough room, reset the free position
if (topLimit != 0) {
freeEnd = -1;
}
}
return false;
} else {
lastState = true;
freeEnd = -1;
}
--y;
}
return false;
}

View File

@ -745,6 +745,7 @@ public enum BlockTypes implements BlockType {
try {
ReflectionUtils.setFailsafeFieldValue(BlockTypes.class.getDeclaredField("settings"), this, new Settings(this, id, internalId));
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@ -987,7 +988,8 @@ public enum BlockTypes implements BlockType {
try {
BlockStateHolder block = LegacyMapper.getInstance().getBlockFromLegacy(input);
if (block != null) return (BlockTypes) block.getBlockType();
} catch (NumberFormatException e) {}
} catch (NumberFormatException e) {
} catch (IndexOutOfBoundsException e) {}
return null;
}

View File

@ -144,9 +144,9 @@ public class BundledBlockData {
}
public static class BlockEntry {
private String id;
public String id;
public String localizedName;
private SimpleBlockMaterial material = new SimpleBlockMaterial();
public SimpleBlockMaterial material = new SimpleBlockMaterial();
}
}

View File

@ -21,7 +21,7 @@ package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.blocks.BlockMaterial;
class SimpleBlockMaterial implements BlockMaterial {
public class SimpleBlockMaterial implements BlockMaterial {
private boolean isAir;
private boolean fullCube;