Future proofing

This is working towards making sure all parts of FAWE will work on newer
versions of minecraft without the plugin needing to update. (it'll still
be slower until proper support is added)
- Adds version agnostic bukkit adapter
- Adds version agnostic bukkit anvil mode
This commit is contained in:
Jesse Boyd 2017-08-13 12:38:19 +10:00
parent 113c625122
commit 92bf3f702b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
21 changed files with 787 additions and 86 deletions

View File

@ -491,6 +491,8 @@ public class FaweBukkit implements IFawe, Listener {
v1_10_R1,
v1_11_R1,
v1_12_R1,
v1_12_R2,
v1_13_R1,
NONE,
}

View File

@ -208,7 +208,7 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
int x = cacheX[m];
int z = cacheZ[m];
int id = combined >> 4;
if (FaweCache.hasNBT(id) && parent.adapter != null) {
if (FaweCache.hasNBT(id) && parent.getAdapter() != null) {
CompoundTag nbt = getTile(x, y, z);
if (nbt != null) {
if (mutableLoc == null) mutableLoc = new Location(world, 0, 0, 0);
@ -216,7 +216,7 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
mutableLoc.setY(y);
mutableLoc.setZ(bz + z);
synchronized (BukkitChunk_All.this) {
parent.adapter.setBlock(mutableLoc, new BaseBlock(id, combined & 0xF, nbt), false);
parent.getAdapter().setBlock(mutableLoc, new BaseBlock(id, combined & 0xF, nbt), false);
}
continue;
}
@ -276,10 +276,10 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
int x = cacheX[j];
int z = cacheZ[j];
int y = cacheY[j];
if (FaweCache.hasNBT(id) && parent.adapter != null) {
if (FaweCache.hasNBT(id) && parent.getAdapter() != null) {
CompoundTag tile = getTile(x, y, z);
if (tile != null) {
parent.adapter.setBlock(new Location(world, bx + x, y, bz + z), new BaseBlock(id, combined & 0xF, tile), false);
parent.getAdapter().setBlock(new Location(world, bx + x, y, bz + z), new BaseBlock(id, combined & 0xF, tile), false);
break;
}
}

View File

@ -12,11 +12,13 @@ import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
@ -37,9 +39,10 @@ import org.bukkit.event.world.WorldInitEvent;
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> implements Listener {
public static BukkitImplAdapter adapter;
public static Method methodToNative;
public static Method methodFromNative;
private static BukkitImplAdapter adapter;
private static FaweAdapter_All backupAdaper;
private static Method methodToNative;
private static Method methodFromNative;
private static boolean setupAdapter = false;
public BukkitQueue_0(final com.sk89q.worldedit.world.World world) {
@ -62,9 +65,38 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static BukkitImplAdapter getAdapter() {
if (adapter == null) setupAdapter(null);
if (adapter == null) return backupAdaper;
return adapter;
}
public static Tag toNative(Object tag) {
BukkitImplAdapter adapter = getAdapter();
if (adapter == null) {
if (backupAdaper != null) return backupAdaper.toNative(tag);
return null;
}
try {
return (Tag) methodToNative.invoke(adapter, tag);
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static Object fromNative(Tag tag) {
BukkitImplAdapter adapter = getAdapter();
if (adapter == null) {
if (backupAdaper != null) return backupAdaper.fromNative(tag);
return null;
}
try {
return methodFromNative.invoke(adapter, tag);
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public File getSaveFolder() {
return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region");
@ -152,37 +184,46 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
public static void setupAdapter(BukkitImplAdapter adapter) {
try {
if (setupAdapter == (setupAdapter = true)) {
if (adapter == null && setupAdapter == (setupAdapter = true)) {
return;
}
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
fieldAdapter.setAccessible(true);
if ((BukkitQueue_0.adapter = adapter) != null) {
if (adapter != null) {
BukkitQueue_0.adapter = adapter;
fieldAdapter.set(instance, adapter);
} else {
BukkitQueue_0.adapter = adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
}
for (Method method : adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;
methodToNative.setAccessible(true);
break;
case "fromNative":
methodFromNative = method;
methodFromNative.setAccessible(true);
break;
if (adapter != null) {
for (Method method : adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;
methodToNative.setAccessible(true);
break;
case "fromNative":
methodFromNative = method;
methodFromNative.setAccessible(true);
break;
}
}
}
return;
} catch (Throwable ignore) {
ignore.printStackTrace();
}
if (BukkitQueue_0.adapter == null) {
if (backupAdaper == null) {
try {
backupAdaper = new FaweAdapter_All();
Fawe.debug("Native adapter failed. Backup adapter is functional.");
} catch (Throwable ignore) {
Fawe.debug("Native and backup adapter failed! (Try updating the plugin)");
ignore.printStackTrace();
}
}
} catch (Throwable e) {
setupAdapter = false;
Fawe.debug("====== NO NATIVE WORLDEDIT ADAPTER ======");
e.printStackTrace();
Fawe.debug("Try updating WorldEdit: ");
Fawe.debug(" - http://builds.enginehub.org/job/worldedit?branch=master");
Fawe.debug("See also: http://wiki.sk89q.com/wiki/WorldEdit/Bukkit_adapters");
Fawe.debug("=========================================");
}
}

View File

@ -3,11 +3,20 @@ package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.Map;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location;
@ -37,6 +46,138 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
}
}
private static Class<?> classRegionFileCache;
private static Class<?> classRegionFile;
private static Class<?> classCraftChunk;
private static Class<?> classCraftWorld;
private static Class<?> classNMSChunk;
private static Class<?> classNMSWorld;
private static Class<?> classChunkProviderServer;
private static Class<?> classIChunkLoader;
private static Class<?> classChunkRegionLoader;
private static Class<?> classIChunkProvider;
private static Method methodGetHandleChunk;
private static Method methodGetHandleWorld;
private static Method methodFlush;
private static Method methodNeedsSaving;
private static Field fieldChunkProvider;
private static Field fieldChunkLoader;
private static Field fieldRegionMap;
private static Field fieldRegionRAF;
static {
try {
ReflectionUtils.init();
classRegionFileCache = ReflectionUtils.getNmsClass("RegionFileCache");
classRegionFile = ReflectionUtils.getNmsClass("RegionFile");
classCraftChunk = ReflectionUtils.getCbClass("CraftChunk");
classNMSChunk = ReflectionUtils.getNmsClass("Chunk");
classCraftWorld = ReflectionUtils.getCbClass("CraftWorld");
classNMSWorld = ReflectionUtils.getNmsClass("World");
classChunkProviderServer = ReflectionUtils.getNmsClass("ChunkProviderServer");
classIChunkProvider = ReflectionUtils.getNmsClass("IChunkProvider");
classIChunkLoader = ReflectionUtils.getNmsClass("IChunkLoader");
classChunkRegionLoader = ReflectionUtils.getNmsClass("ChunkRegionLoader");
methodGetHandleChunk = ReflectionUtils.setAccessible(classCraftChunk.getDeclaredMethod("getHandle"));
methodGetHandleWorld = ReflectionUtils.setAccessible(classCraftWorld.getDeclaredMethod("getHandle"));
methodFlush = ReflectionUtils.findMethod(classChunkRegionLoader, boolean.class);
methodNeedsSaving = ReflectionUtils.findMethod(classNMSChunk, boolean.class, boolean.class);
fieldChunkProvider = ReflectionUtils.findField(classNMSWorld, classIChunkProvider);
fieldChunkLoader = ReflectionUtils.findField(classChunkProviderServer, classIChunkLoader);
fieldRegionMap = ReflectionUtils.findField(classRegionFileCache, Map.class);
fieldRegionRAF = ReflectionUtils.findField(classRegionFile, RandomAccessFile.class);
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
@Override
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper allowed, Runnable whileLocked, boolean load) {
if (classRegionFileCache == null) {
return super.setMCA(mcaX, mcaZ, allowed, whileLocked, load);
}
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
long start = System.currentTimeMillis();
long last = start;
synchronized (classRegionFileCache) {
try {
World world = getWorld();
boolean autoSave = world.isAutoSave();
if (world.getKeepSpawnInMemory()) world.setKeepSpawnInMemory(false);
ArrayDeque<Chunk> unloaded = null;
if (load) {
int bcx = mcaX << 5;
int bcz = mcaZ << 5;
int tcx = bcx + 31;
int tcz = bcz + 31;
for (Chunk chunk : world.getLoadedChunks()) {
int cx = chunk.getX();
int cz = chunk.getZ();
if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) {
Object nmsChunk = methodGetHandleChunk.invoke(chunk);
boolean mustSave = (boolean) methodNeedsSaving.invoke(nmsChunk, false);
chunk.unload(mustSave, false);
if (unloaded == null) unloaded = new ArrayDeque<Chunk>();
unloaded.add(chunk);
}
}
} else {
world.save();
}
Object nmsWorld = methodGetHandleWorld.invoke(world);
Object chunkProviderServer = fieldChunkProvider.get(nmsWorld);
Object chunkRegionLoader = fieldChunkLoader.get(chunkProviderServer);
while ((boolean) methodFlush.invoke(chunkRegionLoader));
if (unloaded != null) {
Map regionMap = (Map) fieldRegionMap.get(null);
File file = new File(world.getWorldFolder(), "region" + File.separator + "r." + mcaX + "." + mcaZ + ".mca");
Object regionFile = regionMap.remove(file);
if (regionFile != null) {
RandomAccessFile raf = (RandomAccessFile) fieldRegionRAF.get(regionFile);
raf.close();
}
}
whileLocked.run();
if (load && unloaded != null) {
final ArrayDeque<Chunk> finalUnloaded = unloaded;
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
for (Chunk chunk : finalUnloaded) {
int cx = chunk.getX();
int cz = chunk.getZ();
if (world.isChunkLoaded(cx, cz)) continue;
SetQueue.IMP.addTask(() -> {
world.loadChunk(chunk.getX(), chunk.getZ(), false);
world.refreshChunk(chunk.getX(), chunk.getZ());
});
}
}
});
// load chunks
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
});
return true;
}
@Override
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
// Not supported
@ -69,7 +210,7 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
@Override
public int getBiome(ChunkSnapshot chunkSnapshot, int x, int z) {
Biome biome = chunkSnapshot.getBiome(x & 15, z & 15);
return adapter.getBiomeId(biome);
return getAdapter().getBiomeId(biome);
}
@Override
@ -132,11 +273,11 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
@Override
public CompoundTag getTileEntity(ChunkSnapshot chunk, int x, int y, int z) {
if (adapter == null) {
if (getAdapter() == null) {
return null;
}
Location loc = new Location(getWorld(), x, y, z);
BaseBlock block = adapter.getBlock(loc);
BaseBlock block = getAdapter().getBlock(loc);
return block != null ? block.getNbtData() : null;
}

View File

@ -0,0 +1,451 @@
package com.boydti.fawe.bukkit.v0;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.internal.Constants;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
public class FaweAdapter_All implements BukkitImplAdapter {
private final Class<?> classCraftBlock;
private final Method biomeToBiomeBase;
private final Class<?> classBiomeBase;
private final Method biomeBaseToTypeId;
private final Method getBiome;
private final Method biomeBaseToBiome;
private final Class<?> classCraftWorld;
private final Method getHandleWorld;
private final Class<?> classWorld;
private final Method getTileEntity1;
private final Method getTileEntity2;
private final Class<?> classNBTTagCompound;
private final Constructor<?> newNBTTagCompound;
private final Class<?> classTileEntity;
private final Class<?> classCraftEntity;
private final Method getHandleEntity;
private final Class<?> classNBTTagInt;
private final Class<?> classNBTBase;
private final Constructor<?> newNBTTagInt;
private final Method setNBTTagCompound;
private Class<?> classEntity;
private Method getBukkitEntity;
private Method addEntity;
private Method setLocation;
private Class<?> classEntityTypes;
private Method getEntityId;
private Method createEntityFromId;
private Method readTagIntoEntity;
private Method readEntityIntoTag;
private Constructor<?> newMinecraftKey;
private Class<?> classMinecraftKey;
private Method readTagIntoTileEntity;
private Method readTileEntityIntoTag;
private Class<?> classBlockPosition;
private Constructor<?> newBlockPosition;
private Map<Class<? extends Tag>, NMSTagConstructor> WEToNMS = new ConcurrentHashMap<>();
private Map<Class, WETagConstructor> NMSToWE = new ConcurrentHashMap<>();
private Map<Class<? extends Tag>, Integer> TagToId = new ConcurrentHashMap<>();
public FaweAdapter_All() throws Throwable {
ReflectionUtils.init();
classCraftWorld = ReflectionUtils.getCbClass("CraftWorld");
classCraftBlock = ReflectionUtils.getCbClass("block.CraftBlock");
classCraftEntity = ReflectionUtils.getCbClass("entity.CraftEntity");
classBiomeBase = ReflectionUtils.getNmsClass("BiomeBase");
classWorld = ReflectionUtils.getNmsClass("World");
classTileEntity = ReflectionUtils.getNmsClass("TileEntity");
biomeToBiomeBase = ReflectionUtils.setAccessible(classCraftBlock.getDeclaredMethod("biomeToBiomeBase", Biome.class));
biomeBaseToBiome = ReflectionUtils.setAccessible(classCraftBlock.getDeclaredMethod("biomeBaseToBiome", classBiomeBase));
getBiome = ReflectionUtils.setAccessible(classBiomeBase.getDeclaredMethod("getBiome", int.class));
biomeBaseToTypeId = ReflectionUtils.findMethod(classBiomeBase, int.class, classBiomeBase);
getHandleWorld = ReflectionUtils.setAccessible(classCraftWorld.getDeclaredMethod("getHandle"));
getHandleEntity = ReflectionUtils.setAccessible(classCraftEntity.getDeclaredMethod("getHandle"));
try {
classBlockPosition = ReflectionUtils.getNmsClass("BlockPosition");
} catch (Throwable ignore) {
}
if (classBlockPosition != null) {
getTileEntity1 = classWorld.getDeclaredMethod("getTileEntity", classBlockPosition);
getTileEntity2 = null;
newBlockPosition = ReflectionUtils.setAccessible(classBlockPosition.getConstructor(int.class, int.class, int.class));
} else {
getTileEntity1 = null;
getTileEntity2 = ReflectionUtils.setAccessible(classWorld.getDeclaredMethod("getTileEntity", int.class, int.class, int.class));
}
classNBTTagCompound = ReflectionUtils.getNmsClass("NBTTagCompound");
classNBTBase = ReflectionUtils.getNmsClass("NBTBase");
classNBTTagInt = ReflectionUtils.getNmsClass("NBTTagInt");
newNBTTagInt = ReflectionUtils.setAccessible(classNBTTagInt.getConstructor(int.class));
setNBTTagCompound = ReflectionUtils.setAccessible(classNBTTagCompound.getDeclaredMethod("set", String.class, classNBTBase));
newNBTTagCompound = ReflectionUtils.setAccessible(classNBTTagCompound.getConstructor());
try {
readTileEntityIntoTag = ReflectionUtils.setAccessible(classTileEntity.getDeclaredMethod("save", classNBTTagCompound));
} catch (Throwable ignore) {
readTileEntityIntoTag = ReflectionUtils.findMethod(classTileEntity, classNBTTagCompound, classNBTTagCompound);
if (readTileEntityIntoTag == null) {
readTileEntityIntoTag = ReflectionUtils.findMethod(classTileEntity, 1, Void.TYPE, classNBTTagCompound);
}
}
try {
readTagIntoTileEntity = ReflectionUtils.setAccessible(classTileEntity.getDeclaredMethod("load", classNBTTagCompound));
} catch (Throwable ignore) {
readTagIntoTileEntity = ReflectionUtils.findMethod(classTileEntity, 0, Void.TYPE, classNBTTagCompound);
}
List<String> nmsClasses = Arrays.asList("NBTTagCompound", "NBTTagByte", "NBTTagByteArray", "NBTTagDouble", "NBTTagFloat", "NBTTagInt", "NBTTagIntArray", "NBTTagList", "NBTTagEnd", "NBTTagString", "NBTTagShort", "NBTTagLong");
List<Class<? extends Tag>> weClasses = Arrays.asList(CompoundTag.class, ByteTag.class, ByteArrayTag.class, DoubleTag.class, FloatTag.class, IntTag.class, IntArrayTag.class, ListTag.class, EndTag.class, StringTag.class, ShortTag.class, LongTag.class);
int[] ids = new int[]{10, 1, 7, 6, 5, 3, 11, 9, 0, 8, 2, 4};
int noMods = Modifier.STATIC;
int hasMods = Modifier.PRIVATE;
for (int i = 0; i < nmsClasses.size(); i++) {
Class<?> nmsClass = ReflectionUtils.getNmsClass(nmsClasses.get(i));
Class<? extends Tag> weClass = weClasses.get(i);
TagToId.put(weClass, ids[i]);
Constructor nmsConstructor = ReflectionUtils.setAccessible(nmsClass.getDeclaredConstructor());
if (weClass == EndTag.class) {
NMSToWE.put(nmsClass, value -> new EndTag());
WEToNMS.put(weClass, value -> nmsConstructor.newInstance());
} else if (weClass == CompoundTag.class) {
Field mapField = ReflectionUtils.findField(nmsClass, Map.class, hasMods, noMods);
Constructor<? extends Tag> weConstructor = ReflectionUtils.setAccessible(CompoundTag.class.getConstructor(Map.class));
NMSToWE.put(nmsClass, value -> {
Map<String, Object> map = (Map) mapField.get(value);
Map<String, Tag> weMap = new HashMap<String, Tag>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
weMap.put(entry.getKey(), toNative(entry.getValue()));
}
return new CompoundTag(weMap);
});
WEToNMS.put(weClass, value -> {
Map<String, Tag> map = ReflectionUtils.getMap(((CompoundTag) value).getValue());
Object nmsTag = nmsConstructor.newInstance();
Map<String, Object> nmsMap = (Map<String, Object>) mapField.get(nmsTag);
for (Map.Entry<String, Tag> entry : map.entrySet()) {
nmsMap.put(entry.getKey(), fromNative(entry.getValue()));
}
return nmsTag;
});
} else if (weClass == ListTag.class) {
Field listField = ReflectionUtils.findField(nmsClass, List.class, hasMods, noMods);
Field typeField = ReflectionUtils.findField(nmsClass, byte.class, hasMods, noMods);
Constructor<? extends Tag> weConstructor = ReflectionUtils.setAccessible(ListTag.class.getConstructor(Class.class, List.class));
NMSToWE.put(nmsClass, tag -> {
int type = ((Number) typeField.get(tag)).intValue();
List list = (List) listField.get(tag);
Class<? extends Tag> weType = NBTConstants.getClassFromType(type);
ArrayList<Tag> weList = new ArrayList<>();
for (Object nmsTag : list) {
weList.add(toNative(nmsTag));
}
return new ListTag(weType, weList);
});
WEToNMS.put(weClass, tag -> {
ListTag lt = (ListTag) tag;
List<Tag> list = ReflectionUtils.getList(lt.getValue());
Class<? extends Tag> type = lt.getType();
int typeId = TagToId.get(type);
Object nmsTagList = nmsConstructor.newInstance();
typeField.set(nmsTagList, (byte) typeId);
ArrayList<Object> nmsList = (ArrayList<Object>) listField.get(nmsTagList);
for (Tag weTag : list) {
nmsList.add(fromNative(weTag));
}
return nmsTagList;
});
} else {
Field typeField = ReflectionUtils.findField(nmsClass, null, hasMods, noMods);
Constructor<? extends Tag> weConstructor = ReflectionUtils.setAccessible(weClass.getConstructor(typeField.getType()));
NMSToWE.put(nmsClass, tag -> {
Object value = typeField.get(tag);
return weConstructor.newInstance(value);
});
WEToNMS.put(weClass, tag -> {
Object nmsTag = nmsConstructor.newInstance();
typeField.set(nmsTag, tag.getValue());
return nmsTag;
});
}
}
try {
classEntity = ReflectionUtils.getNmsClass("Entity");
classEntityTypes = ReflectionUtils.getNmsClass("EntityTypes");
getBukkitEntity = ReflectionUtils.setAccessible(classEntity.getDeclaredMethod("getBukkitEntity"));
addEntity = ReflectionUtils.setAccessible(classWorld.getDeclaredMethod("addEntity", classEntity));
setLocation = ReflectionUtils.setAccessible(classEntity.getDeclaredMethod("setLocation", double.class, double.class, double.class, float.class, float.class));
try {
classMinecraftKey = ReflectionUtils.getNmsClass("MinecraftKey");
newMinecraftKey = classMinecraftKey.getConstructor(String.class);
} catch (Throwable ignore) {
}
if (classMinecraftKey != null) {
getEntityId = ReflectionUtils.findMethod(classEntityTypes, classMinecraftKey, classEntity);
createEntityFromId = ReflectionUtils.findMethod(classEntityTypes, classEntity, classMinecraftKey, classWorld);
} else {
getEntityId = ReflectionUtils.findMethod(classEntityTypes, String.class, classEntity);
createEntityFromId = ReflectionUtils.findMethod(classEntityTypes, classEntity, String.class, classWorld);
}
noMods = Modifier.ABSTRACT | Modifier.PROTECTED | Modifier.PRIVATE;
try {
readEntityIntoTag = classEntity.getDeclaredMethod("save", classNBTTagCompound);
} catch (Throwable ignore) {
readEntityIntoTag = ReflectionUtils.findMethod(classEntity, classNBTTagCompound, classNBTTagCompound);
if (readEntityIntoTag == null) {
readEntityIntoTag = ReflectionUtils.findMethod(classEntity, 0, 0, noMods, Void.TYPE, classNBTTagCompound);
}
}
ReflectionUtils.setAccessible(readEntityIntoTag);
readTagIntoEntity = ReflectionUtils.findMethod(classEntity, 1, 0, noMods, Void.TYPE, classNBTTagCompound);
if (readTagIntoEntity == null) {
readTagIntoEntity = ReflectionUtils.findMethod(classEntity, 0, 0, noMods, Void.TYPE, classNBTTagCompound);
}
} catch (Throwable e) {
e.printStackTrace();
classEntity = null;
}
}
@Nullable
@Override
public BaseEntity getEntity(Entity entity) {
try {
if (classEntity == null) return null;
Object nmsEntity = getHandleEntity.invoke(entity);
String id = getEntityId(nmsEntity);
if (id != null) {
Object tag = newNBTTagCompound.newInstance();
readEntityIntoTag.invoke(nmsEntity, tag);
return new BaseEntity(id, (CompoundTag) toNative(tag));
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
return null;
}
private String getEntityId(Object entity) throws InvocationTargetException, IllegalAccessException {
Object res = getEntityId.invoke(null, entity);
return res == null ? null : res.toString();
}
private Object createEntityFromId(String id, Object world) throws InvocationTargetException, IllegalAccessException, InstantiationException {
if (classMinecraftKey != null) {
Object key = newMinecraftKey.newInstance(id);
return createEntityFromId.invoke(null, key, world);
} else {
return createEntityFromId.invoke(null, id, world);
}
}
@Nullable
@Override
public Entity createEntity(Location location, BaseEntity state) {
try {
if (classEntity == null) return null;
World world = location.getWorld();
Object nmsWorld = getHandleWorld.invoke(world);
Object createdEntity = createEntityFromId(state.getTypeId(), nmsWorld);
if (createdEntity != null) {
CompoundTag nativeTag = state.getNbtData();
Map<String, Tag> rawMap = ReflectionUtils.getMap(nativeTag.getValue());
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
rawMap.remove(name);
}
if (nativeTag != null) {
Object tag = fromNative(nativeTag);
readTagIntoEntity.invoke(createdEntity, tag);
}
setLocation.invoke(createdEntity, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
addEntity.invoke(nmsWorld, createdEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
return (Entity) getBukkitEntity.invoke(createdEntity);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
return null;
}
public Tag toNative(Object nmsTag) {
try {
return NMSToWE.get(nmsTag.getClass()).construct(nmsTag);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object fromNative(Tag tag) {
try {
return WEToNMS.get(tag.getClass()).construct(tag);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public int getBlockId(Material material) {
return material.getId();
}
@Override
public Material getMaterial(int id) {
return Material.getMaterial(id);
}
@Override
public int getBiomeId(Biome biome) {
try {
Object biomeBase = biomeToBiomeBase.invoke(null, biome);
if (biomeBase != null) return (int) biomeBaseToTypeId.invoke(null, biomeBase);
} catch (Throwable e) {
throw new RuntimeException(e);
}
return 0;
}
@Override
public Biome getBiome(int id) {
try {
Object biomeBase = getBiome.invoke(null, id);
if (biomeBase != null) return (Biome) biomeBaseToBiome.invoke(null, biomeBase);
} catch (Throwable e) {
throw new RuntimeException(e);
}
return Biome.OCEAN;
}
@Override
public BaseBlock getBlock(Location location) {
try {
World craftWorld = location.getWorld();
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
org.bukkit.block.Block bukkitBlock = location.getBlock();
BaseBlock block = FaweCache.getBlock(bukkitBlock.getTypeId(), bukkitBlock.getData());
// Read the NBT data
Object nmsWorld = getHandleWorld.invoke(craftWorld);
Object tileEntity = getTileEntity(nmsWorld, x, y, z);
if (tileEntity != null) {
block = new BaseBlock(block);
Object tag = newNBTTagCompound.newInstance();
readTileEntityIntoTag.invoke(tileEntity, tag);
block.setNbtData((CompoundTag) toNative(tag));
}
return block;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
public Object getTileEntity(Object nmsWorld, int x, int y, int z) {
try {
if (getTileEntity1 != null) {
Object pos = newBlockPosition.newInstance(x, y, z);
return getTileEntity1.invoke(nmsWorld, pos);
} else {
return getTileEntity2.invoke(nmsWorld, x, y, z);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public boolean setBlock(Location location, BaseBlock block, boolean notifyAndLight) {
World craftWorld = location.getWorld();
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
boolean changed = location.getBlock().setTypeIdAndData(block.getId(), (byte) block.getData(), notifyAndLight);
CompoundTag nativeTag = block.getNbtData();
if (nativeTag != null) {
try {
Object nmsWorld = getHandleWorld.invoke(craftWorld);
Object tileEntity = getTileEntity(nmsWorld, x, y, z);
if (tileEntity != null) {
Object tag = fromNative(nativeTag);
setNBTTagCompound.invoke(tag, "x", newNBTTagInt.newInstance(x));
setNBTTagCompound.invoke(tag, "y", newNBTTagInt.newInstance(y));
setNBTTagCompound.invoke(tag, "z", newNBTTagInt.newInstance(z));
readTagIntoTileEntity.invoke(tileEntity, tag); // Load data
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
return changed;
}
private interface NMSTagConstructor {
Object construct(Tag value) throws Exception;
}
private interface WETagConstructor {
Tag construct(Object value) throws Exception;
}
}

View File

@ -198,7 +198,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) getParent().methodToNative.invoke(getParent().adapter, tag);
CompoundTag nativeTag = (CompoundTag) getParent().toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
setEntity(nativeTag);
@ -321,7 +321,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_10.methodFromNative.invoke(BukkitQueue_1_10.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_10.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -474,7 +474,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
net.minecraft.server.v1_10_R1.BlockPosition pos = new net.minecraft.server.v1_10_R1.BlockPosition(x, y, z); // Set pos
net.minecraft.server.v1_10_R1.TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
net.minecraft.server.v1_10_R1.NBTTagCompound tag = (net.minecraft.server.v1_10_R1.NBTTagCompound) com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10.methodFromNative.invoke(com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10.adapter, nativeTag);
net.minecraft.server.v1_10_R1.NBTTagCompound tag = (net.minecraft.server.v1_10_R1.NBTTagCompound) com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -140,7 +140,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
getEntitySlices = net.minecraft.server.v1_10_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
setupAdapter(new com.boydti.fawe.bukkit.v1_10.FaweAdapter_1_10());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("Using adapter: " + getAdapter());
Fawe.debug("=========================================");
for (int i = 0; i < IBD_CACHE.length; i++) {
try {
@ -212,7 +212,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
nmsWorld.worldData.getSeed();
boolean result;
ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
BiomeBase base = BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new BiomeBase[]{base});
boolean cold = base.getTemperature() <= 1;
@ -803,7 +803,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -829,7 +829,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
try {
NBTTagCompound tag = new NBTTagCompound();
tile.save(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -90,7 +90,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) getParent().methodToNative.invoke(getParent().adapter, tag);
CompoundTag nativeTag = (CompoundTag) getParent().toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
setEntity(nativeTag);
@ -330,7 +330,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_11.methodFromNative.invoke(BukkitQueue_1_11.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_11.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -484,7 +484,7 @@ public class BukkitChunk_1_11 extends CharFaweChunk<Chunk, com.boydti.fawe.bukki
BlockPosition pos = new BlockPosition(x, y, z); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.methodFromNative.invoke(com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -138,7 +138,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
getEntitySlices = net.minecraft.server.v1_11_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
setupAdapter(new com.boydti.fawe.bukkit.v1_11.FaweAdapter_1_11());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("Using adapter: " + getAdapter());
Fawe.debug("=========================================");
for (int i = 0; i < IBD_CACHE.length; i++) {
try {
@ -210,7 +210,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
nmsWorld.worldData.getSeed();
boolean result;
ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
BiomeBase base = BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new BiomeBase[]{base});
boolean cold = base.getTemperature() <= 1;
@ -805,7 +805,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -831,7 +831,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
try {
NBTTagCompound tag = new NBTTagCompound();
tile.save(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -78,7 +78,7 @@ public class BukkitChunk_1_12 extends CharFaweChunk<Chunk, BukkitQueue_1_12> {
}
public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException {
if (ent instanceof EntityPlayer || BukkitQueue_0.adapter == null) {
if (ent instanceof EntityPlayer || BukkitQueue_0.getAdapter() == null) {
return false;
}
int x = ((int) Math.round(ent.locX) & 15);
@ -90,7 +90,7 @@ public class BukkitChunk_1_12 extends CharFaweChunk<Chunk, BukkitQueue_1_12> {
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.save(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.methodToNative.invoke(getParent().adapter, tag);
CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
setEntity(nativeTag);
@ -330,7 +330,7 @@ public class BukkitChunk_1_12 extends CharFaweChunk<Chunk, BukkitQueue_1_12> {
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -484,7 +484,7 @@ public class BukkitChunk_1_12 extends CharFaweChunk<Chunk, BukkitQueue_1_12> {
BlockPosition pos = new BlockPosition(x, y, z); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -156,7 +156,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
getEntitySlices = net.minecraft.server.v1_12_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
setupAdapter(new FaweAdapter_1_12());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("Using adapter: " + getAdapter());
Fawe.debug("=========================================");
for (int i = 0; i < IBD_CACHE.length; i++) {
try {
@ -228,7 +228,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
nmsWorld.worldData.getSeed();
boolean result;
ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
BiomeBase base = BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new BiomeBase[]{base});
boolean cold = base.getTemperature() <= 1;
@ -820,7 +820,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.save(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -846,7 +846,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
try {
NBTTagCompound tag = new NBTTagCompound();
tile.save(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -237,7 +237,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
if (entity != null) {
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -446,7 +446,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
int z = (blockHash >> 8 & 0xF) + bz;
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -253,7 +253,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
nmsWorld.worldData.getSeed();
boolean result;
net.minecraft.server.v1_7_R4.ChunkProviderGenerate generator = new net.minecraft.server.v1_7_R4.ChunkProviderGenerate(nmsWorld, seed, false);
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
net.minecraft.server.v1_7_R4.BiomeBase base = net.minecraft.server.v1_7_R4.BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new net.minecraft.server.v1_7_R4.BiomeBase[]{base});
net.minecraft.server.v1_7_R4.IChunkProvider existingGenerator = nmsWorld.chunkProviderServer.chunkProvider;
@ -420,7 +420,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -436,7 +436,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
try {
NBTTagCompound tag = new NBTTagCompound();
tile.b(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -167,7 +167,7 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
if (entity != null) {
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -307,7 +307,7 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
BlockPosition pos = new BlockPosition(x, y, z); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -251,7 +251,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
nmsWorld.worldData.getSeed();
boolean result;
net.minecraft.server.v1_8_R3.ChunkProviderGenerate generator = new net.minecraft.server.v1_8_R3.ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
net.minecraft.server.v1_8_R3.BiomeBase base = net.minecraft.server.v1_8_R3.BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new net.minecraft.server.v1_8_R3.BiomeBase[]{base});
IChunkProvider existingGenerator = nmsWorld.chunkProviderServer.chunkProvider;
@ -410,7 +410,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -426,7 +426,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
try {
NBTTagCompound tag = new NBTTagCompound();
tile.b(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -270,7 +270,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
if (nativeTag != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
@ -426,7 +426,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
BlockPosition pos = new BlockPosition(x, y, z); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.adapter, nativeTag);
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));

View File

@ -122,9 +122,9 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
air = (IBlockData) fieldAir.get(null);
fieldBits = DataPaletteBlock.class.getDeclaredField("b");
fieldBits.setAccessible(true);
if (adapter == null) {
if (getAdapter() == null) {
setupAdapter(new FaweAdapter_1_9());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("Using adapter: " + getAdapter());
Fawe.debug("=========================================");
}
} catch (Throwable e) {
@ -158,7 +158,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
nmsWorld.worldData.getSeed();
boolean result;
net.minecraft.server.v1_9_R2.ChunkProviderGenerate generator = new net.minecraft.server.v1_9_R2.ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
Biome bukkitBiome = getAdapter().getBiome(biome.getId());
net.minecraft.server.v1_9_R2.BiomeBase base = net.minecraft.server.v1_9_R2.BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new net.minecraft.server.v1_9_R2.BiomeBase[]{base});
net.minecraft.server.v1_9_R2.ChunkGenerator existingGenerator = nmsWorld.getChunkProviderServer().chunkGenerator;
@ -758,7 +758,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.e(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
CompoundTag nativeTag = (CompoundTag) toNative(tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
@ -784,7 +784,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
try {
NBTTagCompound tag = new NBTTagCompound();
tile.save(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
return (CompoundTag) toNative(tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;

View File

@ -99,7 +99,7 @@ public class AsyncWorld extends DelegateFaweQueue implements World, HasFaweQueue
this.parent = parent;
this.queue = queue;
if (queue instanceof BukkitQueue_0) {
this.adapter = (BukkitImplAdapter) ((BukkitQueue_0) queue).adapter;
this.adapter = (BukkitImplAdapter) ((BukkitQueue_0) queue).getAdapter();
} else {
try {
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");

View File

@ -489,7 +489,7 @@ public class BukkitWorld extends LocalWorld {
@Override
public BaseBlock getBlock(Vector position) {
BukkitImplAdapter adapter = BukkitQueue_0.adapter;
BukkitImplAdapter adapter = BukkitQueue_0.getAdapter();
if (adapter != null) {
return adapter.getBlock(adapt(getWorld(), position));
} else {

View File

@ -52,23 +52,23 @@ public class CatenaryBrush implements Brush, ResettableTool {
return true;
}
public Vector getVertex(Vector pos1, Vector pos2, double lenPercent) {
double len = pos1.distance(pos2) * lenPercent;
public Vector getVertex(Vector pos1, Vector pos2, double lenPercent) {
double len = pos1.distance(pos2) * lenPercent;
double dy = pos2.getY() - pos1.getY();
double dx = pos2.getX() - pos1.getX();
double dz = pos2.getZ() - pos1.getZ();
double h = Math.sqrt(dx * dx + dz * dz);
double dy = pos2.getY() - pos1.getY();
double dx = pos2.getX() - pos1.getX();
double dz = pos2.getZ() - pos1.getZ();
double h = Math.sqrt(dx * dx + dz * dz);
double t = Math.sqrt(len * len - dy * dy) / h;
double z = 0.001;
for (; Math.sinh(z) < t*z; z += 0.001); // close enough
double t = Math.sqrt(len * len - dy * dy) / h;
double z = 0.001;
for (; Math.sinh(z) < t*z; z += 0.001); // close enough
double a = (h / 2) / z;
double p = (h - a * Math.log((len + dy) / (len - dy)))/2;
double q = (dy - len * Math.cosh(z) / Math.sinh(z)) / 2;
double y = a * 1 + q;
double a = (h / 2) / z;
double p = (h - a * Math.log((len + dy) / (len - dy)))/2;
double q = (dy - len * Math.cosh(z) / Math.sinh(z)) / 2;
double y = a * 1 + q;
return pos1.add(pos2.subtract(pos1).multiply(p / h).add(0, y, 0)).round();
}
return pos1.add(pos2.subtract(pos1).multiply(p / h).add(0, y, 0)).round();
}
}

View File

@ -288,6 +288,72 @@ public class ReflectionUtils {
}
}
public static Field findField(final Class<?> clazz, final Class<?> type, int hasMods, int noMods) {
for (Field field : clazz.getDeclaredFields()) {
if (type == null || field.getType() == type) {
int mods = field.getModifiers();
if ((mods & hasMods) == hasMods && (mods & noMods) == 0) {
return setAccessible(field);
}
}
}
return null;
}
public static Field findField(final Class<?> clazz, final Class<?> type) {
for (Field field : clazz.getDeclaredFields()) {
if (field.getType() == type) {
return setAccessible(field);
}
}
return null;
}
public static Method findMethod(final Class<?> clazz, final Class<?> returnType, Class... params) {
return findMethod(clazz, 0, returnType, params);
}
public static Method findMethod(final Class<?> clazz, int index, int hasMods, int noMods, final Class<?> returnType, Class... params) {
outer:
for (Method method : sortMethods(clazz.getDeclaredMethods())) {
if (returnType == null || method.getReturnType() == returnType) {
Class<?>[] mp = method.getParameterTypes();
int mods = method.getModifiers();
if ((mods & hasMods) != hasMods || (mods & noMods) != 0) continue;
if (params == null) {
if (index-- == 0) return setAccessible(method);
else {
continue;
}
}
if (mp.length == params.length) {
for (int i = 0; i < mp.length; i++) {
if (mp[i] != params[i]) continue outer;
}
if (index-- == 0) return setAccessible(method);
else {
continue;
}
}
}
}
return null;
}
private static Method[] sortMethods(Method[] methods) {
Arrays.sort(methods, (o1, o2) -> o1.getName().compareTo(o2.getName()));
return methods;
}
public static Method findMethod(final Class<?> clazz, int index, final Class<?> returnType, Class... params) {
return findMethod(clazz, index, 0, 0, returnType, params);
}
public static <T extends AccessibleObject> T setAccessible(final T ao) {
ao.setAccessible(true);
return ao;
}
@SuppressWarnings("unchecked")
public static <T> T getField(final Field field, final Object instance) {
if (field == null) {