mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
Refactor + Fixes #300
This commit is contained in:
parent
326dcab1f1
commit
07f4f61cc2
@ -46,15 +46,6 @@ subprojects {
|
||||
sourceCompatibility = 1.7
|
||||
targetCompatibility = 1.7
|
||||
|
||||
dependencies {
|
||||
compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') {
|
||||
exclude(module: 'bukkit-classloader-check')
|
||||
}
|
||||
compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT'
|
||||
compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
|
||||
compile 'org.primesoft:BlocksHub:2.0'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {url "http://ci.regularbox.com/plugin/repository/everything/"}
|
||||
|
@ -1,5 +1,6 @@
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10'
|
||||
compile 'net.milkbowl.vault:VaultAPI:1.5'
|
||||
compile 'com.massivecraft:factions:2.8.0'
|
||||
compile 'com.drtshock:factions:1.6.9.5'
|
||||
@ -12,6 +13,7 @@ dependencies {
|
||||
compile 'com.palmergames.bukkit:towny:0.84.0.9'
|
||||
compile 'com.worldcretornica:plotme_core:0.16.3'
|
||||
compile 'junit:junit:4.11'
|
||||
compile 'com.sk89q.worldedit:worldedit-bukkit:6.1.1-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-bukkit:6.1.4-SNAPSHOT'
|
||||
compile 'com.sk89q.worldedit:worldedit-core:6.1.4-SNAPSHOT'
|
||||
compile 'com.thevoxelbox.voxelsniper:voxelsniper:5.171.0'
|
||||
}
|
@ -22,6 +22,7 @@ import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.bukkit.EditSessionBlockChangeDelegate;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
@ -78,6 +79,8 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
new ChunkListener();
|
||||
}
|
||||
});
|
||||
// Inject
|
||||
EditSessionBlockChangeDelegate.inject();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,6 +24,7 @@ import org.bukkit.Difficulty;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.World;
|
||||
@ -33,7 +34,6 @@ import org.bukkit.WorldType;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.CreatureType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
@ -63,6 +63,11 @@ public class AsyncWorld implements World {
|
||||
private FaweQueue queue;
|
||||
private BukkitImplAdapter adapter;
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double v, double v1, double v2, int i, double v3, double v4, double v5, double v6, T t) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i, v3, v4, v5, v6, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #wrap(org.bukkit.World)} instead
|
||||
* @param parent Parent world
|
||||
@ -158,6 +163,61 @@ public class AsyncWorld implements World {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int i) {
|
||||
parent.spawnParticle(particle, location, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double v, double v1, double v2, int i) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int i, T t) {
|
||||
parent.spawnParticle(particle, location, i, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double v, double v1, double v2, int i, T t) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int i, double v, double v1, double v2) {
|
||||
parent.spawnParticle(particle, location, i, v, v1, v2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double v, double v1, double v2, int i, double v3, double v4, double v5) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i, v3, v4, v5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int i, double v, double v1, double v2, T t) {
|
||||
parent.spawnParticle(particle, location, i, v, v1, v2, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double v, double v1, double v2, int i, double v3, double v4, double v5, T t) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i, v3, v4, v5, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int i, double v, double v1, double v2, double v3) {
|
||||
parent.spawnParticle(particle, location, i, v, v1, v2, v3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double v, double v1, double v2, int i, double v3, double v4, double v5, double v6) {
|
||||
parent.spawnParticle(particle, v, v1, v2, i, v3, v4, v5, v6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int i, double v, double v1, double v2, double v3, T t) {
|
||||
parent.spawnParticle(particle, location, i, v, v1, v2, v3, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlockAt(final int x, final int y, final int z) {
|
||||
return new AsyncBlock(this, queue, x, y, z);
|
||||
@ -315,6 +375,7 @@ public class AsyncWorld implements World {
|
||||
return unloadChunk(x, z, save, false);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean unloadChunk(final int x, final int z, final boolean save, final boolean safe) {
|
||||
if (isChunkLoaded(x, z)) {
|
||||
@ -385,6 +446,11 @@ public class AsyncWorld implements World {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Arrow> T spawnArrow(Location location, Vector vector, float v, float v1, Class<T> aClass) {
|
||||
return parent.spawnArrow(location, vector, v, v1, aClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(final Location location, final TreeType type) {
|
||||
return TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||
@ -410,18 +476,6 @@ public class AsyncWorld implements World {
|
||||
return spawn(loc, type.getEntityClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public LivingEntity spawnCreature(Location loc, EntityType type) {
|
||||
return (LivingEntity)this.spawnEntity(loc, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public LivingEntity spawnCreature(Location loc, CreatureType type) {
|
||||
return this.spawnCreature(loc, type.toEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightningStrike strikeLightning(final Location loc) {
|
||||
return TaskManager.IMP.sync(new RunnableVal<LightningStrike>() {
|
||||
@ -896,6 +950,16 @@ public class AsyncWorld implements World {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(final Location location, final String sound, final float volume, final float pitch) {
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
parent.playSound(location, sound, volume, pitch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGameRules() {
|
||||
return parent.getGameRules();
|
||||
@ -917,8 +981,18 @@ public class AsyncWorld implements World {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetadata(String key, MetadataValue value) {
|
||||
parent.setMetadata(key, value);
|
||||
public Spigot spigot() {
|
||||
return parent.spigot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetadata(final String key, final MetadataValue meta) {
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
parent.setMetadata(key, meta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -932,8 +1006,13 @@ public class AsyncWorld implements World {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMetadata(String key, Plugin plugin) {
|
||||
parent.removeMetadata(key, plugin);
|
||||
public void removeMetadata(final String key, final Plugin plugin) {
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
parent.removeMetadata(key, plugin);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.bukkit;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import org.bukkit.BlockChangeDelegate;
|
||||
|
||||
/**
|
||||
* Proxy class to catch calls to set blocks.
|
||||
*/
|
||||
public class EditSessionBlockChangeDelegate implements BlockChangeDelegate {
|
||||
|
||||
private EditSession editSession;
|
||||
|
||||
public EditSessionBlockChangeDelegate(EditSession editSession) {
|
||||
this.editSession = editSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRawTypeId(int x, int y, int z, int typeId) {
|
||||
return editSession.setBlock(x, y, z, FaweCache.getBlock(typeId, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRawTypeIdAndData(int x, int y, int z, int typeId, int data) {
|
||||
return editSession.setBlock(x, y, z, FaweCache.getBlock(typeId, data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTypeId(int x, int y, int z, int typeId) {
|
||||
return setRawTypeId(x, y, z, typeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTypeIdAndData(int x, int y, int z, int typeId, int data) {
|
||||
return setRawTypeIdAndData(x, y, z, typeId, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTypeId(int x, int y, int z) {
|
||||
return editSession.getBlock(x, y, z).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return editSession.getMaxY() + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(int x, int y, int z) {
|
||||
return editSession.getBlock(x, y, z).getId() == BlockID.AIR;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return EditSessionBlockChangeDelegate.class;
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
dependencies {
|
||||
compile project(':bukkit0')
|
||||
compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -3,6 +3,12 @@ dependencies {
|
||||
compile 'org.yaml:snakeyaml:1.16'
|
||||
compile 'com.google.code.gson:gson:2.2.4'
|
||||
compile 'net.fabiozumbi12:redprotect:1.9.6'
|
||||
compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT'
|
||||
compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
|
||||
compile 'org.primesoft:BlocksHub:2.0'
|
||||
compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') {
|
||||
exclude(module: 'bukkit-classloader-check')
|
||||
}
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
|
@ -46,8 +46,13 @@ import com.sk89q.worldedit.extent.clipboard.io.SchematicReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.SchematicWriter;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.FuzzyBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
||||
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
||||
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
@ -368,6 +373,12 @@ public class Fawe {
|
||||
Vector.inject(); // Optimizations
|
||||
// Pattern
|
||||
Patterns.inject(); // Optimizations (reduce object creation)
|
||||
RandomPattern.inject(); // Optimizations
|
||||
ClipboardPattern.inject(); // Optimizations
|
||||
// Mask
|
||||
BlockMask.inject(); // Optimizations
|
||||
SolidBlockMask.inject(); // Optimizations
|
||||
FuzzyBlockMask.inject(); // Optimizations
|
||||
// Operations
|
||||
Operations.inject(); // Optimizations
|
||||
// BlockData
|
||||
|
@ -407,7 +407,7 @@ public class FaweAPI {
|
||||
NMSRelighter relighter = new NMSRelighter(nmsQueue);
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z ++) {
|
||||
relighter.addChunk(x, z, null);
|
||||
relighter.addChunk(x, z, null, 65536);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class FaweCache {
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static BaseBlock getBlock(int id, int data) {
|
||||
public static final BaseBlock getBlock(int id, int data) {
|
||||
return CACHE_BLOCK[(id << 4) + data];
|
||||
}
|
||||
|
||||
@ -89,15 +89,15 @@ public class FaweCache {
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static int getCombined(int id, int data) {
|
||||
public static final int getCombined(int id, int data) {
|
||||
return (id << 4) + data;
|
||||
}
|
||||
|
||||
public static int getId(int combined) {
|
||||
public static final int getId(int combined) {
|
||||
return combined >> 4;
|
||||
}
|
||||
|
||||
public static int getData(int combined) {
|
||||
public static final int getData(int combined) {
|
||||
return combined & 15;
|
||||
}
|
||||
|
||||
@ -106,11 +106,11 @@ public class FaweCache {
|
||||
* @param block
|
||||
* @return
|
||||
*/
|
||||
public static int getCombined(BaseBlock block) {
|
||||
public static final int getCombined(BaseBlock block) {
|
||||
return getCombined(block.getId(), block.getData());
|
||||
}
|
||||
|
||||
public static Color getColor(int id, int data) {
|
||||
public static final Color getColor(int id, int data) {
|
||||
Color exact = CACHE_COLOR[getCombined(id, data)];
|
||||
if (exact != null) {
|
||||
return exact;
|
||||
|
@ -62,7 +62,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
relighter = new NMSRelighter(this);
|
||||
}
|
||||
if (Settings.LIGHTING.MODE == 2) {
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), null);
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), null, chunk.getBitMask());
|
||||
return;
|
||||
}
|
||||
CharFaweChunk cfc = (CharFaweChunk) chunk;
|
||||
@ -76,7 +76,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
}
|
||||
}
|
||||
if (relight) {
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), fix);
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), fix, chunk.getBitMask());
|
||||
} else {
|
||||
refreshChunk(chunk);
|
||||
}
|
||||
|
@ -28,12 +28,12 @@ public class NMSRelighter {
|
||||
this.maxY = queue.getWEWorld().getMaxY();
|
||||
}
|
||||
|
||||
public boolean addChunk(int cx, int cz, boolean[] fix) {
|
||||
public boolean addChunk(int cx, int cz, boolean[] fix, int bitmask) {
|
||||
long pair = MathMan.pairInt(cx, cz);
|
||||
if (skyToRelight.containsKey(pair)) {
|
||||
return false;
|
||||
}
|
||||
skyToRelight.put(pair, new RelightSkyEntry(cx, cz, fix));
|
||||
skyToRelight.put(pair, new RelightSkyEntry(cx, cz, fix, bitmask));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -126,16 +126,9 @@ public class NMSRelighter {
|
||||
for (Map.Entry<Long, RelightSkyEntry> entry : skyToRelight.entrySet()) {
|
||||
RelightSkyEntry chunk = entry.getValue();
|
||||
CharFaweChunk fc = (CharFaweChunk) queue.getFaweChunk(chunk.x, chunk.z);
|
||||
int mask = 0;
|
||||
for (int y = 0; y < chunk.fix.length; y++) {
|
||||
if (chunk.fix[y]) {
|
||||
mask += 1 << y;
|
||||
}
|
||||
}
|
||||
fc.setBitMask(mask);
|
||||
fc.setBitMask(chunk.bitmask);
|
||||
queue.sendChunk(fc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isTransparent(int x, int y, int z) {
|
||||
@ -338,14 +331,16 @@ public class NMSRelighter {
|
||||
public final int z;
|
||||
public final byte[] mask;
|
||||
public final boolean[] fix;
|
||||
public final int bitmask;
|
||||
public boolean smooth;
|
||||
|
||||
public RelightSkyEntry(int x, int z, boolean[] fix) {
|
||||
public RelightSkyEntry(int x, int z, boolean[] fix, int bitmask) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
byte[] array = new byte[maxY + 1];
|
||||
Arrays.fill(array, (byte) 15);
|
||||
this.mask = array;
|
||||
this.bitmask = bitmask;
|
||||
if (fix == null) {
|
||||
this.fix = new boolean[(maxY + 1) >> 4];
|
||||
Arrays.fill(this.fix, true);
|
||||
|
@ -5,6 +5,7 @@ import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
@ -116,7 +117,12 @@ public abstract class FawePlayer<T> {
|
||||
try {
|
||||
run.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
FaweException fe = FaweException.get(e);
|
||||
if (fe != null) {
|
||||
sendMessage(fe.getMessage());
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
runningCount.decrementAndGet();
|
||||
Runnable next = getActions().poll();
|
||||
@ -157,7 +163,16 @@ public abstract class FawePlayer<T> {
|
||||
|
||||
public boolean runAction(final Runnable ifFree, boolean checkFree, boolean async) {
|
||||
if (checkFree) {
|
||||
queueAction(ifFree);
|
||||
if (async) {
|
||||
TaskManager.IMP.taskNow(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
queueAction(ifFree);
|
||||
}
|
||||
}, async);
|
||||
} else {
|
||||
queueAction(ifFree);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
TaskManager.IMP.taskNow(ifFree, async);
|
||||
|
@ -20,6 +20,11 @@ public class IntegerTrio {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + "," + y + "," + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public class FastRandomCollection<T> extends RandomCollection<T> {
|
||||
private PseudoRandom random = new PseudoRandom();
|
||||
private T[] values;
|
||||
|
||||
public FastRandomCollection(Map<T, Double> weights) {
|
||||
super(weights);
|
||||
int max = 0;
|
||||
int[] counts = new int[weights.size()];
|
||||
Double[] weightDoubles = weights.values().toArray(new Double[weights.size()]);
|
||||
for (int i = 0; i < weightDoubles.length; i++) {
|
||||
int weight = (int) (weightDoubles[i] * 100);
|
||||
counts[i] = weight;
|
||||
if (weight != (weightDoubles[i] * 100)) {
|
||||
throw new IllegalArgumentException("Too small");
|
||||
}
|
||||
if (weight > max) {
|
||||
max = weight;
|
||||
}
|
||||
}
|
||||
int gcd = MathMan.gcd(counts);
|
||||
if (max / gcd > 100000) {
|
||||
throw new IllegalArgumentException("Too large");
|
||||
}
|
||||
ArrayList<T> parsed = new ArrayList<>();
|
||||
for (Map.Entry<T, Double> entry : weights.entrySet()) {
|
||||
int num = (int) (100 * entry.getValue());
|
||||
for (int j = 0; j < num / gcd; j++) {
|
||||
parsed.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
this.values = (T[]) parsed.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return values[random.nextInt(values.length)];
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class RandomCollection<T> {
|
||||
public RandomCollection(Map<T, Double> weights) {}
|
||||
|
||||
public static <T> RandomCollection<T> of(Map<T, Double> weights) {
|
||||
try {
|
||||
return new FastRandomCollection<>(weights);
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
return new SimpleRandomCollection<>(weights);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract T next();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class SimpleRandomCollection<E> extends RandomCollection<E> {
|
||||
|
||||
private final NavigableMap<Double, E> map = new TreeMap<Double, E>();
|
||||
private final Random random;
|
||||
private double total = 0;
|
||||
|
||||
public SimpleRandomCollection(Map<E, Double> weights) {
|
||||
super(weights);
|
||||
this.random = new Random();
|
||||
for (Map.Entry<E, Double> entry : weights.entrySet()) {
|
||||
add(entry.getValue(), entry.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void add(double weight, E result) {
|
||||
if (weight <= 0) return;
|
||||
total += weight;
|
||||
map.put(total, result);
|
||||
}
|
||||
|
||||
public E next() {
|
||||
double value = random.nextDouble() * total;
|
||||
return map.ceilingEntry(value).getValue();
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@ public class AboveVisitor extends RecursiveVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisitable(Vector from, Vector to) {
|
||||
public boolean isVisitable(Vector from, Vector to) {
|
||||
return (from.getBlockY() >= baseY) && super.isVisitable(from, to);
|
||||
}
|
||||
}
|
@ -43,56 +43,71 @@ public class MathMan {
|
||||
253, 254, 254, 255
|
||||
};
|
||||
|
||||
public static long inverseRound(double val) {
|
||||
public static final long inverseRound(double val) {
|
||||
long round = Math.round(val);
|
||||
return (long) (round + Math.signum(val - round));
|
||||
}
|
||||
|
||||
public static short pairByte(int x, int y) {
|
||||
public static final short pairByte(int x, int y) {
|
||||
return (short) ((x << 8) | (y & 0xFF));
|
||||
}
|
||||
|
||||
public static byte unpairShortX(short pair) {
|
||||
public static final byte unpairShortX(short pair) {
|
||||
return (byte) (pair >> 8);
|
||||
}
|
||||
|
||||
public static byte unpairShortY(short pair) {
|
||||
public static final byte unpairShortY(short pair) {
|
||||
return (byte) pair;
|
||||
}
|
||||
|
||||
public static long pairInt(int x, int y) {
|
||||
public static final long pairInt(int x, int y) {
|
||||
return (((long)x) << 32) | (y & 0xffffffffL);
|
||||
}
|
||||
|
||||
public static long chunkXZ2Int(int x, int z) {
|
||||
public static final long chunkXZ2Int(int x, int z) {
|
||||
return (long)x & 4294967295L | ((long)z & 4294967295L) << 32;
|
||||
}
|
||||
|
||||
public static int unpairIntX(long pair) {
|
||||
public static final int unpairIntX(long pair) {
|
||||
return (int)(pair >> 32);
|
||||
}
|
||||
|
||||
public static int unpairIntY(long pair) {
|
||||
public static final int unpairIntY(long pair) {
|
||||
return (int)pair;
|
||||
}
|
||||
|
||||
public static byte pair16(int x, int y) {
|
||||
public static final byte pair16(int x, int y) {
|
||||
return (byte) (x + (y << 4));
|
||||
}
|
||||
|
||||
public static byte unpair16x(byte value) {
|
||||
public static final byte unpair16x(byte value) {
|
||||
return (byte) (value & 0xF);
|
||||
}
|
||||
|
||||
public static byte unpair16y(byte value) {
|
||||
public static final byte unpair16y(byte value) {
|
||||
return (byte) ((value >> 4) & 0xF);
|
||||
}
|
||||
|
||||
public static int lossyFastDivide(int a, int b) {
|
||||
public static final int lossyFastDivide(int a, int b) {
|
||||
return (a*((1<<16)/b))>>16;
|
||||
}
|
||||
|
||||
public static int sqrt(int x) {
|
||||
public static final int gcd(int a, int b) {
|
||||
if (b == 0) {
|
||||
return a;
|
||||
}
|
||||
return gcd(b, a % b);
|
||||
}
|
||||
|
||||
public static final int gcd(int[] a) {
|
||||
int result = a[0];
|
||||
for (int i = 1; i < a.length; i++) {
|
||||
result = gcd(result, a[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int sqrt(int x) {
|
||||
int xn;
|
||||
|
||||
if (x >= 0x10000) {
|
||||
@ -160,7 +175,7 @@ public class MathMan {
|
||||
}
|
||||
|
||||
|
||||
public static double getMean(int[] array) {
|
||||
public static final double getMean(int[] array) {
|
||||
double count = 0;
|
||||
for (int i : array) {
|
||||
count += i;
|
||||
@ -168,7 +183,7 @@ public class MathMan {
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public static double getMean(double[] array) {
|
||||
public static final double getMean(double[] array) {
|
||||
double count = 0;
|
||||
for (double i : array) {
|
||||
count += i;
|
||||
@ -176,15 +191,15 @@ public class MathMan {
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public static int pair(short x, short y) {
|
||||
public static final int pair(short x, short y) {
|
||||
return (x << 16) | (y & 0xFFFF);
|
||||
}
|
||||
|
||||
public static short unpairX(int hash) {
|
||||
public static final short unpairX(int hash) {
|
||||
return (short) (hash >> 16);
|
||||
}
|
||||
|
||||
public static short unpairY(int hash) {
|
||||
public static final short unpairY(int hash) {
|
||||
return (short) (hash & 0xFFFF);
|
||||
}
|
||||
|
||||
@ -194,12 +209,12 @@ public class MathMan {
|
||||
* @param pitch
|
||||
* @return
|
||||
*/
|
||||
public static float[] getDirection(float yaw, float pitch) {
|
||||
public static final float[] getDirection(float yaw, float pitch) {
|
||||
double pitch_sin = Math.sin(pitch);
|
||||
return new float[]{(float) (pitch_sin * Math.cos(yaw)), (float) (pitch_sin * Math.sin(yaw)), (float) Math.cos(pitch)};
|
||||
}
|
||||
|
||||
public static int roundInt(double value) {
|
||||
public static final int roundInt(double value) {
|
||||
return (int) (value < 0 ? (value == (int) value) ? value : value - 1 : value);
|
||||
}
|
||||
|
||||
@ -210,7 +225,7 @@ public class MathMan {
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static float[] getPitchAndYaw(float x, float y, float z) {
|
||||
public static final float[] getPitchAndYaw(float x, float y, float z) {
|
||||
float distance = sqrtApprox((z * z) + (x * x));
|
||||
return new float[]{atan2(y, distance), atan2(x, z)};
|
||||
}
|
||||
@ -249,15 +264,15 @@ public class MathMan {
|
||||
return (atan2[(yi * ATAN2_DIM) + xi] + add) * mul;
|
||||
}
|
||||
|
||||
public static float sqrtApprox(float f) {
|
||||
public static final float sqrtApprox(float f) {
|
||||
return f * Float.intBitsToFloat(0x5f375a86 - (Float.floatToIntBits(f) >> 1));
|
||||
}
|
||||
|
||||
public static double sqrtApprox(double d) {
|
||||
public static final double sqrtApprox(double d) {
|
||||
return Double.longBitsToDouble(((Double.doubleToLongBits(d) - (1l << 52)) >> 1) + (1l << 61));
|
||||
}
|
||||
|
||||
public static float invSqrt(float x) {
|
||||
public static final float invSqrt(float x) {
|
||||
float xhalf = 0.5f * x;
|
||||
int i = Float.floatToIntBits(x);
|
||||
i = 0x5f3759df - (i >> 1);
|
||||
@ -266,14 +281,14 @@ public class MathMan {
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int getPositiveId(int i) {
|
||||
public static final int getPositiveId(int i) {
|
||||
if (i < 0) {
|
||||
return (-i * 2) - 1;
|
||||
}
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
public static boolean isInteger(String str) {
|
||||
public static final boolean isInteger(String str) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
@ -297,7 +312,7 @@ public class MathMan {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static double getSD(double[] array, double av) {
|
||||
public static final double getSD(double[] array, double av) {
|
||||
double sd = 0;
|
||||
for (double element : array) {
|
||||
sd += Math.pow(Math.abs(element - av), 2);
|
||||
@ -305,7 +320,7 @@ public class MathMan {
|
||||
return Math.sqrt(sd / array.length);
|
||||
}
|
||||
|
||||
public static double getSD(int[] array, double av) {
|
||||
public static final double getSD(int[] array, double av) {
|
||||
double sd = 0;
|
||||
for (int element : array) {
|
||||
sd += Math.pow(Math.abs(element - av), 2);
|
||||
@ -313,21 +328,21 @@ public class MathMan {
|
||||
return Math.sqrt(sd / array.length);
|
||||
}
|
||||
|
||||
public static int mod(int x, int y) {
|
||||
public static final int mod(int x, int y) {
|
||||
if (isPowerOfTwo(y)) {
|
||||
return x & (y - 1);
|
||||
}
|
||||
return x % y;
|
||||
}
|
||||
|
||||
public static int unsignedmod(int x, int y) {
|
||||
public static final int unsignedmod(int x, int y) {
|
||||
if (isPowerOfTwo(y)) {
|
||||
return x & (y - 1);
|
||||
}
|
||||
return x % y;
|
||||
}
|
||||
|
||||
public static boolean isPowerOfTwo(int x) {
|
||||
public static final boolean isPowerOfTwo(int x) {
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
}
|
||||
|
@ -191,6 +191,8 @@ public class SetQueue {
|
||||
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
||||
completer = new ExecutorCompletionService(pool);
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
queue.runTasks();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,9 @@ public class Vector implements Comparable<Vector> {
|
||||
* @param z the Z coordinate
|
||||
*/
|
||||
public Vector(int x, int y, int z) {
|
||||
this.x = (double) x;
|
||||
this.y = (double) y;
|
||||
this.z = (double) z;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,9 +70,9 @@ public class Vector implements Comparable<Vector> {
|
||||
* @param z the Z coordinate
|
||||
*/
|
||||
public Vector(float x, float y, float z) {
|
||||
this.x = (double) x;
|
||||
this.y = (double) y;
|
||||
this.z = (double) z;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +112,7 @@ public class Vector implements Comparable<Vector> {
|
||||
* @return the x coordinate
|
||||
*/
|
||||
public int getBlockX() {
|
||||
return (int) Math.round(x);
|
||||
return (int) x;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +150,7 @@ public class Vector implements Comparable<Vector> {
|
||||
* @return the y coordinate
|
||||
*/
|
||||
public int getBlockY() {
|
||||
return (int) Math.round(y);
|
||||
return (int) (y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,7 +188,7 @@ public class Vector implements Comparable<Vector> {
|
||||
* @return the z coordinate
|
||||
*/
|
||||
public int getBlockZ() {
|
||||
return (int) Math.round(z);
|
||||
return (int) (z);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -773,7 +773,7 @@ public class Vector implements Comparable<Vector> {
|
||||
}
|
||||
|
||||
Vector other = (Vector) obj;
|
||||
return other.x == this.x && other.y == this.y && other.z == this.z;
|
||||
return other.x == this.x && other.z == this.z && other.y == this.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -789,12 +789,7 @@ public class Vector implements Comparable<Vector> {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
|
||||
hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
|
||||
hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
|
||||
hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
|
||||
return hash;
|
||||
return (int) x ^ ((int) z << 16) ^ ((byte) y << 31);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.blocks;
|
||||
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ import com.sk89q.worldedit.command.tool.BlockDataCyler;
|
||||
import com.sk89q.worldedit.command.tool.BlockReplacer;
|
||||
import com.sk89q.worldedit.command.tool.DistanceWand;
|
||||
import com.sk89q.worldedit.command.tool.FloatingTreeRemover;
|
||||
import com.sk89q.worldedit.command.tool.FloodFillTool;
|
||||
import com.sk89q.worldedit.command.tool.FloodFillTool;
|
||||
import com.sk89q.worldedit.command.tool.LongRangeBuildTool;
|
||||
import com.sk89q.worldedit.command.tool.QueryTool;
|
||||
import com.sk89q.worldedit.command.tool.TreePlanter;
|
||||
|
@ -0,0 +1,136 @@
|
||||
package com.sk89q.worldedit.function.mask;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A mask that checks whether blocks at the given positions are matched by
|
||||
* a block in a list.
|
||||
*
|
||||
* <p>This mask checks for both an exact block ID and data value match, as well
|
||||
* for a block with the same ID but a data value of -1.</p>
|
||||
*/
|
||||
public class BlockMask extends AbstractExtentMask {
|
||||
|
||||
public final boolean[] blocks = new boolean[Character.MAX_VALUE + 1];
|
||||
public final boolean[] blockIds = new boolean[4096];
|
||||
public Collection<BaseBlock> computedLegacyList;
|
||||
|
||||
/**
|
||||
* Create a new block mask.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param blocks a list of blocks to match
|
||||
*/
|
||||
public BlockMask(Extent extent, Collection<BaseBlock> blocks) {
|
||||
super(extent);
|
||||
checkNotNull(blocks);
|
||||
add(blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new block mask.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param block an array of blocks to match
|
||||
*/
|
||||
public BlockMask(Extent extent, BaseBlock... block) {
|
||||
this(extent, Arrays.asList(checkNotNull(block)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given blocks to the list of criteria.
|
||||
*
|
||||
* @param blocks a list of blocks
|
||||
*/
|
||||
public void add(Collection<BaseBlock> blocks) {
|
||||
checkNotNull(blocks);
|
||||
for (BaseBlock block : blocks) {
|
||||
add(block);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given blocks to the list of criteria.
|
||||
*
|
||||
* @param blocks an array of blocks
|
||||
*/
|
||||
public void add(BaseBlock... blocks) {
|
||||
for (BaseBlock block : blocks) {
|
||||
add(block);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(BaseBlock block) {
|
||||
blockIds[block.getId()] = true;
|
||||
if (block.getData() == -1) {
|
||||
for (int data = 0; data < 16; data++) {
|
||||
blocks[FaweCache.getCombined(block.getId(), data)] = true;
|
||||
}
|
||||
} else {
|
||||
blocks[FaweCache.getCombined(block)] = true;
|
||||
}
|
||||
computedLegacyList = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of blocks that are tested with.
|
||||
*
|
||||
* @return a list of blocks
|
||||
*/
|
||||
public Collection<BaseBlock> getBlocks() {
|
||||
if (computedLegacyList != null) {
|
||||
return computedLegacyList;
|
||||
}
|
||||
computedLegacyList = new LinkedHashSet<>();
|
||||
for (int id = 0; id < FaweCache.getId(blocks.length); id++) {
|
||||
boolean all = true;
|
||||
ArrayList<BaseBlock> tmp = new ArrayList<BaseBlock>(16);
|
||||
for (int data = 0; data < 16; data++) {
|
||||
if (blocks[FaweCache.getCombined(id, data)]) {
|
||||
tmp.add(FaweCache.getBlock(id, data));
|
||||
}
|
||||
}
|
||||
if (tmp.size() == 16) {
|
||||
computedLegacyList.add(new BaseBlock(id, -1));
|
||||
} else {
|
||||
computedLegacyList.addAll(tmp);
|
||||
}
|
||||
}
|
||||
return computedLegacyList;
|
||||
}
|
||||
|
||||
public boolean test(int blockId) {
|
||||
return blockIds[blockId];
|
||||
}
|
||||
|
||||
public boolean test(int blockId, int data) {
|
||||
return blocks[FaweCache.getCombined(blockId, data)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
BaseBlock block = getExtent().getBlock(vector);
|
||||
return blocks[FaweCache.getCombined(block)];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return BlockMask.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.sk89q.worldedit.function.mask;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import java.util.Collection;
|
||||
|
||||
public class FuzzyBlockMask extends BlockMask {
|
||||
|
||||
public FuzzyBlockMask(Extent extent, Collection<BaseBlock> blocks) {
|
||||
super(extent, blocks);
|
||||
}
|
||||
|
||||
public FuzzyBlockMask(Extent extent, BaseBlock... block) {
|
||||
super(extent, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
Extent extent = getExtent();
|
||||
Collection<BaseBlock> blocks = getBlocks();
|
||||
BaseBlock lazyBlock = extent.getBlock(vector);
|
||||
if (lazyBlock.getData() == -1) {
|
||||
return test(lazyBlock.getId());
|
||||
} else {
|
||||
return test(lazyBlock.getId(), lazyBlock.getData());
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return FuzzyBlockMask.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.sk89q.worldedit.function.mask;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SolidBlockMask extends BlockMask {
|
||||
|
||||
public SolidBlockMask(Extent extent) {
|
||||
super(extent);
|
||||
for (int id = 0; id < 4096; id++) {
|
||||
for (int data = 0; data < 16; data++) {
|
||||
if (!BlockType.canPassThrough(id, data)) {
|
||||
add(new BaseBlock(id, data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null; // 9751418
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return SolidBlockMask.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.sk89q.worldedit.function.pattern;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A pattern that reads from {@link Clipboard}.
|
||||
*/
|
||||
public class ClipboardPattern extends AbstractPattern {
|
||||
|
||||
private final Clipboard clipboard;
|
||||
private final Vector size;
|
||||
private final Vector min;
|
||||
|
||||
/**
|
||||
* Create a new clipboard pattern.
|
||||
*
|
||||
* @param clipboard the clipboard
|
||||
*/
|
||||
public ClipboardPattern(Clipboard clipboard) {
|
||||
checkNotNull(clipboard);
|
||||
this.clipboard = clipboard;
|
||||
this.size = clipboard.getMaximumPoint().subtract(clipboard.getMinimumPoint()).add(1, 1, 1);
|
||||
this.min = clipboard.getMinimumPoint();
|
||||
}
|
||||
|
||||
private Vector mutable = new Vector();
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(Vector position) {
|
||||
int xp = Math.abs(position.getBlockX()) % size.getBlockX();
|
||||
int yp = Math.abs(position.getBlockY()) % size.getBlockY();
|
||||
int zp = Math.abs(position.getBlockZ()) % size.getBlockZ();
|
||||
mutable.x = min.x + xp;
|
||||
mutable.y = min.y + yp;
|
||||
mutable.z = min.z + zp;
|
||||
return clipboard.getBlock(mutable);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ClipboardPattern.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.sk89q.worldedit.function.pattern;
|
||||
|
||||
import com.boydti.fawe.object.collection.RandomCollection;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Uses a random pattern of a weighted list of patterns.
|
||||
*/
|
||||
public class RandomPattern extends AbstractPattern {
|
||||
|
||||
private Map<Pattern, Double> weights = new HashMap<>();
|
||||
private RandomCollection<Pattern> collection;
|
||||
|
||||
/**
|
||||
* Add a pattern to the weight list of patterns.
|
||||
*
|
||||
* <p>The probability for the pattern added is chance / max where max is
|
||||
* the sum of the probabilities of all added patterns.</p>
|
||||
*
|
||||
* @param pattern the pattern
|
||||
* @param chance the chance, which can be any positive number
|
||||
*/
|
||||
public void add(Pattern pattern, double chance) {
|
||||
checkNotNull(pattern);
|
||||
weights.put(pattern, chance);
|
||||
collection = RandomCollection.of(weights);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(Vector position) {
|
||||
return collection.next().apply(position);
|
||||
}
|
||||
|
||||
private static class Chance {
|
||||
private Pattern pattern;
|
||||
private double chance;
|
||||
|
||||
private Chance(Pattern pattern, double chance) {
|
||||
this.pattern = pattern;
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
public Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public double getChance() {
|
||||
return chance;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return RandomPattern.class;
|
||||
}
|
||||
|
||||
}
|
@ -1,93 +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.function.visitor;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.operation.RunContext;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Performs a breadth-first search starting from points added with
|
||||
* {@link #visit(com.sk89q.worldedit.Vector)}. The search continues
|
||||
* to a certain adjacent point provided that the method
|
||||
* {@link #isVisitable(com.sk89q.worldedit.Vector, com.sk89q.worldedit.Vector)}
|
||||
* returns true for that point.
|
||||
*
|
||||
* <p>As an abstract implementation, this class can be used to implement
|
||||
* functionality that starts at certain points and extends outward from
|
||||
* those points.</p>
|
||||
*/
|
||||
public abstract class BreadthFirstSearch implements Operation {
|
||||
|
||||
private final RegionFunction function;
|
||||
private final Queue<BlockVector> queue = new ArrayDeque<BlockVector>();
|
||||
private final Set<BlockVector> visited = new HashSet<BlockVector>();
|
||||
private final List<Vector> directions = new ArrayList<Vector>();
|
||||
private final List<Vector> directions = new ArrayList<>();
|
||||
private final Map<Node, Integer> visited;
|
||||
private final ArrayDeque<Node> queue;
|
||||
private int affected = 0;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param function the function to apply to visited blocks
|
||||
*/
|
||||
protected BreadthFirstSearch(final RegionFunction function) {
|
||||
checkNotNull(function);
|
||||
public BreadthFirstSearch(final RegionFunction function) {
|
||||
this.queue = new ArrayDeque<>();
|
||||
this.visited = new LinkedHashMap<>();
|
||||
this.function = function;
|
||||
this.addAxes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of directions will be visited.
|
||||
*
|
||||
* <p>Directions are {@link com.sk89q.worldedit.Vector}s that determine
|
||||
* what adjacent points area available. Vectors should not be
|
||||
* unit vectors. An example of a valid direction is
|
||||
* {@code new Vector(1, 0, 1)}.</p>
|
||||
*
|
||||
* <p>The list of directions can be cleared.</p>
|
||||
*
|
||||
* @return the list of directions
|
||||
*/
|
||||
protected Collection<Vector> getDirections() {
|
||||
return this.directions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the directions along the axes as directions to visit.
|
||||
*/
|
||||
protected void addAxes() {
|
||||
this.directions.add(new Vector(0, -1, 0));
|
||||
this.directions.add(new Vector(0, 1, 0));
|
||||
this.directions.add(new Vector(-1, 0, 0));
|
||||
@ -96,97 +35,150 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
this.directions.add(new Vector(0, 0, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the diagonal directions as directions to visit.
|
||||
*/
|
||||
protected void addDiagonal() {
|
||||
this.directions.add(new Vector(1, 0, 1));
|
||||
this.directions.add(new Vector(-1, 0, -1));
|
||||
this.directions.add(new Vector(1, 0, -1));
|
||||
this.directions.add(new Vector(-1, 0, 1));
|
||||
public abstract boolean isVisitable(Vector from, Vector to);
|
||||
|
||||
public Collection<Vector> getDirections() {
|
||||
return this.directions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given location to the list of locations to visit, provided
|
||||
* that it has not been visited. The position passed to this method
|
||||
* will still be visited even if it fails
|
||||
* {@link #isVisitable(com.sk89q.worldedit.Vector, com.sk89q.worldedit.Vector)}.
|
||||
*
|
||||
* <p>This method should be used before the search begins, because if
|
||||
* the position <em>does</em> fail the test, and the search has already
|
||||
* visited it (because it is connected to another root point),
|
||||
* the search will mark the position as "visited" and a call to this
|
||||
* method will do nothing.</p>
|
||||
*
|
||||
* @param position the position
|
||||
*/
|
||||
public void visit(final Vector position) {
|
||||
final BlockVector blockVector = new BlockVector(position);
|
||||
if (!this.visited.contains(blockVector)) {
|
||||
this.queue.add(blockVector);
|
||||
this.visited.add(blockVector);
|
||||
private IntegerTrio[] getIntDirections() {
|
||||
IntegerTrio[] array = new IntegerTrio[directions.size()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
Vector dir = directions.get(i);
|
||||
array[i] = new IntegerTrio(dir.getBlockX(), dir.getBlockY(), dir.getBlockZ());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to visit the given 'to' location.
|
||||
*
|
||||
* @param from the origin block
|
||||
* @param to the block under question
|
||||
*/
|
||||
private void visit(final Vector from, final Vector to) {
|
||||
final BlockVector blockVector = to.toBlockVector();
|
||||
if (!this.visited.contains(blockVector)) {
|
||||
this.visited.add(blockVector);
|
||||
if (this.isVisitable(from, to)) {
|
||||
this.queue.add(blockVector);
|
||||
}
|
||||
public void visit(final Vector pos) {
|
||||
Node node = new Node((int) pos.x, (int) pos.y, (int) pos.z);
|
||||
if (!this.visited.containsKey(node)) {
|
||||
visited.put(node, 0);
|
||||
queue.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given 'to' block should be visited, starting from the
|
||||
* 'from' block.
|
||||
*
|
||||
* @param from the origin block
|
||||
* @param to the block under question
|
||||
* @return true if the 'to' block should be visited
|
||||
*/
|
||||
protected abstract boolean isVisitable(final Vector from, final Vector to);
|
||||
|
||||
/**
|
||||
* Get the number of affected objects.
|
||||
*
|
||||
* @return the number of affected
|
||||
*/
|
||||
public int getAffected() {
|
||||
return this.affected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume(final RunContext run) throws WorldEditException {
|
||||
Vector position;
|
||||
while ((position = this.queue.poll()) != null) {
|
||||
if (this.function.apply(position)) {
|
||||
this.affected++;
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Node from;
|
||||
Node adjacent;
|
||||
Vector mutable = new Vector();
|
||||
Vector mutable2 = new Vector();
|
||||
boolean shouldTrim = false;
|
||||
IntegerTrio[] dirs = getIntDirections();
|
||||
for (int layer = 0; !queue.isEmpty(); layer++) {
|
||||
int size = queue.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
from = queue.poll();
|
||||
mutable.x = from.getX();
|
||||
mutable.y = from.getY();
|
||||
mutable.z = from.getZ();
|
||||
function.apply(mutable);
|
||||
affected++;
|
||||
for (IntegerTrio direction : dirs) {
|
||||
mutable2.x = from.getX() + direction.x;
|
||||
mutable2.y = from.getY() + direction.y;
|
||||
mutable2.z = from.getZ() + direction.z;
|
||||
if (isVisitable(mutable, mutable2)) {
|
||||
adjacent = new Node(mutable2.getBlockX(), mutable2.getBlockY(), mutable2.getBlockZ());
|
||||
if (!visited.containsKey(adjacent)) {
|
||||
visited.put(adjacent, layer);
|
||||
queue.add(adjacent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final Vector dir : this.directions) {
|
||||
this.visit(position, position.add(dir));
|
||||
int lastLayer = layer - 1;
|
||||
size = visited.size();
|
||||
if (shouldTrim || (shouldTrim = size > 16384)) {
|
||||
Iterator<Map.Entry<Node, Integer>> iter = visited.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Node, Integer> entry = iter.next();
|
||||
Integer val = entry.getValue();
|
||||
if (val < lastLayer) {
|
||||
iter.remove();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {}
|
||||
public void addStatusMessages(List<String> messages) {
|
||||
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Operations.class;
|
||||
public int getAffected() {
|
||||
return this.affected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatusMessages(final List<String> messages) {
|
||||
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
public static final class Node {
|
||||
private int x,y,z;
|
||||
|
||||
public Node(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = (short) y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Node(Node node) {
|
||||
this.x = node.x;
|
||||
this.y = node.y;
|
||||
this.z = node.z;
|
||||
}
|
||||
|
||||
public Node() {}
|
||||
|
||||
private final void set(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = (short) y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
private final void set(Node node) {
|
||||
this.x = node.x;
|
||||
this.y = node.y;
|
||||
this.z = node.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return (x ^ (z << 12)) ^ (y << 24);
|
||||
}
|
||||
|
||||
private final int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
private final int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
private final int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + "," + y + "," + z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
Node other = (Node) obj;
|
||||
return other.x == x && other.z == z && other.y == y;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return BreadthFirstSearch.class;
|
||||
}
|
||||
}
|
||||
|
@ -62,12 +62,12 @@ public class DownwardVisitor extends RecursiveVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisitable(final Vector from, final Vector to) {
|
||||
public boolean isVisitable(final Vector from, final Vector to) {
|
||||
final int fromY = from.getBlockY();
|
||||
return ((fromY == this.baseY) || (to.subtract(from).getBlockY() < 0)) && super.isVisitable(from, to);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Operations.class;
|
||||
return DownwardVisitor.class;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class NonRisingVisitor extends RecursiveVisitor {
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Operations.class;
|
||||
return NonRisingVisitor.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,11 +48,11 @@ public class RecursiveVisitor extends BreadthFirstSearch {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisitable(final Vector from, final Vector to) {
|
||||
public boolean isVisitable(final Vector from, final Vector to) {
|
||||
return this.mask.test(to);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Operations.class;
|
||||
return RecursiveVisitor.class;
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
|
||||
private Vector pos1;
|
||||
private Vector pos2;
|
||||
private int minX,minY,minZ,maxX,maxY,maxZ;
|
||||
|
||||
/**
|
||||
* Construct a new instance of this cuboid using two corners of the cuboid.
|
||||
@ -93,6 +94,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
*/
|
||||
public void setPos1(Vector pos1) {
|
||||
this.pos1 = pos1;
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,6 +113,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
*/
|
||||
public void setPos2(Vector pos2) {
|
||||
this.pos2 = pos2;
|
||||
recalculate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,6 +122,14 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
private void recalculate() {
|
||||
pos1 = pos1.clampY(0, world == null ? 255 : world.getMaxY());
|
||||
pos2 = pos2.clampY(0, world == null ? 255 : world.getMaxY());
|
||||
Vector min = getMinimumPoint();
|
||||
Vector max = getMaximumPoint();
|
||||
minX = min.getBlockX();
|
||||
minY = min.getBlockY();
|
||||
minZ = min.getBlockZ();
|
||||
maxX = max.getBlockX();
|
||||
maxY = max.getBlockY();
|
||||
maxZ = max.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,13 +348,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
Vector min = getMinimumPoint();
|
||||
Vector max = getMaximumPoint();
|
||||
|
||||
return x >= min.getBlockX() && x <= max.getBlockX()
|
||||
&& y >= min.getBlockY() && y <= max.getBlockY()
|
||||
&& z >= min.getBlockZ() && z <= max.getBlockZ();
|
||||
return x >= this.minX && x <= this.maxX && z >= this.minZ && z <= this.maxZ && y >= this.minY && y <= this.maxY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user