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) { public BlockMaterial getMaterial(BlockType blockType) {
Material type = BukkitAdapter.adapt(blockType); Material type = BukkitAdapter.adapt(blockType);
if (type == null) { if (type == null) {
type = Material.AIR; return new PassthroughBlockMaterial(null);
} }
return materialMap.computeIfAbsent(type, m -> new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), m)); 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) { public WorldEditPlugin(JavaPluginLoader loader, PluginDescriptionFile desc, File dataFolder, File jarFile) {
super(loader, desc, dataFolder, jarFile);
init(); init();
} }

View File

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

View File

@ -2519,6 +2519,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
* @throws MaxChangedBlocksException thrown if too many blocks are changed * @throws MaxChangedBlocksException thrown if too many blocks are changed
*/ */
public int makePumpkinPatches(final Vector position, final int apothem) { 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 // We want to generate pumpkins
final GardenPatchGenerator generator = new GardenPatchGenerator(EditSession.this); final GardenPatchGenerator generator = new GardenPatchGenerator(EditSession.this);
generator.setPlant(GardenPatchGenerator.getPumpkinPattern()); generator.setPlant(GardenPatchGenerator.getPumpkinPattern());
@ -2526,7 +2538,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
// In a region of the given radius // In a region of the given radius
final FlatRegion region = new CuboidRegion(EditSession.this.getWorld(), // Causes clamping of Y range final FlatRegion region = new CuboidRegion(EditSession.this.getWorld(), // Causes clamping of Y range
position.add(-apothem, -5, -apothem), position.add(apothem, 10, apothem)); 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 GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator);
final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground); 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.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.Block;
import java.util.EnumMap; import java.util.EnumMap;
@ -45,8 +46,70 @@ public class BlockType {
return centralTopLimit(type.getDefaultState()); 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. * 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 * @param block the block
@ -54,7 +117,8 @@ public class BlockType {
*/ */
public static double centralTopLimit(BlockStateHolder block) { public static double centralTopLimit(BlockStateHolder block) {
checkNotNull(block); checkNotNull(block);
switch (block.getBlockType().getTypeEnum()) { BlockTypes type = block.getBlockType();
switch (type) {
case BLACK_BED: case BLACK_BED:
case BLUE_BED: case BLUE_BED:
case BROWN_BED: case BROWN_BED:
@ -111,7 +175,17 @@ public class BlockType {
case SANDSTONE_SLAB: case SANDSTONE_SLAB:
case SPRUCE_SLAB: case SPRUCE_SLAB:
case STONE_BRICK_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 LILY_PAD: return 0.015625;
case REPEATER: return 0.125; case REPEATER: return 0.125;
case SOUL_SAND: return 0.875; case SOUL_SAND: return 0.875;
@ -142,7 +216,12 @@ public class BlockType {
case OAK_FENCE_GATE: case OAK_FENCE_GATE:
case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 0 : 1.5; case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 0 : 1.5;
default: 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 { 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; density = density / 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type); int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type);
player.print(affected + " trees created."); player.print(BBC.getPrefix() + affected + " trees created.");
} }
@Command( @Command(
aliases = {"pumpkins"}, aliases = {"pumpkins"},
usage = "[size]", usage = "[size=10] [density=0.02]",
desc = "Generate pumpkin patches", desc = "Generate pumpkin patches",
min = 0, min = 0,
max = 1 max = 2
) )
@CommandPermissions("worldedit.generation.pumpkins") @CommandPermissions("worldedit.generation.pumpkins")
@Logging(POSITION) @Logging(POSITION)
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException, ParameterException { 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); int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem, density);
BBC.COMMAND_PUMPKIN.send(player, affected); 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.Vector;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.block.BlockStateHolder; 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 int z = pos.getBlockZ();
final Extent world = pos.getExtent(); final Extent world = pos.getExtent();
byte free = 0; int maxY = world.getMaxY();
byte spots = 0; if (y >= maxY) return false;
while (y <= world.getMaximumPoint().getY() + 2) { BlockMaterial initialMaterial = world.getBlockType(new Vector(x, y, z)).getMaterial();
if (!world.getBlock(new Vector(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
++free;
} else {
free = 0;
}
if (free == 2) { boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube();
++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();
// Don't get put in lava! double height = 1.85;
if (type == BlockTypes.LAVA) { double freeStart = -1;
return false;
}
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5)); for (int level = y + 1; level <= maxY + 2; level++) {
return true; 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; return false;
} }
@ -194,48 +206,52 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
public boolean descendLevel() { public boolean descendLevel() {
final Location pos = getBlockIn(); final Location pos = getBlockIn();
final int x = pos.getBlockX(); 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 int z = pos.getBlockZ();
final Extent world = pos.getExtent(); final Extent world = pos.getExtent();
byte free = 0; BlockMaterial initialMaterial = world.getBlockType(new Vector(x, y, z)).getMaterial();
while (y >= 1) { boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube();
if (!world.getBlock(new Vector(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
++free;
} else {
free = 0;
}
if (free == 2) { double height = 1.85;
// So we've found a spot, but we have to drop the player double freeEnd = -1;
// 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();
// Don't want to end up in lava int maxY = world.getMaxY();
switch (type) { if (y <= 2) return false;
case AIR:
case CAVE_AIR: for (int level = y + 1; level > 0; level--) {
case VOID_AIR: BlockState state;
case LAVA: if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState();
--y; else state = world.getBlock(new Vector(x, level, z));
continue; BlockTypes type = state.getBlockType();
default: BlockMaterial material = type.getMaterial();
// Found a block!
setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5)); if (!material.isFullCube() || !material.isMovementBlocker()) {
return true; 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; return false;
} }

View File

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

View File

@ -144,9 +144,9 @@ public class BundledBlockData {
} }
public static class BlockEntry { public static class BlockEntry {
private String id; public String id;
public String localizedName; 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; import com.sk89q.worldedit.blocks.BlockMaterial;
class SimpleBlockMaterial implements BlockMaterial { public class SimpleBlockMaterial implements BlockMaterial {
private boolean isAir; private boolean isAir;
private boolean fullCube; private boolean fullCube;