mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 13:45:36 +01:00
Various minor
forge 1710 - fix block extra optimize expressions better texture util error memory optimize PrimitiveList don't clear brush settings on assignment (affected craftscripts)
This commit is contained in:
parent
ef6ad05c2e
commit
31d43b27d8
@ -28,7 +28,7 @@ ext {
|
||||
date = git.head().date.format("yy.MM.dd")
|
||||
revision = "-${git.head().abbreviatedId}"
|
||||
parents = git.head().parentIds;
|
||||
index = -94; // Offset to mach CI
|
||||
index = -95; // Offset to mach CI
|
||||
int major, minor, patch;
|
||||
major = minor = patch = 0;
|
||||
for (;parents != null && !parents.isEmpty();index++) {
|
||||
|
@ -6,10 +6,12 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||
import com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10;
|
||||
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
|
||||
import com.boydti.fawe.bukkit.v1_12.BukkitQueue_1_12;
|
||||
import com.boydti.fawe.bukkit.v1_12.NMSRegistryDumper;
|
||||
import com.boydti.fawe.bukkit.v1_7.BukkitQueue17;
|
||||
import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3;
|
||||
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
@ -66,6 +68,15 @@ public class BukkitMain extends JavaPlugin {
|
||||
try {
|
||||
BukkitQueue_0.checkVersion(v.name());
|
||||
this.version = v;
|
||||
if (version == Version.v1_12_R1) {
|
||||
try {
|
||||
Fawe.debug("Running 1.12 registry dumper!");
|
||||
NMSRegistryDumper dumper = new NMSRegistryDumper(MainUtil.getFile(getDataFolder(), "extrablocks.json"));
|
||||
dumper.run();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
} catch (IllegalStateException e) {}
|
||||
}
|
||||
|
@ -0,0 +1,317 @@
|
||||
package com.boydti.fawe.bukkit.v1_12;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.server.v1_12_R1.BaseBlockPosition;
|
||||
import net.minecraft.server.v1_12_R1.Block;
|
||||
import net.minecraft.server.v1_12_R1.BlockStateDirection;
|
||||
import net.minecraft.server.v1_12_R1.BlockStateList;
|
||||
import net.minecraft.server.v1_12_R1.EnumDirection;
|
||||
import net.minecraft.server.v1_12_R1.EnumPistonReaction;
|
||||
import net.minecraft.server.v1_12_R1.IBlockData;
|
||||
import net.minecraft.server.v1_12_R1.IBlockState;
|
||||
import net.minecraft.server.v1_12_R1.Material;
|
||||
import net.minecraft.server.v1_12_R1.MinecraftKey;
|
||||
import net.minecraft.server.v1_12_R1.Vec3D;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class NMSRegistryDumper {
|
||||
|
||||
private final Field fieldDirection;
|
||||
private File file;
|
||||
private Gson gson;
|
||||
|
||||
public NMSRegistryDumper(File file) throws NoSuchFieldException {
|
||||
this.file = file;
|
||||
GsonBuilder builder = new GsonBuilder().setPrettyPrinting();
|
||||
builder.registerTypeAdapter(BaseBlockPosition.class, new BaseBlockPositionAdapter());
|
||||
builder.registerTypeAdapter(Vec3D.class, new Vec3DAdapter());
|
||||
this.gson = builder.create();
|
||||
this.fieldDirection = EnumDirection.class.getDeclaredField("m");
|
||||
this.fieldDirection.setAccessible(true);
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
List<Map<String, Object>> list = new LinkedList<Map<String, Object>>();
|
||||
for (Block block : Block.REGISTRY) {
|
||||
MinecraftKey key = Block.REGISTRY.b(block);
|
||||
list.add(getProperties(block, key));
|
||||
}
|
||||
Collections.sort(list, new MapComparator());
|
||||
String out = gson.toJson(list);
|
||||
this.write(out);
|
||||
}
|
||||
|
||||
private Map<String, Object> getProperties(Block b, MinecraftKey key) throws IllegalAccessException {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
map.put("legacyId", Block.getId(b));
|
||||
map.put("id", key.toString());
|
||||
map.put("unlocalizedName", b.a());
|
||||
map.put("localizedName", b.getName());
|
||||
map.put("states", getStates(b));
|
||||
map.put("material", getMaterial(b));
|
||||
return map;
|
||||
}
|
||||
|
||||
private Map<String, Map> getStates(Block b) throws IllegalAccessException {
|
||||
Map<String, Map> map = new LinkedHashMap<String, Map>();
|
||||
BlockStateList bs = b.s();
|
||||
Collection<IBlockState<?>> props = bs.d();
|
||||
for (IBlockState prop : props) {
|
||||
map.put(prop.a(), dataValues(b, prop));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private final Vec3D[] rotations = {
|
||||
new Vec3D(0, 0, -1),
|
||||
new Vec3D(0.5, 0, -1),
|
||||
new Vec3D(1, 0, -1),
|
||||
new Vec3D(1, 0, -0.5),
|
||||
new Vec3D(1, 0, 0),
|
||||
new Vec3D(1, 0, 0.5),
|
||||
new Vec3D(1, 0, 1),
|
||||
new Vec3D(0.5, 0, 1),
|
||||
new Vec3D(0, 0, 1),
|
||||
new Vec3D(-0.5, 0, 1),
|
||||
new Vec3D(-1, 0, 1),
|
||||
new Vec3D(-1, 0, 0.5),
|
||||
new Vec3D(-1, 0, 0),
|
||||
new Vec3D(-1, 0, -0.5),
|
||||
new Vec3D(-1, 0, -1),
|
||||
new Vec3D(-0.5, 0, -1)
|
||||
};
|
||||
|
||||
|
||||
private BaseBlockPosition addDirection(Object orig, BaseBlockPosition addend) {
|
||||
if (orig instanceof BaseBlockPosition) {
|
||||
BaseBlockPosition ov = ((BaseBlockPosition) orig);
|
||||
return new BaseBlockPosition(addend.getX() + ov.getX(), addend.getY() + ov.getY(), addend.getZ() + ov.getZ());
|
||||
}
|
||||
return addend;
|
||||
}
|
||||
|
||||
private Map<String, Object> dataValues(Block b, IBlockState prop) throws IllegalAccessException {
|
||||
//BlockState bs = b.getBlockState();
|
||||
IBlockData base = b.fromLegacyData(0);
|
||||
|
||||
Map<String, Object> dataMap = new LinkedHashMap<String, Object>();
|
||||
Map<String, Object> valueMap = new LinkedHashMap<String, Object>();
|
||||
List<Integer> dvs = new ArrayList<Integer>();
|
||||
for (Comparable val : (Iterable<Comparable>) prop.c()) {
|
||||
Map<String, Object> stateMap = new LinkedHashMap<String, Object>();
|
||||
int dv = b.toLegacyData(base.set(prop, val));
|
||||
stateMap.put("data", dv);
|
||||
|
||||
Map<String, Object> addAfter = null;
|
||||
String addAfterName = null;
|
||||
|
||||
dvs.add(dv);
|
||||
|
||||
if (prop instanceof BlockStateDirection) {
|
||||
EnumDirection dir = EnumDirection.valueOf(val.toString().toUpperCase());
|
||||
BaseBlockPosition vec = (BaseBlockPosition) fieldDirection.get(dir);
|
||||
stateMap.put("direction", addDirection(stateMap.get("direction"), vec));
|
||||
} else if (prop.a().equals("half")) {
|
||||
if (prop.a(val).equals("top")) {
|
||||
stateMap.put("direction", addDirection(stateMap.get("direction"), new BaseBlockPosition(0, 1, 0)));
|
||||
} else if (prop.a(val).equals("bottom")) {
|
||||
stateMap.put("direction", addDirection(stateMap.get("direction"), new BaseBlockPosition(0, -1, 0)));
|
||||
}
|
||||
} else if (prop.a().equals("axis")) {
|
||||
if (prop.a(val).equals("x")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(1, 0, 0));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(-1, 0, 0));
|
||||
addAfterName = "-x";
|
||||
} else if (prop.a(val).equals("y")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, 1, 0));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(0, -1, 0));
|
||||
addAfterName = "-y";
|
||||
} else if (prop.a(val).equals("z")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, 0, 1));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(0, 0, -1));
|
||||
addAfterName = "-z";
|
||||
}
|
||||
} else if (prop.a().equals("rotation")) {
|
||||
stateMap.put("direction", rotations[Integer.valueOf(prop.a(val))]);
|
||||
} else if (prop.a().equals("facing")) { // usually already instanceof PropertyDirection, unless it's a lever
|
||||
if (prop.a(val).equals("south")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, 0, 1));
|
||||
} else if (prop.a(val).equals("north")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, 0, -1));
|
||||
} else if (prop.a(val).equals("west")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(-1, 0, 0));
|
||||
} else if (prop.a(val).equals("east")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(1, 0, 0));
|
||||
}
|
||||
/*
|
||||
// TODO fix these levers. they disappear right now
|
||||
// excluding them just means they won't get rotated
|
||||
} else if (prop.getName(val).equals("up_x")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(1, 1, 0));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(-1, 1, 0));
|
||||
addAfterName = "up_-x";
|
||||
} else if (prop.getName(val).equals("up_z")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, 1, 1));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(0, 1, -1));
|
||||
addAfterName = "up_-z";
|
||||
} else if (prop.getName(val).equals("down_x")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(1, -1, 0));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(-1, -1, 0));
|
||||
addAfterName = "down_-x";
|
||||
} else if (prop.getName(val).equals("down_z")) {
|
||||
stateMap.put("direction", new BaseBlockPosition(0, -1, 1));
|
||||
addAfter = new LinkedHashMap<String, Object>();
|
||||
addAfter.put("data", dv);
|
||||
addAfter.put("direction", new BaseBlockPosition(0, -1, -1));
|
||||
addAfterName = "down_-z";
|
||||
}*/
|
||||
}
|
||||
valueMap.put(prop.a(val), stateMap);
|
||||
if (addAfter != null) {
|
||||
valueMap.put(addAfterName, addAfter);
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to calc mask
|
||||
int dataMask = 0;
|
||||
for (int dv : dvs) {
|
||||
dataMask |= dv;
|
||||
}
|
||||
dataMap.put("dataMask", dataMask);
|
||||
|
||||
dataMap.put("values", valueMap);
|
||||
return dataMap;
|
||||
}
|
||||
|
||||
private Map<String, Object> getMaterial(Block b) {
|
||||
IBlockData bs = b.getBlockData();
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
map.put("powerSource", b.isPowerSource(bs));
|
||||
map.put("lightOpacity", b.m(bs));
|
||||
map.put("lightValue", b.o(bs));
|
||||
map.put("usingNeighborLight", b.p(bs));
|
||||
map.put("hardness", getField(b, Block.class, "blockHardness", "strength"));
|
||||
map.put("resistance", getField(b, Block.class, "blockResistance", "durability"));
|
||||
map.put("ticksRandomly", b.isTicking());
|
||||
map.put("fullCube", b.c(bs));
|
||||
map.put("slipperiness", b.frictionFactor);
|
||||
map.put("renderedAsNormalBlock", b.l(bs));
|
||||
//map.put("solidFullCube", b.isSolidFullCube());
|
||||
Material m = b.q(bs);
|
||||
map.put("liquid", m.isLiquid());
|
||||
map.put("solid", m.isBuildable());
|
||||
map.put("movementBlocker", m.isSolid());
|
||||
//map.put("blocksLight", m.blocksLight());
|
||||
map.put("burnable", m.isBurnable());
|
||||
map.put("opaque", m.k());
|
||||
map.put("replacedDuringPlacement", m.isReplaceable());
|
||||
map.put("toolRequired", !m.isAlwaysDestroyable());
|
||||
map.put("fragileWhenPushed", m.getPushReaction() == EnumPistonReaction.DESTROY);
|
||||
map.put("unpushable", m.getPushReaction() == EnumPistonReaction.BLOCK);
|
||||
map.put("adventureModeExempt", getField(m, Material.class, "isAdventureModeExempt", "Q"));
|
||||
//map.put("mapColor", rgb(m.getMaterialMapColor().colorValue));
|
||||
map.put("ambientOcclusionLightValue", b.s(bs) ? 0.2F:1.0F);
|
||||
map.put("grassBlocking", false); // idk what this property was originally supposed to be...grass uses a combination of light values to check growth
|
||||
return map;
|
||||
}
|
||||
|
||||
private Object getField(Object obj, Class<?> clazz, String name, String obfName) {
|
||||
try {
|
||||
Field f;
|
||||
try {
|
||||
f = clazz.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
f = clazz.getDeclaredField(obfName);
|
||||
}
|
||||
if (f == null) return null;
|
||||
f.setAccessible(true);
|
||||
return f.get(obj);
|
||||
} catch (IllegalAccessException ignored) {
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String rgb(int i) {
|
||||
int r = (i >> 16) & 0xFF;
|
||||
int g = (i >> 8) & 0xFF;
|
||||
int b = i & 0xFF;
|
||||
return String.format("#%02x%02x%02x", r, g, b);
|
||||
}
|
||||
|
||||
private void write(String s) {
|
||||
try {
|
||||
FileOutputStream str = new FileOutputStream(file);
|
||||
str.write(s.getBytes());
|
||||
} catch (IOException e) {
|
||||
System.err.printf("Error writing registry dump: %e", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class BaseBlockPositionAdapter extends TypeAdapter<BaseBlockPosition> {
|
||||
@Override
|
||||
public BaseBlockPosition read(final JsonReader in) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void write(final JsonWriter out, final BaseBlockPosition vec) throws IOException {
|
||||
out.beginArray();
|
||||
out.value(vec.getX());
|
||||
out.value(vec.getY());
|
||||
out.value(vec.getZ());
|
||||
out.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Vec3DAdapter extends TypeAdapter<Vec3D> {
|
||||
@Override
|
||||
public Vec3D read(final JsonReader in) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
public void write(final JsonWriter out, final Vec3D vec) throws IOException {
|
||||
out.beginArray();
|
||||
out.value(vec.x);
|
||||
out.value(vec.y);
|
||||
out.value(vec.z);
|
||||
out.endArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapComparator implements Comparator<Map<String, Object>> {
|
||||
@Override
|
||||
public int compare(Map<String, Object> a, Map<String, Object> b) {
|
||||
return ((Integer) a.get("legacyId")).compareTo((Integer) b.get("legacyId"));
|
||||
}
|
||||
}
|
||||
}
|
@ -32,13 +32,14 @@ import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockData;
|
||||
import com.sk89q.worldedit.command.BiomeCommands;
|
||||
import com.sk89q.worldedit.command.BrushCommands;
|
||||
import com.sk89q.worldedit.command.BrushOptionsCommands;
|
||||
import com.sk89q.worldedit.command.ChunkCommands;
|
||||
import com.sk89q.worldedit.command.ClipboardCommands;
|
||||
import com.sk89q.worldedit.command.FlattenedClipboardTransform;
|
||||
import com.sk89q.worldedit.command.OptionsCommands;
|
||||
import com.sk89q.worldedit.command.GenerationCommands;
|
||||
import com.sk89q.worldedit.command.HistoryCommands;
|
||||
import com.sk89q.worldedit.command.NavigationCommands;
|
||||
import com.sk89q.worldedit.command.OptionsCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommands;
|
||||
import com.sk89q.worldedit.command.SchematicCommands;
|
||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||
@ -46,7 +47,6 @@ import com.sk89q.worldedit.command.SnapshotCommands;
|
||||
import com.sk89q.worldedit.command.SnapshotUtilCommands;
|
||||
import com.sk89q.worldedit.command.SuperPickaxeCommands;
|
||||
import com.sk89q.worldedit.command.ToolCommands;
|
||||
import com.sk89q.worldedit.command.BrushOptionsCommands;
|
||||
import com.sk89q.worldedit.command.UtilityCommands;
|
||||
import com.sk89q.worldedit.command.WorldEditCommands;
|
||||
import com.sk89q.worldedit.command.composition.SelectionCommand;
|
||||
@ -106,6 +106,9 @@ import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
@ -113,6 +116,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.EllipsoidRegion;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.shape.ArbitraryShape;
|
||||
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.session.PasteBuilder;
|
||||
import com.sk89q.worldedit.session.SessionManager;
|
||||
@ -128,6 +132,7 @@ import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.MessageBox;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
@ -340,8 +345,10 @@ public class Fawe {
|
||||
|
||||
public TextureUtil getCachedTextureUtil(boolean randomize, int min, int max) {
|
||||
TextureUtil tu = getTextureUtil();
|
||||
tu = min == 0 && max == 100 ? tu : new CleanTextureUtil(tu, min, max);
|
||||
tu = randomize ? new RandomTextureUtil(tu) : new CachedTextureUtil(tu);
|
||||
try {
|
||||
tu = min == 0 && max == 100 ? tu : new CleanTextureUtil(tu, min, max);
|
||||
tu = randomize ? new RandomTextureUtil(tu) : new CachedTextureUtil(tu);
|
||||
} catch (FileNotFoundException neverHappens) { neverHappens.printStackTrace(); }
|
||||
return tu;
|
||||
}
|
||||
|
||||
@ -355,7 +362,7 @@ public class Fawe {
|
||||
textures = tmp = new TextureUtil();
|
||||
tmp.loadModTextures();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -545,6 +552,11 @@ public class Fawe {
|
||||
BlockReplace.inject(); // Optimizations + Features
|
||||
ForwardExtentCopy.inject(); // Fixes + optimizations
|
||||
ChangeSetExecutor.inject(); // Optimizations
|
||||
// Expression
|
||||
ExpressionEnvironment.inject(); // Optimizations + features
|
||||
WorldEditExpressionEnvironment.inject(); // Optimizations + features
|
||||
Expression.inject(); // Optimizations
|
||||
Functions.inject(); // Optimizations
|
||||
// BlockData
|
||||
BlockData.inject(); // Temporary fix for 1.9.4
|
||||
BundledBlockData.inject(); // Add custom rotation
|
||||
|
@ -201,6 +201,7 @@ public enum BBC {
|
||||
|
||||
COMMAND_INVALID_SYNTAX("The command was not used properly (no more help available).", "WorldEdit.Command"),
|
||||
|
||||
COMMAND_CLARIFYING_BRACKET("&7Added clarifying bracket for &c%s0", "WorldEdit.Help"),
|
||||
HELP_SUGGEST("&7Couldn't find %s0. Maybe try one of &c%s1 &7?", "WorldEdit.Help"),
|
||||
HELP_HEADER_CATEGORIES("Command Types", "WorldEdit.Help"),
|
||||
HELP_HEADER_SUBCOMMANDS("Subcommands", "WorldEdit.Help"),
|
||||
|
@ -31,6 +31,7 @@ import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
||||
@ -79,11 +80,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
||||
if (textureUtil == null) {
|
||||
textureUtil = Fawe.get().getTextureUtil();
|
||||
}
|
||||
if (randomVariation) {
|
||||
return new RandomTextureUtil(textureUtil);
|
||||
} else {
|
||||
return new CachedTextureUtil(textureUtil);
|
||||
}
|
||||
try {
|
||||
if (randomVariation) {
|
||||
return new RandomTextureUtil(textureUtil);
|
||||
} else {
|
||||
return new CachedTextureUtil(textureUtil);
|
||||
}
|
||||
} catch (FileNotFoundException neverHappens) { neverHappens.printStackTrace(); return null; }
|
||||
}
|
||||
|
||||
public void setWaterHeight(int waterHeight) {
|
||||
|
@ -137,6 +137,11 @@ public class BrushSettings {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BrushSettings clearPerms() {
|
||||
permissions.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public BrushSettings addSetting(SettingType type, String args) {
|
||||
constructor.put(type, args);
|
||||
return this;
|
||||
|
@ -0,0 +1,315 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.AbstractList;
|
||||
|
||||
public class PrimitiveList<T> extends AbstractList<T> {
|
||||
private final Class<?> primitive;
|
||||
private final Type type;
|
||||
private int length;
|
||||
private int totalLength;
|
||||
private Object arr;
|
||||
|
||||
private enum Type {
|
||||
Byte,
|
||||
Boolean,
|
||||
Short,
|
||||
Character,
|
||||
Integer,
|
||||
Float,
|
||||
Long,
|
||||
Double
|
||||
}
|
||||
|
||||
public PrimitiveList(Class<T> type) {
|
||||
try {
|
||||
Class<T> boxed;
|
||||
if (type.isPrimitive()) {
|
||||
this.primitive = type;
|
||||
boxed = (Class<T>) Array.get(Array.newInstance(primitive,1),0).getClass();
|
||||
} else {
|
||||
this.primitive = (Class<?>) type.getField("TYPE").get(null);
|
||||
boxed = type;
|
||||
}
|
||||
this.type = Type.valueOf(boxed.getSimpleName());
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
length = 0;
|
||||
totalLength = 0;
|
||||
arr = Array.newInstance(primitive, 0);
|
||||
}
|
||||
|
||||
public PrimitiveList(T[] arr) {
|
||||
try {
|
||||
Class<T> boxed = (Class<T>) arr.getClass().getComponentType();
|
||||
this.primitive = (Class<?>) boxed.getField("TYPE").get(null);
|
||||
this.type = Type.valueOf(boxed.getSimpleName());
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.arr = Array.newInstance(primitive, arr.length);
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
T val = arr[i];
|
||||
if (val != null) setFast(i, val);
|
||||
}
|
||||
this.length = arr.length;
|
||||
this.totalLength = length;
|
||||
}
|
||||
|
||||
public PrimitiveList(Object arr) {
|
||||
if (!arr.getClass().isArray()) {
|
||||
throw new IllegalArgumentException("Argument must be an array!");
|
||||
}
|
||||
this.primitive = arr.getClass().getComponentType();
|
||||
Class<T> boxed = (Class<T>) Array.get(Array.newInstance(primitive, 1), 0).getClass();
|
||||
this.type = Type.valueOf(boxed.getSimpleName());
|
||||
this.arr = arr;
|
||||
this.length = Array.getLength(arr);
|
||||
this.totalLength = length;
|
||||
}
|
||||
|
||||
public Object getArray() {
|
||||
return arr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int index) {
|
||||
return (T) getFast(index);
|
||||
}
|
||||
|
||||
public byte getByte(int index) {
|
||||
return type == Type.Double ? ((byte[]) arr)[index] : (byte) getFast(index);
|
||||
}
|
||||
|
||||
public boolean getBoolean(int index) {
|
||||
return type == Type.Boolean ? ((boolean[]) arr)[index] : (boolean) getFast(index);
|
||||
}
|
||||
|
||||
public short getShort(int index) {
|
||||
return type == Type.Short ? ((short[]) arr)[index] : (short) getFast(index);
|
||||
}
|
||||
|
||||
public char getCharacter(int index) {
|
||||
return type == Type.Character ? ((char[]) arr)[index] : (char) getFast(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return type == Type.Integer ? ((int[]) arr)[index] : (int) getFast(index);
|
||||
}
|
||||
|
||||
public float getFloat(int index) {
|
||||
return type == Type.Float ? ((float[]) arr)[index] : (float) getFast(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) {
|
||||
return type == Type.Long ? ((long[]) arr)[index] : (long) getFast(index);
|
||||
}
|
||||
|
||||
public double getDouble(int index) {
|
||||
return type == Type.Double ? ((double[]) arr)[index] : (double) getFast(index);
|
||||
}
|
||||
|
||||
private final Object getFast(int index) {
|
||||
switch (type) {
|
||||
case Byte:
|
||||
return ((byte[]) arr)[index];
|
||||
case Boolean:
|
||||
return ((boolean[]) arr)[index];
|
||||
case Short:
|
||||
return ((short[]) arr)[index];
|
||||
case Character:
|
||||
return ((char[]) arr)[index];
|
||||
case Integer:
|
||||
return ((int[]) arr)[index];
|
||||
case Float:
|
||||
return ((float[]) arr)[index];
|
||||
case Long:
|
||||
return ((long[]) arr)[index];
|
||||
case Double:
|
||||
return ((double[]) arr)[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
T value = get(index);
|
||||
setFast(index, element);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void set(int index, char value) {
|
||||
switch (type) {
|
||||
default:
|
||||
setFast(index, value);
|
||||
return;
|
||||
case Character:
|
||||
((char[]) arr)[index] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(int index, byte value) {
|
||||
switch (type) {
|
||||
default:
|
||||
setFast(index, value);
|
||||
return;
|
||||
case Byte:
|
||||
((byte[]) arr)[index] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(int index, int value) {
|
||||
switch (type) {
|
||||
default:
|
||||
setFast(index, value);
|
||||
return;
|
||||
case Integer:
|
||||
((int[]) arr)[index] = value;
|
||||
return;
|
||||
case Long:
|
||||
((long[]) arr)[index] = (long) value;
|
||||
return;
|
||||
case Double:
|
||||
((double[]) arr)[index] = (double) value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(int index, double value) {
|
||||
switch (type) {
|
||||
default:
|
||||
setFast(index, value);
|
||||
return;
|
||||
case Float:
|
||||
((float[]) arr)[index] = (float) value;
|
||||
return;
|
||||
case Long:
|
||||
((long[]) arr)[index] = (long) value;
|
||||
return;
|
||||
case Double:
|
||||
((double[]) arr)[index] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public final void setFast(int index, Object element) {
|
||||
switch (type) {
|
||||
case Byte:
|
||||
((byte[]) arr)[index] = (byte) element;
|
||||
return;
|
||||
case Boolean:
|
||||
((boolean[]) arr)[index] = (boolean) element;
|
||||
return;
|
||||
case Short:
|
||||
((short[]) arr)[index] = (short) element;
|
||||
return;
|
||||
case Character:
|
||||
((char[]) arr)[index] = (char) element;
|
||||
return;
|
||||
case Integer:
|
||||
((int[]) arr)[index] = (int) element;
|
||||
return;
|
||||
case Float:
|
||||
((float[]) arr)[index] = (float) element;
|
||||
return;
|
||||
case Long:
|
||||
((long[]) arr)[index] = (long) element;
|
||||
return;
|
||||
case Double:
|
||||
((double[]) arr)[index] = (double) element;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
if (index == length) {
|
||||
if (totalLength == length) {
|
||||
Object tmp = arr;
|
||||
totalLength = (length << 1) + 16;
|
||||
arr = Array.newInstance(primitive, totalLength);
|
||||
System.arraycopy(tmp, 0, arr, 0, length);
|
||||
}
|
||||
setFast(length, element);
|
||||
length++;
|
||||
} else {
|
||||
if (totalLength == length) {
|
||||
Object tmp = arr;
|
||||
totalLength = (length << 1) + 16;
|
||||
arr = Array.newInstance(primitive, totalLength);
|
||||
System.arraycopy(tmp, 0, arr, 0, index);
|
||||
}
|
||||
System.arraycopy(arr, index, arr, index + 1, length - index);
|
||||
set(index, element);
|
||||
length++;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAddCapacity() {
|
||||
if (totalLength == length) {
|
||||
Object tmp = arr;
|
||||
totalLength = (length << 1) + 16;
|
||||
arr = Array.newInstance(primitive, totalLength);
|
||||
System.arraycopy(tmp, 0, arr, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
ensureAddCapacity();
|
||||
setFast(length++, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean add(int element) {
|
||||
ensureAddCapacity();
|
||||
set(length++, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean add(double element) {
|
||||
ensureAddCapacity();
|
||||
set(length++, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean add(byte element) {
|
||||
ensureAddCapacity();
|
||||
set(length++, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean add(char element) {
|
||||
ensureAddCapacity();
|
||||
set(length++, element);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int index) {
|
||||
if (index < 0 || index > length) throw new IndexOutOfBoundsException(index + " not in [0, " + length + "]");
|
||||
T value = get(index);
|
||||
if (index != length) {
|
||||
System.arraycopy(arr, index + 1, arr, index, length - index - 1);
|
||||
}
|
||||
length--;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (length != 0) {
|
||||
this.arr = Array.newInstance(primitive, 0);
|
||||
}
|
||||
length = 0;
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ public class ExpressionPattern extends AbstractPattern {
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param expression the expression
|
||||
* @param input the expression
|
||||
* @throws ExpressionException thrown if there is an error with the expression
|
||||
*/
|
||||
public ExpressionPattern(String input) throws ExpressionException {
|
||||
@ -56,7 +56,11 @@ public class ExpressionPattern extends AbstractPattern {
|
||||
double combined = expression.evaluate(vector.getX(), vector.getY(), vector.getZ());
|
||||
return FaweCache.CACHE_BLOCK[(char) combined];
|
||||
} catch (EvaluationException e) {
|
||||
e.printStackTrace();
|
||||
return EditSession.nullBlock;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.util;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public class CachedTextureUtil extends DelegateTextureUtil {
|
||||
private final TextureUtil parent;
|
||||
@ -10,7 +11,7 @@ public class CachedTextureUtil extends DelegateTextureUtil {
|
||||
private transient Int2ObjectOpenHashMap<Integer> colorBiomeMap;
|
||||
private transient Int2ObjectOpenHashMap<char[]> colorLayerMap;
|
||||
|
||||
public CachedTextureUtil(TextureUtil parent) {
|
||||
public CachedTextureUtil(TextureUtil parent) throws FileNotFoundException {
|
||||
super(parent);
|
||||
this.parent = parent;
|
||||
this.colorBlockMap = new Int2ObjectOpenHashMap<>();
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CleanTextureUtil extends TextureUtil {
|
||||
public CleanTextureUtil(TextureUtil parent, int minPercent, int maxPercent) {
|
||||
public CleanTextureUtil(TextureUtil parent, int minPercent, int maxPercent) throws FileNotFoundException {
|
||||
super(parent.getFolder());
|
||||
int minIndex = ((parent.distances.length - 1) * minPercent) / 100;
|
||||
int maxIndex = ((parent.distances.length - 1) * maxPercent) / 100;
|
||||
|
@ -3,12 +3,13 @@ package com.boydti.fawe.util;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DelegateTextureUtil extends TextureUtil {
|
||||
private final TextureUtil parent;
|
||||
|
||||
public DelegateTextureUtil(TextureUtil parent) {
|
||||
public DelegateTextureUtil(TextureUtil parent) throws FileNotFoundException {
|
||||
super(parent.getFolder());
|
||||
this.parent = parent;
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ package com.boydti.fawe.util;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Set;
|
||||
|
||||
public class FilteredTextureUtil extends TextureUtil {
|
||||
public FilteredTextureUtil(TextureUtil parent, Set<BaseBlock> blocks) {
|
||||
public FilteredTextureUtil(TextureUtil parent, Set<BaseBlock> blocks) throws FileNotFoundException {
|
||||
super(parent.getFolder());
|
||||
this.validBiomes = parent.validBiomes;
|
||||
this.blockColors = parent.blockColors;
|
||||
|
@ -5,12 +5,13 @@ import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
public class RandomTextureUtil extends CachedTextureUtil {
|
||||
|
||||
private final int grassColor;
|
||||
|
||||
public RandomTextureUtil(TextureUtil parent) {
|
||||
public RandomTextureUtil(TextureUtil parent) throws FileNotFoundException {
|
||||
super(parent);
|
||||
this.grassColor = parent.getColor(FaweCache.getBlock(BlockID.GRASS, 0));
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -50,6 +51,7 @@ public class TextureUtil {
|
||||
protected int[] validLayerColors;
|
||||
protected char[][] validLayerBlocks;
|
||||
|
||||
|
||||
/**
|
||||
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
|
||||
*/
|
||||
@ -315,12 +317,15 @@ public class TextureUtil {
|
||||
new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
|
||||
};
|
||||
|
||||
public TextureUtil() {
|
||||
public TextureUtil() throws FileNotFoundException {
|
||||
this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES));
|
||||
}
|
||||
|
||||
public TextureUtil(File folder) {
|
||||
public TextureUtil(File folder) throws FileNotFoundException {
|
||||
this.folder = folder;
|
||||
if (!folder.exists()) {
|
||||
throw new FileNotFoundException("Please create a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar or mods in it.");
|
||||
}
|
||||
}
|
||||
|
||||
public BaseBlock getNearestBlock(int color) {
|
||||
@ -808,6 +813,9 @@ public class TextureUtil {
|
||||
if (all == null) {
|
||||
all = (String) textures.get("top");
|
||||
}
|
||||
if (all == null) {
|
||||
all = (String) textures.get("pattern");
|
||||
}
|
||||
if (all != null) {
|
||||
String textureName = getFileName(all);
|
||||
// Add the model
|
||||
|
@ -16,7 +16,7 @@ public class Updater {
|
||||
|
||||
public String getChanges() {
|
||||
if (changes == null) {
|
||||
try (Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) {
|
||||
try (Scanner scanner = new Scanner(new URL("http://empcraft.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) {
|
||||
changes = scanner.useDelimiter("\\A").next();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -60,7 +60,7 @@ public class Updater {
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
}
|
||||
Fawe.debug("Updated FAWE to " + versionString);
|
||||
MainUtil.sendAdmin("&7Restart to update FAWE with these changes: &c/fawe changelog &7or&c " + "http://boydti.com/fawe/cl?" + Integer.toHexString(currentVersion.hash));
|
||||
MainUtil.sendAdmin("&7Restart to update FAWE with these changes: &c/fawe changelog &7or&c " + "http://empcraft.com/fawe/cl?" + Integer.toHexString(currentVersion.hash));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ public class MaskCommands extends MethodCommands {
|
||||
max = 1
|
||||
)
|
||||
public Mask expression(EditSession editSession, String input) throws ExpressionException {
|
||||
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
|
||||
Expression exp = Expression.compile(input, "x", "y", "z");
|
||||
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
|
||||
editSession, Vector.ONE, Vector.ZERO);
|
||||
exp.setEnvironment(env);
|
||||
|
@ -131,7 +131,7 @@ public class WorldEditCommands {
|
||||
Updater updater = Fawe.get().getUpdater();
|
||||
String changes = updater != null ? updater.getChanges() : null;
|
||||
if (changes == null) {
|
||||
try (Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) {
|
||||
try (Scanner scanner = new Scanner(new URL("http://empcraft.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) {
|
||||
changes = scanner.useDelimiter("\\A").next();
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
|
||||
public void setBrush(Brush brush, String permission, Player player) {
|
||||
if (player != null) clear(player);
|
||||
BrushSettings current = getContext();
|
||||
current.clear();
|
||||
current.clearPerms();
|
||||
current.setBrush(brush);
|
||||
current.addPermission(permission);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.boydti.fawe.command.FaweParser;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
@ -103,7 +104,7 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
input = input.substring(input.indexOf(char0) + 1);
|
||||
mask = parseFromInput(char0 + "[" + input + "]", context);
|
||||
if (actor != null) {
|
||||
actor.print("&7Added clarifying bracket for: " + char0 + "&c[&7" + input + "&c]&7");
|
||||
BBC.COMMAND_CLARIFYING_BRACKET.send(actor, char0 + "[" + input + "]");
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.internal.expression;
|
||||
|
||||
import com.sk89q.worldedit.internal.expression.lexer.Lexer;
|
||||
import com.sk89q.worldedit.internal.expression.lexer.tokens.Token;
|
||||
import com.sk89q.worldedit.internal.expression.parser.Parser;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Constant;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.RValue;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ReturnException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Variable;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Compiles and evaluates expressions.
|
||||
*
|
||||
* <p>Supported operators:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>Logical: &&, ||, ! (unary)</li>
|
||||
* <li>Bitwise: ~ (unary), >>, <<</li>
|
||||
* <li>Arithmetic: +, -, *, /, % (modulo), ^ (power), - (unary), --, ++ (prefix only)</li>
|
||||
* <li>Comparison: <=, >=, >, <, ==, !=, ~= (near)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Supported functions: abs, acos, asin, atan, atan2, cbrt, ceil, cos, cosh,
|
||||
* exp, floor, ln, log, log10, max, max, min, min, rint, round, sin, sinh,
|
||||
* sqrt, tan, tanh and more. (See the Functions class or the wiki)</p>
|
||||
*
|
||||
* <p>Constants: e, pi</p>
|
||||
*
|
||||
* <p>To compile an equation, run
|
||||
* {@code Expression.compile("expression here", "var1", "var2"...)}.
|
||||
* If you wish to run the equation multiple times, you can then optimize it,
|
||||
* by calling {@link #optimize()}. You can then run the equation as many times
|
||||
* as you want by calling {@link #evaluate(double...)}. You do not need to
|
||||
* pass values for all variables specified while compiling.
|
||||
* To query variables after evaluation, you can use
|
||||
* {@link #getVariable(String, boolean)}. To get a value out of these, use
|
||||
* {@link Variable#getValue()}.</p>
|
||||
*
|
||||
* <p>Variables are also supported and can be set either by passing values
|
||||
* to {@link #evaluate(double...)}.</p>
|
||||
*/
|
||||
public class Expression {
|
||||
|
||||
private static final ThreadLocal<ArrayDeque<Expression>> instance = new ThreadLocal<ArrayDeque<Expression>>() {
|
||||
@Override
|
||||
protected ArrayDeque<Expression> initialValue() {
|
||||
return new ArrayDeque<>();
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<String, RValue> variables = new HashMap<String, RValue>();
|
||||
private final String[] variableNames;
|
||||
private Variable[] variableArray;
|
||||
private RValue root;
|
||||
private final Functions functions = new Functions();
|
||||
private ExpressionEnvironment environment;
|
||||
|
||||
public static Expression compile(String expression, String... variableNames) throws ExpressionException {
|
||||
return new Expression(expression, variableNames);
|
||||
}
|
||||
|
||||
private Expression(String expression, String... variableNames) throws ExpressionException {
|
||||
this(Lexer.tokenize(expression), variableNames);
|
||||
}
|
||||
|
||||
private Expression(List<Token> tokens, String... variableNames) throws ExpressionException {
|
||||
variables.put("e", new Constant(-1, Math.E));
|
||||
variables.put("pi", new Constant(-1, Math.PI));
|
||||
variables.put("true", new Constant(-1, 1));
|
||||
variables.put("false", new Constant(-1, 0));
|
||||
|
||||
this.variableNames = variableNames;
|
||||
variableArray = new Variable[variableNames.length];
|
||||
for (int i = 0; i < variableNames.length; i++) {
|
||||
String variableName = variableNames[i];
|
||||
if (variables.containsKey(variableName)) {
|
||||
throw new ExpressionException(-1, "Tried to overwrite identifier '" + variableName + "'");
|
||||
}
|
||||
Variable var = new Variable(0);
|
||||
variables.put(variableName, var);
|
||||
variableArray[i] = var;
|
||||
}
|
||||
|
||||
root = Parser.parse(tokens, this);
|
||||
}
|
||||
|
||||
public double evaluate(double... values) throws EvaluationException {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
Variable var = variableArray[i];
|
||||
var.value = values[i];
|
||||
}
|
||||
pushInstance();
|
||||
try {
|
||||
return root.getValue();
|
||||
} catch (ReturnException e) {
|
||||
return e.getValue();
|
||||
} finally {
|
||||
popInstance();
|
||||
}
|
||||
}
|
||||
|
||||
public void optimize() throws EvaluationException {
|
||||
root = root.optimize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return root.toString();
|
||||
}
|
||||
|
||||
public RValue getVariable(String name, boolean create) {
|
||||
RValue variable = variables.get(name);
|
||||
if (variable == null && create) {
|
||||
variables.put(name, variable = new Variable(0));
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
public static Expression getInstance() {
|
||||
return instance.get().peek();
|
||||
}
|
||||
|
||||
private void pushInstance() {
|
||||
ArrayDeque<Expression> foo = instance.get();
|
||||
foo.push(this);
|
||||
}
|
||||
|
||||
private void popInstance() {
|
||||
ArrayDeque<Expression> foo = instance.get();
|
||||
|
||||
foo.pop();
|
||||
}
|
||||
|
||||
public Functions getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
|
||||
public ExpressionEnvironment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public void setEnvironment(ExpressionEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Expression.class;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.internal.expression.runtime;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
/**
|
||||
* Represents a way to access blocks in a world. Has to accept non-rounded coordinates.
|
||||
*/
|
||||
public interface ExpressionEnvironment {
|
||||
|
||||
BaseBlock getBlock(double x, double y, double z);
|
||||
BaseBlock getBlockAbs(double x, double y, double z);
|
||||
BaseBlock getBlockRel(double x, double y, double z);
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ExpressionEnvironment.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.internal.expression.runtime;
|
||||
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.parser.ParserException;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Wrapper for a Java method and its arguments (other Nodes).
|
||||
*/
|
||||
public class Function extends Node {
|
||||
|
||||
/**
|
||||
* Add this annotation on functions that don't always return the same value
|
||||
* for the same inputs and on functions with side-effects.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Dynamic { }
|
||||
|
||||
public final Method method;
|
||||
public final RValue[] args;
|
||||
|
||||
public Function(int position, Method method, RValue... args) {
|
||||
super(position);
|
||||
this.method = method;
|
||||
this.method.setAccessible(true);
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final double getValue() throws EvaluationException {
|
||||
return invokeMethod(method, args);
|
||||
}
|
||||
|
||||
public static double invokeMethod(Method method, Object[] args) throws EvaluationException {
|
||||
try {
|
||||
return (Double) method.invoke(null, args);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getTargetException() instanceof EvaluationException) {
|
||||
throw (EvaluationException) e.getTargetException();
|
||||
}
|
||||
throw new EvaluationException(-1, "Exception caught while evaluating expression", e.getTargetException());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new EvaluationException(-1, "Internal error while evaluating expression", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder ret = new StringBuilder(method.getName()).append('(');
|
||||
boolean first = true;
|
||||
for (Object obj : args) {
|
||||
if (!first) {
|
||||
ret.append(", ");
|
||||
}
|
||||
first = false;
|
||||
ret.append(obj);
|
||||
}
|
||||
return ret.append(')').toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char id() {
|
||||
return 'f';
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue optimize() throws EvaluationException {
|
||||
final RValue[] optimizedArgs = new RValue[args.length];
|
||||
boolean optimizable = !method.isAnnotationPresent(Dynamic.class);
|
||||
int position = getPosition();
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
final RValue optimized = optimizedArgs[i] = args[i].optimize();
|
||||
|
||||
if (!(optimized instanceof Constant)) {
|
||||
optimizable = false;
|
||||
}
|
||||
|
||||
if (optimized.getPosition() < position) {
|
||||
position = optimized.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
if (optimizable) {
|
||||
return new Constant(position, invokeMethod(method, optimizedArgs));
|
||||
} else {
|
||||
return new Function(position, method, optimizedArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue bindVariables(Expression expression, boolean preferLValue) throws ParserException {
|
||||
final Class<?>[] parameters = method.getParameterTypes();
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
final boolean argumentPrefersLValue = LValue.class.isAssignableFrom(parameters[i]);
|
||||
args[i] = args[i].bindVariables(expression, argumentPrefersLValue);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Function.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,511 @@
|
||||
/*
|
||||
* 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.internal.expression.runtime;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Function.Dynamic;
|
||||
import com.sk89q.worldedit.math.noise.PerlinNoise;
|
||||
import com.sk89q.worldedit.math.noise.RidgedMultiFractalNoise;
|
||||
import com.sk89q.worldedit.math.noise.VoronoiNoise;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Contains all functions that can be used in expressions.
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public final class Functions {
|
||||
|
||||
private static class Overload {
|
||||
private final Method method;
|
||||
private final int mask;
|
||||
private final boolean isSetter;
|
||||
|
||||
private Overload(Method method) throws IllegalArgumentException {
|
||||
this.method = method;
|
||||
|
||||
boolean isSetter = false;
|
||||
int accum = 0;
|
||||
Class<?>[] parameters = method.getParameterTypes();
|
||||
for (Class<?> parameter : parameters) {
|
||||
if (isSetter) {
|
||||
throw new IllegalArgumentException("Method takes arguments that can't be cast to RValue.");
|
||||
}
|
||||
|
||||
if (double.class.equals(parameter)) {
|
||||
isSetter = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!RValue.class.isAssignableFrom(parameter)) {
|
||||
throw new IllegalArgumentException("Method takes arguments that can't be cast to RValue.");
|
||||
}
|
||||
|
||||
accum <<= 2;
|
||||
|
||||
if (LValue.class.isAssignableFrom(parameter)) {
|
||||
accum |= 3;
|
||||
} else {
|
||||
accum |= 1;
|
||||
}
|
||||
}
|
||||
mask = accum;
|
||||
this.isSetter = isSetter;
|
||||
}
|
||||
|
||||
public boolean matches(boolean isSetter, RValue... args) {
|
||||
if (this.isSetter != isSetter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.method.getParameterTypes().length != args.length) { // TODO: optimize
|
||||
return false;
|
||||
}
|
||||
|
||||
int accum = 0;
|
||||
for (RValue argument : args) {
|
||||
accum <<= 2;
|
||||
|
||||
if (argument instanceof LValue) {
|
||||
accum |= 3;
|
||||
} else {
|
||||
accum |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (accum & mask) == mask;
|
||||
}
|
||||
}
|
||||
|
||||
public static Function getFunction(int position, String name, RValue... args) throws NoSuchMethodException {
|
||||
final Method getter = getMethod(name, false, args);
|
||||
try {
|
||||
Method setter = getMethod(name, true, args);
|
||||
return new LValueFunction(position, getter, setter, args);
|
||||
} catch (NoSuchMethodException e) {
|
||||
return new Function(position, getter, args);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(String name, boolean isSetter, RValue... args) throws NoSuchMethodException {
|
||||
final List<Overload> overloads = functions.get(name);
|
||||
if (overloads != null) {
|
||||
for (Overload overload : overloads) {
|
||||
if (overload.matches(isSetter, args)) {
|
||||
return overload.method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new NoSuchMethodException(); // TODO: return null (check for side-effects first)
|
||||
}
|
||||
|
||||
private static final Map<String, List<Overload>> functions = new HashMap<String, List<Overload>>();
|
||||
static {
|
||||
for (Method method : Functions.class.getMethods()) {
|
||||
try {
|
||||
addFunction(method);
|
||||
} catch (IllegalArgumentException ignored) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void addFunction(Method method) throws IllegalArgumentException {
|
||||
final String methodName = method.getName();
|
||||
|
||||
Overload overload = new Overload(method);
|
||||
|
||||
List<Overload> overloads = functions.get(methodName);
|
||||
if (overloads == null) {
|
||||
functions.put(methodName, overloads = new ArrayList<Overload>());
|
||||
}
|
||||
|
||||
overloads.add(overload);
|
||||
}
|
||||
|
||||
|
||||
public static double sin(RValue x) throws EvaluationException {
|
||||
return Math.sin(x.getValue());
|
||||
}
|
||||
|
||||
public static double cos(RValue x) throws EvaluationException {
|
||||
return Math.cos(x.getValue());
|
||||
}
|
||||
|
||||
public static double tan(RValue x) throws EvaluationException {
|
||||
return Math.tan(x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double asin(RValue x) throws EvaluationException {
|
||||
return Math.asin(x.getValue());
|
||||
}
|
||||
|
||||
public static double acos(RValue x) throws EvaluationException {
|
||||
return Math.acos(x.getValue());
|
||||
}
|
||||
|
||||
public static double atan(RValue x) throws EvaluationException {
|
||||
return Math.atan(x.getValue());
|
||||
}
|
||||
|
||||
public static double atan2(RValue y, RValue x) throws EvaluationException {
|
||||
return Math.atan2(y.getValue(), x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double sinh(RValue x) throws EvaluationException {
|
||||
return Math.sinh(x.getValue());
|
||||
}
|
||||
|
||||
public static double cosh(RValue x) throws EvaluationException {
|
||||
return Math.cosh(x.getValue());
|
||||
}
|
||||
|
||||
public static double tanh(RValue x) throws EvaluationException {
|
||||
return Math.tanh(x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double sqrt(RValue x) throws EvaluationException {
|
||||
return Math.sqrt(x.getValue());
|
||||
}
|
||||
|
||||
public static double cbrt(RValue x) throws EvaluationException {
|
||||
return Math.cbrt(x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double abs(RValue x) throws EvaluationException {
|
||||
return Math.abs(x.getValue());
|
||||
}
|
||||
|
||||
public static double min(RValue a, RValue b) throws EvaluationException {
|
||||
return Math.min(a.getValue(), b.getValue());
|
||||
}
|
||||
|
||||
public static double min(RValue a, RValue b, RValue c) throws EvaluationException {
|
||||
return Math.min(a.getValue(), Math.min(b.getValue(), c.getValue()));
|
||||
}
|
||||
|
||||
public static double max(RValue a, RValue b) throws EvaluationException {
|
||||
return Math.max(a.getValue(), b.getValue());
|
||||
}
|
||||
|
||||
public static double max(RValue a, RValue b, RValue c) throws EvaluationException {
|
||||
return Math.max(a.getValue(), Math.max(b.getValue(), c.getValue()));
|
||||
}
|
||||
|
||||
|
||||
public static double ceil(RValue x) throws EvaluationException {
|
||||
return Math.ceil(x.getValue());
|
||||
}
|
||||
|
||||
public static double floor(RValue x) throws EvaluationException {
|
||||
return Math.floor(x.getValue());
|
||||
}
|
||||
|
||||
public static double rint(RValue x) throws EvaluationException {
|
||||
return Math.rint(x.getValue());
|
||||
}
|
||||
|
||||
public static double round(RValue x) throws EvaluationException {
|
||||
return Math.round(x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double exp(RValue x) throws EvaluationException {
|
||||
return Math.exp(x.getValue());
|
||||
}
|
||||
|
||||
public static double ln(RValue x) throws EvaluationException {
|
||||
return Math.log(x.getValue());
|
||||
}
|
||||
|
||||
public static double log(RValue x) throws EvaluationException {
|
||||
return Math.log(x.getValue());
|
||||
}
|
||||
|
||||
public static double log10(RValue x) throws EvaluationException {
|
||||
return Math.log10(x.getValue());
|
||||
}
|
||||
|
||||
|
||||
public static double rotate(LValue x, LValue y, RValue angle) throws EvaluationException {
|
||||
final double f = angle.getValue();
|
||||
|
||||
final double cosF = Math.cos(f);
|
||||
final double sinF = Math.sin(f);
|
||||
|
||||
final double xOld = x.getValue();
|
||||
final double yOld = y.getValue();
|
||||
|
||||
x.assign(xOld * cosF - yOld * sinF);
|
||||
y.assign(xOld * sinF + yOld * cosF);
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public static double swap(LValue x, LValue y) throws EvaluationException {
|
||||
final double tmp = x.getValue();
|
||||
|
||||
x.assign(y.getValue());
|
||||
y.assign(tmp);
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
private static final Map<Integer, double[]> gmegabuf = new HashMap<Integer, double[]>();
|
||||
private final Map<Integer, double[]> megabuf = new HashMap<Integer, double[]>();
|
||||
|
||||
public Map<Integer, double[]> getMegabuf() {
|
||||
return megabuf;
|
||||
}
|
||||
|
||||
private static double[] getSubBuffer(Map<Integer, double[]> megabuf, Integer key) {
|
||||
double[] ret = megabuf.get(key);
|
||||
if (ret == null) {
|
||||
megabuf.put(key, ret = new double[1024]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static double getBufferItem(final Map<Integer, double[]> megabuf, final int index) {
|
||||
return getSubBuffer(megabuf, index & ~1023)[index & 1023];
|
||||
}
|
||||
|
||||
private static double setBufferItem(final Map<Integer, double[]> megabuf, final int index, double value) {
|
||||
return getSubBuffer(megabuf, index & ~1023)[index & 1023] = value;
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double gmegabuf(RValue index) throws EvaluationException {
|
||||
return getBufferItem(gmegabuf, (int) index.getValue());
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double gmegabuf(RValue index, double value) throws EvaluationException {
|
||||
return setBufferItem(gmegabuf, (int) index.getValue(), value);
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double megabuf(RValue index) throws EvaluationException {
|
||||
return getBufferItem(Expression.getInstance().getFunctions().megabuf, (int) index.getValue());
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double megabuf(RValue index, double value) throws EvaluationException {
|
||||
return setBufferItem(Expression.getInstance().getFunctions().megabuf, (int) index.getValue(), value);
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double closest(RValue x, RValue y, RValue z, RValue index, RValue count, RValue stride) throws EvaluationException {
|
||||
return findClosest(
|
||||
Expression.getInstance().getFunctions().megabuf,
|
||||
x.getValue(),
|
||||
y.getValue(),
|
||||
z.getValue(),
|
||||
(int) index.getValue(),
|
||||
(int) count.getValue(),
|
||||
(int) stride.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double gclosest(RValue x, RValue y, RValue z, RValue index, RValue count, RValue stride) throws EvaluationException {
|
||||
return findClosest(
|
||||
gmegabuf,
|
||||
x.getValue(),
|
||||
y.getValue(),
|
||||
z.getValue(),
|
||||
(int) index.getValue(),
|
||||
(int) count.getValue(),
|
||||
(int) stride.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
private static double findClosest(Map<Integer, double[]> megabuf, double x, double y, double z, int index, int count, int stride) {
|
||||
int closestIndex = -1;
|
||||
double minDistanceSquared = Double.MAX_VALUE;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
double currentX = getBufferItem(megabuf, index+0) - x;
|
||||
double currentY = getBufferItem(megabuf, index+1) - y;
|
||||
double currentZ = getBufferItem(megabuf, index+2) - z;
|
||||
|
||||
double currentDistanceSquared = currentX*currentX + currentY*currentY + currentZ*currentZ;
|
||||
|
||||
if (currentDistanceSquared < minDistanceSquared) {
|
||||
minDistanceSquared = currentDistanceSquared;
|
||||
closestIndex = index;
|
||||
}
|
||||
|
||||
index += stride;
|
||||
}
|
||||
|
||||
return closestIndex;
|
||||
}
|
||||
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
@Dynamic
|
||||
public static double random() {
|
||||
return random.nextDouble();
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double randint(RValue max) throws EvaluationException {
|
||||
return random.nextInt((int) Math.floor(max.getValue()));
|
||||
}
|
||||
|
||||
private static final ThreadLocal<PerlinNoise> localPerlin = new ThreadLocal<PerlinNoise>() {
|
||||
@Override
|
||||
protected PerlinNoise initialValue() {
|
||||
return new PerlinNoise();
|
||||
}
|
||||
};
|
||||
|
||||
public static double perlin(RValue seed, RValue x, RValue y, RValue z, RValue frequency, RValue octaves, RValue persistence) throws EvaluationException {
|
||||
PerlinNoise perlin = localPerlin.get();
|
||||
try {
|
||||
perlin.setSeed((int) seed.getValue());
|
||||
perlin.setFrequency(frequency.getValue());
|
||||
perlin.setOctaveCount((int) octaves.getValue());
|
||||
perlin.setPersistence(persistence.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new EvaluationException(0, "Perlin noise error: " + e.getMessage());
|
||||
}
|
||||
return perlin.noise(new Vector(x.getValue(), y.getValue(), z.getValue()));
|
||||
}
|
||||
|
||||
private static final ThreadLocal<VoronoiNoise> localVoronoi = new ThreadLocal<VoronoiNoise>() {
|
||||
@Override
|
||||
protected VoronoiNoise initialValue() {
|
||||
return new VoronoiNoise();
|
||||
}
|
||||
};
|
||||
|
||||
public static double voronoi(RValue seed, RValue x, RValue y, RValue z, RValue frequency) throws EvaluationException {
|
||||
VoronoiNoise voronoi = localVoronoi.get();
|
||||
try {
|
||||
voronoi.setSeed((int) seed.getValue());
|
||||
voronoi.setFrequency(frequency.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new EvaluationException(0, "Voronoi error: " + e.getMessage());
|
||||
}
|
||||
return voronoi.noise(new Vector(x.getValue(), y.getValue(), z.getValue()));
|
||||
}
|
||||
|
||||
private static final ThreadLocal<RidgedMultiFractalNoise> localRidgedMulti = new ThreadLocal<RidgedMultiFractalNoise>() {
|
||||
@Override
|
||||
protected RidgedMultiFractalNoise initialValue() {
|
||||
return new RidgedMultiFractalNoise();
|
||||
}
|
||||
};
|
||||
|
||||
public static double ridgedmulti(RValue seed, RValue x, RValue y, RValue z, RValue frequency, RValue octaves) throws EvaluationException {
|
||||
RidgedMultiFractalNoise ridgedMulti = localRidgedMulti.get();
|
||||
try {
|
||||
ridgedMulti.setSeed((int) seed.getValue());
|
||||
ridgedMulti.setFrequency(frequency.getValue());
|
||||
ridgedMulti.setOctaveCount((int) octaves.getValue());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new EvaluationException(0, "Ridged multi error: " + e.getMessage());
|
||||
}
|
||||
return ridgedMulti.noise(new Vector(x.getValue(), y.getValue(), z.getValue()));
|
||||
}
|
||||
|
||||
private static double queryInternal(RValue type, RValue data, double typeId, double dataValue) throws EvaluationException {
|
||||
// Compare to input values and determine return value
|
||||
// -1 is a wildcard, always true
|
||||
final double ret = ((type.getValue() == -1 || typeId == type.getValue())
|
||||
&& (data.getValue() == -1 || dataValue == data.getValue())) ? 1.0 : 0.0;
|
||||
|
||||
if (type instanceof LValue) {
|
||||
((LValue) type).assign(typeId);
|
||||
}
|
||||
|
||||
if (data instanceof LValue) {
|
||||
((LValue) data).assign(dataValue);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double query(RValue x, RValue y, RValue z, RValue type, RValue data) throws EvaluationException {
|
||||
final double xp = x.getValue();
|
||||
final double yp = y.getValue();
|
||||
final double zp = z.getValue();
|
||||
|
||||
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
|
||||
|
||||
// Read values from world
|
||||
BaseBlock block = environment.getBlock(xp, yp, zp);
|
||||
int typeId = block.getId();
|
||||
int dataValue = block.getData();
|
||||
|
||||
return queryInternal(type, data, typeId, dataValue);
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double queryAbs(RValue x, RValue y, RValue z, RValue type, RValue data) throws EvaluationException {
|
||||
final double xp = x.getValue();
|
||||
final double yp = y.getValue();
|
||||
final double zp = z.getValue();
|
||||
|
||||
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
|
||||
|
||||
// Read values from world
|
||||
BaseBlock block = environment.getBlockAbs(xp, yp, zp);
|
||||
int typeId = block.getId();
|
||||
int dataValue = block.getData();
|
||||
|
||||
return queryInternal(type, data, typeId, dataValue);
|
||||
}
|
||||
|
||||
@Dynamic
|
||||
public static double queryRel(RValue x, RValue y, RValue z, RValue type, RValue data) throws EvaluationException {
|
||||
final double xp = x.getValue();
|
||||
final double yp = y.getValue();
|
||||
final double zp = z.getValue();
|
||||
|
||||
final ExpressionEnvironment environment = Expression.getInstance().getEnvironment();
|
||||
|
||||
// Read values from world
|
||||
BaseBlock block = environment.getBlockRel(xp, yp, zp);
|
||||
int typeId = block.getId();
|
||||
int dataValue = block.getData();
|
||||
|
||||
return queryInternal(type, data, typeId, dataValue);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Functions.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.regions.shape;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||
|
||||
public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
|
||||
|
||||
private final Vector unit;
|
||||
private final Vector zero2;
|
||||
private Vector current = new Vector();
|
||||
private EditSession editSession;
|
||||
|
||||
public WorldEditExpressionEnvironment(EditSession editSession, Vector unit, Vector zero) {
|
||||
this.editSession = editSession;
|
||||
this.unit = unit;
|
||||
this.zero2 = zero.add(0.5, 0.5, 0.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlock(double x, double y, double z) {
|
||||
x = x * unit.getX() + zero2.getX();
|
||||
y = y * unit.getY() + zero2.getY();
|
||||
z = z * unit.getZ() + zero2.getZ();
|
||||
return editSession.getBlock((int) x, (int) y, (int) z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockAbs(double x, double y, double z) {
|
||||
return editSession.getBlock((int) x, (int) y, (int) z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlockRel(double x, double y, double z) {
|
||||
x = x + current.getBlockX();
|
||||
y = y + current.getBlockY();
|
||||
z = z + current.getBlockZ();
|
||||
return editSession.getBlock((int) x, (int) y, (int) z);
|
||||
}
|
||||
|
||||
public void setCurrentBlock(Vector current) {
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return WorldEditExpressionEnvironment.class;
|
||||
}
|
||||
}
|
@ -19,10 +19,8 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
@ -75,11 +73,8 @@ public class FaweForge implements IFawe {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public void insertCommands() {
|
||||
for (Map.Entry<String, FaweCommand> entry : commands.entrySet()) {
|
||||
ServerCommandManager scm = (ServerCommandManager) FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
public HashMap<String, FaweCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@ -34,7 +36,9 @@ public class ForgeMain {
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
IMP.insertCommands();
|
||||
for (Map.Entry<String, FaweCommand> entry : IMP.getCommands().entrySet()) {
|
||||
event.registerServerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
|
@ -356,6 +356,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
|
@ -19,10 +19,8 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import net.minecraft.command.ServerCommandManager;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
@ -70,18 +68,15 @@ public class FaweForge implements IFawe {
|
||||
|
||||
private HashMap<String, FaweCommand> commands = new HashMap<>();
|
||||
|
||||
public HashMap<String, FaweCommand> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
this.commands.put(label, cmd);
|
||||
}
|
||||
|
||||
public void insertCommands() {
|
||||
for (Map.Entry<String, FaweCommand> entry : commands.entrySet()) {
|
||||
ServerCommandManager scm = (ServerCommandManager) FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager();
|
||||
scm.registerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
EntityPlayerMP player = null;
|
||||
|
@ -1,8 +1,10 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@ -33,7 +35,9 @@ public class ForgeMain {
|
||||
|
||||
@Mod.EventHandler
|
||||
public void serverLoad(FMLServerStartingEvent event) {
|
||||
IMP.insertCommands();
|
||||
for (Map.Entry<String, FaweCommand> entry : IMP.getCommands().entrySet()) {
|
||||
event.registerServerCommand(new ForgeCommand(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
|
@ -379,6 +379,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import com.boydti.fawe.forge.MutableGenLayer;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.brush.visualization.VisualChunk;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
@ -30,6 +29,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
@ -131,7 +131,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
}
|
||||
if (id > 255) {
|
||||
NibbleArray nibble = extended[i];
|
||||
if (extended == null) {
|
||||
if (nibble == null) {
|
||||
extended[i] = nibble = new NibbleArray(4096, 4);
|
||||
}
|
||||
nibble.set(x, y & 15, z, id >> 8);
|
||||
@ -315,6 +315,12 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
continue;
|
||||
case 1:
|
||||
currentIdArray[k] = 0;
|
||||
if (extra) {
|
||||
int x = FaweCache.CACHE_X[0][k];
|
||||
int y = FaweCache.CACHE_Y[0][k];
|
||||
int z = FaweCache.CACHE_Z[0][k];
|
||||
currentExtraArray.set(x, y, z, 0);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
solid++;
|
||||
|
@ -166,10 +166,18 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
|
||||
byte[] ids = ls.getBlockLSBArray();
|
||||
NibbleArray datasNibble = ls.getBlockMSBArray();
|
||||
NibbleArray currentDataArray = ls.getMetadataArray();
|
||||
NibbleArray currentExtraArray = ls.getBlockMSBArray();
|
||||
int i = FaweCache.CACHE_J[y & 15][z & 15][x & 15];
|
||||
int combined = ((ids[i] & 0xFF) << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15));
|
||||
return combined;
|
||||
int id = (ids[i] & 0xFF);
|
||||
if (currentExtraArray != null) {
|
||||
id += (currentExtraArray.get(x & 15, y & 15, z & 15)) << 8;
|
||||
}
|
||||
if (currentDataArray != null && FaweCache.hasData(id)) {
|
||||
return (id << 4) + currentDataArray.get(x & 15, y & 15, z & 15);
|
||||
} else {
|
||||
return (id << 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -354,6 +354,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
sectionPalettes = null;
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user