comments / minor compiling

This commit is contained in:
Jesse Boyd 2019-08-07 10:13:07 +10:00
parent 3c626ef25a
commit ee59dec3d8
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
12 changed files with 336 additions and 248 deletions

View File

@ -60,6 +60,7 @@ public final class FaweCache implements Trimable {
MUTABLE_VECTOR3.clean(); MUTABLE_VECTOR3.clean();
MUTABLE_BLOCKVECTOR3.clean(); MUTABLE_BLOCKVECTOR3.clean();
SECTION_BITS_TO_CHAR.clean();
return false; return false;
} }
@ -72,6 +73,14 @@ public final class FaweCache implements Trimable {
} }
}; };
public static final IterableThreadLocal<char[]> SECTION_BITS_TO_CHAR = new IterableThreadLocal<char[]>() {
@Override
public char[] init() {
char[] result = new char[4096];
return result;
}
};
public static final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<int[]>() { public static final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<int[]>() {
@Override @Override
public int[] init() { public int[] init() {

View File

@ -19,17 +19,30 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChu
/** /**
* Initialize at the location * Initialize at the location
* * (allows for reuse)
* - It's expected initialization will clear any set fields
* @param extent * @param extent
* @param x * @param x
* @param z * @param z
*/ */
void init(IQueueExtent extent, int x, int z); void init(IQueueExtent extent, int x, int z);
/**
* Get the queue
* @return
*/
IQueueExtent getQueue(); IQueueExtent getQueue();
/**
* Get chunkX
* @return
*/
int getX(); int getX();
/**
* Get chunkZ
* @return
*/
int getZ(); int getZ();
/** /**
@ -53,14 +66,14 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChu
* <p>The future returned may return another future. To ensure completion keep calling {@link * <p>The future returned may return another future. To ensure completion keep calling {@link
* Future#get()} on each result.</p> * Future#get()} on each result.</p>
* *
* @return Futures * @return Future
*/ */
@Override @Override
T call(); T call();
/** /**
* Call and join * Call and join
* * - Should be done async, if at all
* @throws ExecutionException * @throws ExecutionException
* @throws InterruptedException * @throws InterruptedException
*/ */
@ -73,7 +86,7 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChu
} }
/** /**
* Filter * Filter through all the blocks in the chunk
* *
* @param filter the filter * @param filter the filter
* @param block The filter block * @param block The filter block
@ -81,6 +94,13 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChu
*/ */
void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region); void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region);
/**
* Flood through all the blocks in the chunk
* TODO not implemented
* @param flood
* @param mask
* @param block
*/
void flood(Flood flood, FilterBlockMask mask, ChunkFilterBlock block); void flood(Flood flood, FilterBlockMask mask, ChunkFilterBlock block);
/* set - queues a change */ /* set - queues a change */
@ -100,6 +120,10 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChu
@Override @Override
CompoundTag getTag(int x, int y, int z); CompoundTag getTag(int x, int y, int z);
/**
* Reset (defaults to just calling init)
* @return
*/
@Override @Override
default IBlocks reset() { default IBlocks reset() {
init(getQueue(), getX(), getZ()); init(getQueue(), getX(), getZ());

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.beta;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.WorldChunkCache; import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
@ -23,6 +24,22 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
return true; return true;
} }
/**
* Clear any block updates
* @param players
*/
default void clearBlockUpdates(Player... players) {
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
}
/**
* Send all the chunks as block updates
* @param players
*/
default void sendBlockUpdates(Player... players) {
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
}
/** /**
* Must ensure that it is enqueued with QueueHandler * Must ensure that it is enqueued with QueueHandler
*/ */
@ -30,20 +47,33 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
void enableQueue(); void enableQueue();
/** /**
* Must ensure it is not in the queue handler * Must ensure it is not in the queue handler (i.e. does not change blocks in the world)
*/ */
@Override @Override
void disableQueue(); void disableQueue();
void init(WorldChunkCache world);
void init(WorldChunkCache world); // TODO NOT IMPLEMENTED replace with supplier
/** /**
* Get the {@link WorldChunkCache} * Get the cached get object
* * - Faster than getting it using NMS and allows for wrapping
* @param x
* @param z
* @param supplier
* @return * @return
*/ */
IChunkGet getCachedGet(int x, int z, Supplier<IChunkGet> supplier); IChunkGet getCachedGet(int x, int z, Supplier<IChunkGet> supplier);
/**
* Get the cached chunk set object
* @param x
* @param z
* @param supplier
* @return
*/
IChunkSet getCachedSet(int x, int z, Supplier<IChunkSet> supplier);
/** /**
* Get the IChunk at a position (and cache it if it's not already) * Get the IChunk at a position (and cache it if it's not already)
* *
@ -61,6 +91,8 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
*/ */
<T extends Future<T>> T submit(IChunk<T> chunk); <T extends Future<T>> T submit(IChunk<T> chunk);
// standard get / set
@Override @Override
default boolean setBlock(int x, int y, int z, BlockStateHolder state) { default boolean setBlock(int x, int y, int z, BlockStateHolder state) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
@ -126,11 +158,31 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
@Override @Override
void flush(); void flush();
/**
* A filter block is used to iterate over blocks / positions
* - Essentially combines BlockVector3, Extent and BlockState functions in a way that avoids lookups
* @return
*/
ChunkFilterBlock initFilterBlock(); ChunkFilterBlock initFilterBlock();
/**
* Number of chunks in queue
* @return
*/
int size(); int size();
/**
* @return If queue is empty
*/
boolean isEmpty(); boolean isEmpty();
/**
* Refresh a specific chunk with a bitMask (0 = default, 65535 = all block sections)
* Note: only 0 is guaranteed to send all tiles / entities
* Note: Only 65535 is guaranteed to send all blocks
* @param chunkX
* @param chunkZ
* @param bitMask
*/
void sendChunk(int chunkX, int chunkZ, int bitMask); void sendChunk(int chunkX, int chunkZ, int bitMask);
} }

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.beta.implementation.blocks; package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkSet; import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.object.collection.MemBlockSet; import com.boydti.fawe.object.collection.MemBlockSet;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
@ -59,7 +60,8 @@ public class BitSetBlocks implements IChunkSet {
@Override @Override
public char[] getArray(int layer) { public char[] getArray(int layer) {
char[] arr = FaweCache.SECTION_BITS_TO_CHAR.get();
} }
@Override @Override

View File

@ -22,7 +22,7 @@ import javax.annotation.Nullable;
/** /**
* An abstract {@link IChunk} class that implements basic get/set blocks * An abstract {@link IChunk} class that implements basic get/set blocks
*/ */
public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> { public abstract class ChunkHolder implements IChunk {
public static final IBlockDelegate BOTH = new IBlockDelegate() { public static final IBlockDelegate BOTH = new IBlockDelegate() {
@Override @Override
@ -242,27 +242,61 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
return set == null || set.isEmpty(); return set == null || set.isEmpty();
} }
/**
* Get or create the settable part of this chunk
* @return
*/
public final IChunkGet getOrCreateGet() { public final IChunkGet getOrCreateGet() {
if (get == null) { if (get == null) {
get = newGet(); get = newWrappedGet();
} }
return get; return get;
} }
/**
* Get or create the settable part of this chunk
* @return
*/
public final IChunkSet getOrCreateSet() { public final IChunkSet getOrCreateSet() {
if (set == null) { if (set == null) {
set = set(); set = newWrappedSet();
} }
return set; return set;
} }
public IChunkSet set() { /**
* Create the settable part of this chunk (defaults to a char array)
* @return
*/
public IChunkSet createSet() {
return new CharSetBlocks(); return new CharSetBlocks();
} }
private IChunkGet newGet() { /**
* Create a wrapped set object
* - The purpose of wrapping is to allow different extents to intercept / alter behavior
* - E.g. caching, optimizations, filtering
* @return
*/
private IChunkSet newWrappedSet() {
if (extent instanceof SingleThreadQueueExtent) { if (extent instanceof SingleThreadQueueExtent) {
IChunkGet newGet = extent.getCachedGet(chunkX, chunkZ, this); IChunkSet newSet = extent.getCachedSet(chunkX, chunkZ, this::createSet);
if (newSet != null) {
return newSet;
}
}
return createSet();
}
/**
* Create a wrapped get object
* - The purpose of wrapping is to allow different extents to intercept / alter behavior
* - E.g. caching, optimizations, filtering
* @return
*/
private IChunkGet newWrappedGet() {
if (extent instanceof SingleThreadQueueExtent) {
IChunkGet newGet = extent.getCachedGet(chunkX, chunkZ, this::get);
if (newGet != null) { if (newGet != null) {
return newGet; return newGet;
} }
@ -270,6 +304,8 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
return get(); return get();
} }
public abstract IChunkGet get();
@Override @Override
public void init(IQueueExtent extent, int chunkX, int chunkZ) { public void init(IQueueExtent extent, int chunkX, int chunkZ) {
this.extent = extent; this.extent = extent;

View File

@ -12,17 +12,15 @@ import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.*; import java.util.*;
public abstract class FaweParser<T> extends InputParser<T> { public abstract class FaweParser<T> extends InputParser<T> {
private final PlatformCommandManager platform;
private final Class<T> type; private final Class<T> type;
protected FaweParser(WorldEdit worldEdit, PlatformCommandManager commandManager, Class<T> type) { protected FaweParser(WorldEdit worldEdit, Class<T> type) {
super(worldEdit); super(worldEdit);
this.platform = commandManager;
this.type = type; this.type = type;
} }
public PlatformCommandManager getPlatform() { public PlatformCommandManager getPlatform() {
return platform; return PlatformCommandManager.getInstance();
} }
public Class<T> getType() { public Class<T> getType() {

View File

@ -15,7 +15,6 @@ import java.util.concurrent.Future;
* - Using a non transparent block can cause FPS lag * - Using a non transparent block can cause FPS lag
*/ */
public class VisualChunk extends ChunkHolder { public class VisualChunk extends ChunkHolder {
public static BlockState VISUALIZE_BLOCK = BlockTypes.BLACK_STAINED_GLASS.getDefaultState();
private final IChunk parent; private final IChunk parent;
private final VisualExtent extent; private final VisualExtent extent;
@ -42,7 +41,7 @@ public class VisualChunk extends ChunkHolder {
} }
@Override @Override
public IChunkSet set() { public IChunkSet createSet() {
return new BitSetBlocks(VISUALIZE_BLOCK); return new BitSetBlocks(VISUALIZE_BLOCK);
} }
} }

View File

@ -5,30 +5,38 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.extent.PassthroughExtent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import javax.annotation.Nullable;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public class VisualExtent extends AbstractDelegateExtent { public class VisualExtent extends AbstractDelegateExtent {
public static final BlockType VISUALIZE_BLOCK_DEFAULT = BlockTypes.BLACK_STAINED_GLASS;
private final BlockType visualizeBlock;
private final Player player;
private final IQueueExtent queue; public VisualExtent(IQueueExtent parent, Player player) {
private Long2ObjectMap<VisualChunk> chunks = new Long2ObjectOpenHashMap<>(); this(parent, player, VISUALIZE_BLOCK_DEFAULT);
public VisualExtent(Extent parent, IQueueExtent queue) {
super(parent);
this.queue = queue;
} }
public VisualChunk getChunk(int cx, int cz) { public VisualExtent(IQueueExtent parent, Player player, BlockType visualizeBlock) {
return chunks.get(MathMan.pairInt(cx, cz)); super(parent);
this.visualizeBlock = visualizeBlock;
this.player = player;
} }
@Override @Override
@ -38,68 +46,30 @@ public class VisualExtent extends AbstractDelegateExtent {
@Override @Override
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException { public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
BlockStateHolder previous = super.getBlock(x, y, z); if (block.getMaterial().isAir()) {
int cx = x >> 4; return super.setBlock(x, y, z, block);
int cz = z >> 4;
long chunkPair = MathMan.pairInt(cx, cz);
VisualChunk chunk = chunks.get(chunkPair);
if (previous.equals(block)) {
if (chunk != null) {
chunk.unset(x, y, z);
}
return false;
} else { } else {
if (chunk == null) { return super.setBlock(x, y, z, visualizeBlock.getDefaultState());
chunk = new VisualChunk(cx, cz);
chunks.put(chunkPair, chunk);
}
chunk.setBlock(x, y, z, block.getInternalId());
return true;
} }
} }
@Nullable
@Override
public Operation commit() {
IQueueExtent queue = (IQueueExtent) getExtent();
queue.sendBlockUpdates(this.player);
return null;
}
@Override @Override
public boolean setBiome(BlockVector2 position, BiomeType biome) { public boolean setBiome(BlockVector2 position, BiomeType biome) {
// Do nothing // Do nothing
return false; return false;
} }
public void clear(VisualExtent other, FawePlayer... players) { public void clear() {
for (Long2ObjectMap.Entry<VisualChunk> entry : chunks.long2ObjectEntrySet()) { IQueueExtent queue = (IQueueExtent) getExtent();
long pair = entry.getLongKey(); queue.clearBlockUpdates(player);
int cx = MathMan.unpairIntX(pair); queue.cancel();
int cz = MathMan.unpairIntY(pair);
VisualChunk chunk = entry.getValue();
final VisualChunk otherChunk = other != null ? other.getChunk(cx, cz) : null;
final IntFaweChunk newChunk = new NullQueueIntFaweChunk(cx, cz);
final int bx = cx << 4;
final int bz = cz << 4;
if (otherChunk == null) {
chunk.forEachQueuedBlock((localX, y, localZ, combined) -> {
combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0);
newChunk.setBlock(localX, y, localZ, combined);
});
} else {
chunk.forEachQueuedBlock((localX, y, localZ, combined) -> {
if (combined != otherChunk.getBlockCombinedId(localX, y, localZ)) {
combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0);
newChunk.setBlock(localX, y, localZ, combined);
}
});
}
if (newChunk.getTotalCount() != 0) {
queue.sendBlockUpdate(newChunk, players);
}
}
} }
}
public void visualize(FawePlayer players) {
for (VisualChunk chunk : chunks.values()) {
queue.sendBlockUpdate(chunk, players);
}
}
public Future sendChunkUpdate(VisualChunk visualChunk) {
return null; // TODO NOT IMPLEMENTED
}
}

View File

@ -652,14 +652,13 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
.changeSetNull() .changeSetNull()
.combineStages(false); .combineStages(false);
EditSession editSession = builder.build(); EditSession editSession = builder.build();
VisualExtent newVisualExtent = new VisualExtent(editSession, player);
VisualExtent newVisualExtent = new VisualExtent(builder.getExtent(), builder.getQueue());
BlockVector3 position = getPosition(editSession, player); BlockVector3 position = getPosition(editSession, player);
if (position != null) { if (position != null) {
editSession.setExtent(newVisualExtent); editSession.setExtent(newVisualExtent);
switch (mode) { switch (mode) {
case POINT: case POINT:
editSession.setBlock(position, VisualChunk.VISUALIZE_BLOCK); editSession.setBlock(position, VisualExtent.VISUALIZE_BLOCK_DEFAULT);
break; break;
case OUTLINE: { case OUTLINE: {
new PatternTraverser(current).reset(editSession); new PatternTraverser(current).reset(editSession);
@ -670,7 +669,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
} }
if (visualExtent != null) { if (visualExtent != null) {
// clear old data // clear old data
visualExtent.clear(newVisualExtent, fp); visualExtent.clear(newVisualExtent, player);
} }
visualExtent = newVisualExtent; visualExtent = newVisualExtent;
newVisualExtent.visualize(fp); newVisualExtent.visualize(fp);

View File

@ -1,11 +1,13 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.command.FaweParser; import com.boydti.fawe.command.FaweParser;
import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.object.extent.MultiTransform; import com.boydti.fawe.object.extent.MultiTransform;
import com.boydti.fawe.object.extent.RandomTransform; import com.boydti.fawe.object.extent.RandomTransform;
import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.object.random.TrueRandom; import com.boydti.fawe.object.random.TrueRandom;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.google.common.collect.Iterables;
import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.TransformCommands; import com.sk89q.worldedit.command.TransformCommands;
@ -22,16 +24,7 @@ import java.util.Map;
public class DefaultTransformParser extends FaweParser<ResettableExtent> { public class DefaultTransformParser extends FaweParser<ResettableExtent> {
public DefaultTransformParser(WorldEdit worldEdit) { public DefaultTransformParser(WorldEdit worldEdit) {
super(worldEdit); super(worldEdit, ResettableExtent.class);
this.register(new TransformCommands());
}
public void register(Object clazz) {
ParametricBuilder builder = new ParametricBuilder();
builder.setAuthorizer(new ActorAuthorizer());
builder.addBinding(new WorldEditBinding(worldEdit));
builder.registerMethodsAsCommands(dispatcher, clazz);
} }
@Override @Override
@ -57,49 +50,54 @@ public class DefaultTransformParser extends FaweParser<ResettableExtent> {
double chance = 1; double chance = 1;
if (command.isEmpty()) { if (command.isEmpty()) {
transform = parseFromInput(StringMan.join(entry.getValue(), ','), context); transform = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else if (dispatcher.get(command) == null) {
// Legacy syntax
int percentIndex = command.indexOf('%');
if (percentIndex != -1) { // Legacy percent pattern
chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
command = command.substring(percentIndex + 1);
if (!entry.getValue().isEmpty()) {
if (!command.isEmpty()) command += " ";
command += StringMan.join(entry.getValue(), " ");
}
transform = parseFromInput(command, context);
} else {
throw new NoMatchException("See: //transforms");
}
} else { } else {
List<String> args = entry.getValue(); List<String> args = entry.getValue();
if (!args.isEmpty()) { String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
command += " " + StringMan.join(args, " "); try {
transform = Iterables.getFirst(parse(cmdArgs, actor), null);
} catch (SuggestInputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
throw new NoMatchException("See: //transforms");
} }
transform = (ResettableExtent) dispatcher.call(command, locals, new String[0]); if (transform == null) {
} // Legacy syntax
if (pe.and) { // & int percentIndex = command.indexOf('%');
intersectionChances.add(chance); if (percentIndex != -1) { // Legacy percent pattern
intersection.add(transform); chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
} else { command = command.substring(percentIndex + 1);
if (!intersection.isEmpty()) { if (!entry.getValue().isEmpty()) {
if (intersection.size() == 1) { if (!command.isEmpty()) command += " ";
throw new InputParseException("Error, floating &"); command += StringMan.join(entry.getValue(), " ");
}
transform = parseFromInput(command, context);
} else {
throw new NoMatchException("See: //transforms");
} }
MultiTransform multi = new MultiTransform();
double total = 0;
for (int i = 0; i < intersection.size(); i++) {
Double value = intersectionChances.get(i);
total += value;
multi.add(intersection.get(i), value);
}
union.add(multi);
unionChances.add(total);
intersection.clear();
intersectionChances.clear();
} }
unionChances.add(chance); if (pe.and) { // &
union.add(transform); intersectionChances.add(chance);
intersection.add(transform);
} else {
if (!intersection.isEmpty()) {
if (intersection.size() == 1) {
throw new InputParseException("Error, floating &");
}
MultiTransform multi = new MultiTransform();
double total = 0;
for (int i = 0; i < intersection.size(); i++) {
Double value = intersectionChances.get(i);
total += value;
multi.add(intersection.get(i), value);
}
union.add(multi);
unionChances.add(total);
intersection.clear();
intersectionChances.clear();
}
unionChances.add(chance);
union.add(transform);
}
} }
} }
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -48,8 +48,8 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class DefaultMaskParser extends FaweParser<Mask> { public class DefaultMaskParser extends FaweParser<Mask> {
public DefaultMaskParser(WorldEdit worldEdit, PlatformCommandManager manager) { public DefaultMaskParser(WorldEdit worldEdit) {
super(worldEdit, manager, Mask.class); super(worldEdit, Mask.class);
} }
@Override @Override
@ -73,12 +73,40 @@ public class DefaultMaskParser extends FaweParser<Mask> {
ParseEntry pe = entry.getKey(); ParseEntry pe = entry.getKey();
final String command = pe.input; final String command = pe.input;
String full = pe.full; String full = pe.full;
Mask mask; Mask mask = null;
if (command.isEmpty()) { if (command.isEmpty()) {
mask = parseFromInput(StringMan.join(entry.getValue(), ','), context); mask = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else { } else {
mask = Iterables.getFirst(parse(input, actor), null); List<String> args = entry.getValue();
SuggestInputParseException suggestion = null; // TODO NOT IMPLEMENTED suggestion String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
try {
mask = Iterables.getFirst(parse(cmdArgs, actor), null);
} catch (SuggestInputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
// TODO NOT IMPLEMENTED
// throw SuggestInputParseException.of(e, full, () -> {
// try {
// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
// if (suggestions.size() <= 2) {
// for (int i = 0; i < suggestions.size(); i++) {
// String suggestion = suggestions.get(i);
// if (suggestion.indexOf(' ') != 0) {
// String[] split = suggestion.split(" ");
// suggestion = "[" + StringMan.join(split, "][") + "]";
// suggestions.set(i, suggestion);
// }
// }
// }
// return suggestions;
// } catch (CommandException e1) {
// throw new InputParseException(e1.getMessage());
// } catch (Throwable e2) {
// e2.printStackTrace();
// throw new InputParseException(e2.getMessage());
// }
// });
}
if (mask == null) { if (mask == null) {
// Legacy patterns // Legacy patterns
char char0 = command.charAt(0); char char0 = command.charAt(0);
@ -87,7 +115,7 @@ public class DefaultMaskParser extends FaweParser<Mask> {
return parseFromInput(char0 + "[" + input.substring(1) + "]", context); return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
} }
if (char0 == '#' || char0 == '?') { if (char0 == '#' || char0 == '?') {
throw suggestion; // TODO NOT IMPLEMENTED
// throw new SuggestInputParseException(new NoMatchException("Unknown mask: " + full + ", See: //masks"), full, // throw new SuggestInputParseException(new NoMatchException("Unknown mask: " + full + ", See: //masks"), full,
// () -> { // () -> {
// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases()); // if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
@ -150,37 +178,6 @@ public class DefaultMaskParser extends FaweParser<Mask> {
} }
} }
} }
// else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// mask = (Mask) dispatcher.call(command + cmdArgs, locals, new String[0]);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// throw SuggestInputParseException.of(e, full, () -> {
// try {
// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
// if (suggestions.size() <= 2) {
// for (int i = 0; i < suggestions.size(); i++) {
// String suggestion = suggestions.get(i);
// if (suggestion.indexOf(' ') != 0) {
// String[] split = suggestion.split(" ");
// suggestion = "[" + StringMan.join(split, "][") + "]";
// suggestions.set(i, suggestion);
// }
// }
// }
// return suggestions;
// } catch (CommandException e1) {
// throw new InputParseException(e1.getMessage());
// } catch (Throwable e2) {
// e2.printStackTrace();
// throw new InputParseException(e2.getMessage());
// }
// });
// }
// }
if (pe.and) { if (pe.and) {
masks.add(new ArrayList<>()); masks.add(new ArrayList<>());
} }

View File

@ -24,6 +24,7 @@ import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.random.TrueRandom; import com.boydti.fawe.object.random.TrueRandom;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.google.common.collect.Iterables;
import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
@ -47,8 +48,8 @@ import java.util.stream.Stream;
public class DefaultPatternParser extends FaweParser<Pattern> { public class DefaultPatternParser extends FaweParser<Pattern> {
public DefaultPatternParser(WorldEdit worldEdit, PlatformCommandManager commandManager) { public DefaultPatternParser(WorldEdit worldEdit) {
super(worldEdit, commandManager, Pattern.class); super(worldEdit, Pattern.class);
} }
@Override @Override
@ -72,90 +73,93 @@ public class DefaultPatternParser extends FaweParser<Pattern> {
double chance = 1; double chance = 1;
if (command.isEmpty()) { if (command.isEmpty()) {
pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context); pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else if (dispatcher.get(command) == null) {
// Legacy patterns
char char0 = command.charAt(0);
boolean charMask = input.length() > 1 && input.charAt(1) != '[';
if (charMask && input.charAt(0) == '=') {
return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
}
if (char0 == '#') {
throw new SuggestInputParseException(new NoMatchException("Unknown pattern: " + full + ", See: //patterns"), full,
() -> {
if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
return dispatcher.getAliases().stream().filter(
s -> s.startsWith(command.toLowerCase(Locale.ROOT))
).collect(Collectors.toList());
}
);
}
if (charMask) {
if (char0 == '$') {
String value = command.substring(1) + ((entry.getValue().isEmpty()) ? ""
: "[" + StringMan.join(entry.getValue(), "][") + "]");
if (value.contains(":")) {
if (value.charAt(0) == ':') {
value.replaceFirst(":", "");
}
value = value.replaceAll(":", "][");
}
pattern = parseFromInput(char0 + "[" + value + "]", context);
}
}
if (pattern == null) {
if (command.startsWith("[")) {
int end = command.lastIndexOf(']');
pattern = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
} else {
int percentIndex = command.indexOf('%');
if (percentIndex != -1) { // Legacy percent pattern
chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
String value = command.substring(percentIndex + 1);
if (!entry.getValue().isEmpty()) {
if (!value.isEmpty()) value += " ";
value += StringMan.join(entry.getValue(), " ");
}
pattern = parseFromInput(value, context);
} else { // legacy block pattern
try {
pattern = worldEdit.getBlockFactory().parseFromInput(pe.full, context);
} catch (NoMatchException e) {
throw new NoMatchException(e.getMessage() + " See: //patterns");
}
}
}
}
} else { } else {
List<String> args = entry.getValue(); List<String> args = entry.getValue();
String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " ")); String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
try { try {
pattern = (Pattern) dispatcher.call(command + cmdArgs, locals, new String[0]); pattern = Iterables.getFirst(parse(cmdArgs, actor), null);
} catch (SuggestInputParseException rethrow) { } catch (SuggestInputParseException rethrow) {
throw rethrow; throw rethrow;
} catch (Throwable e) { } catch (Throwable e) {
throw SuggestInputParseException.of(e, full, () -> { // TODO NOT IMPLEMENTED
try { // throw SuggestInputParseException.of(e, full, () -> {
List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals); // try {
if (suggestions.size() <= 2) { // List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
for (int i = 0; i < suggestions.size(); i++) { // if (suggestions.size() <= 2) {
String suggestion = suggestions.get(i); // for (int i = 0; i < suggestions.size(); i++) {
if (suggestion.indexOf(' ') != 0) { // String suggestion = suggestions.get(i);
String[] split = suggestion.split(" "); // if (suggestion.indexOf(' ') != 0) {
suggestion = "[" + StringMan.join(split, "][") + "]"; // String[] split = suggestion.split(" ");
suggestions.set(i, suggestion); // suggestion = "[" + StringMan.join(split, "][") + "]";
} // suggestions.set(i, suggestion);
// }
// }
// }
// return suggestions;
// } catch (CommandException e1) {
// throw new InputParseException(e1.getMessage());
// } catch (Throwable e2) {
// e2.printStackTrace();
// throw new InputParseException(e2.getMessage());
// }
// });
}
if (pattern == null) {
// Legacy patterns
char char0 = command.charAt(0);
boolean charMask = input.length() > 1 && input.charAt(1) != '[';
if (charMask && input.charAt(0) == '=') {
return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
}
if (char0 == '#') {
// TODO NOT IMPLEMENTED
// throw new SuggestInputParseException(new NoMatchException("Unknown pattern: " + full + ", See: //patterns"), full,
// () -> {
// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
// return dispatcher.getAliases().stream().filter(
// s -> s.startsWith(command.toLowerCase(Locale.ROOT))
// ).collect(Collectors.toList());
// }
// );
}
if (charMask) {
if (char0 == '$') {
String value = command.substring(1) + ((entry.getValue().isEmpty()) ? ""
: "[" + StringMan.join(entry.getValue(), "][") + "]");
if (value.contains(":")) {
if (value.charAt(0) == ':') {
value.replaceFirst(":", "");
}
value = value.replaceAll(":", "][");
}
pattern = parseFromInput(char0 + "[" + value + "]", context);
}
}
if (pattern == null) {
if (command.startsWith("[")) {
int end = command.lastIndexOf(']');
pattern = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
} else {
int percentIndex = command.indexOf('%');
if (percentIndex != -1) { // Legacy percent pattern
chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
String value = command.substring(percentIndex + 1);
if (!entry.getValue().isEmpty()) {
if (!value.isEmpty()) value += " ";
value += StringMan.join(entry.getValue(), " ");
}
pattern = parseFromInput(value, context);
} else { // legacy block pattern
try {
pattern = worldEdit.getBlockFactory().parseFromInput(pe.full, context);
} catch (NoMatchException e) {
throw new NoMatchException(e.getMessage() + " See: //patterns");
} }
} }
return suggestions;
} catch (CommandException e1) {
throw new InputParseException(e1.getMessage());
} catch (Throwable e2) {
e2.printStackTrace();
throw new InputParseException(e2.getMessage());
} }
}); }
} }
} }
if (pattern != null) { if (pattern != null) {