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:
Jesse Boyd 2017-05-21 23:40:24 +10:00
parent ef6ad05c2e
commit 31d43b27d8
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
35 changed files with 1664 additions and 48 deletions

View File

@ -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++) {

View File

@ -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) {}
}

View File

@ -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"));
}
}
}

View File

@ -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

View File

@ -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"),

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<>();

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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));
}

View File

@ -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

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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), &gt;&gt;, &lt;&lt;</li>
* <li>Arithmetic: +, -, *, /, % (modulo), ^ (power), - (unary), --, ++ (prefix only)</li>
* <li>Comparison: &lt;=, &gt;=, &gt;, &lt;, ==, !=, ~= (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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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++;

View File

@ -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

View File

@ -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);
}