This commit is contained in:
Jesse Boyd 2016-08-26 03:02:50 +10:00
parent b5349e16f0
commit 61d00e51ef
2 changed files with 117 additions and 75 deletions

View File

@ -4,6 +4,8 @@ import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue; import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
@ -126,4 +128,60 @@ public class BukkitLocalQueue<T> extends BasicLocalBlockQueue<T> {
} }
} }
} }
private Field fieldNeighbors;
private Method chunkGetHandle;
/**
* Exploiting a bug in the vanilla lighting algorithm for faster block placement
* - Could have been achieved without reflection by force unloading specific chunks
* - Much faster just setting the variable manually though
* @param chunk
* @return
*/
protected Object[] disableLighting(Chunk chunk) {
try {
if (chunkGetHandle == null) {
chunkGetHandle = chunk.getClass().getDeclaredMethod("getHandle");
chunkGetHandle.setAccessible(true);
}
Object nmsChunk = chunkGetHandle.invoke(chunk);
if (fieldNeighbors == null) {
fieldNeighbors = nmsChunk.getClass().getDeclaredField("neighbors");
fieldNeighbors.setAccessible(true);
}
Object value = fieldNeighbors.get(nmsChunk);
fieldNeighbors.set(nmsChunk, 0);
return new Object[] {nmsChunk, value};
} catch (Throwable ignore) {}
return null;
}
protected void disableLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], 0);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
protected void resetLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], disableResult[1]);
} catch (Throwable ignore) {
ignore.printStackTrace();
}
}
}
protected void enableLighting(Object[] disableResult) {
if (disableResult != null) {
try {
fieldNeighbors.set(disableResult[0], 0x739C0);
} catch (Throwable ignore) {}
}
}
} }

View File

@ -1,9 +1,7 @@
package com.plotsquared.bukkit.util.block; package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ChunkWrapper; import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.ReflectionUtils; import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue; import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
@ -380,87 +378,73 @@ public class BukkitLocalQueue_1_9 extends BukkitLocalQueue<char[]> {
Object c = this.methodGetHandleChunk.of(chunk).call(); Object c = this.methodGetHandleChunk.of(chunk).call();
ChunkWrapper wrapper = new ChunkWrapper(getWorld(), bc.getX(), bc.getZ()); ChunkWrapper wrapper = new ChunkWrapper(getWorld(), bc.getX(), bc.getZ());
if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) { Object[] result = disableLighting(chunk);
World world = chunk.getWorld(); enableLighting(result);
for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) {
for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
if (x != 0 && z != 0) {
Chunk other = world.getChunkAt(x, z);
while (!other.isLoaded()) {
other.load(true);
}
ChunkManager.manager.loadChunk(getWorld(), new ChunkLoc(x, z), true);
}
}
}
}
this.methodInitLighting.of(c).call(); this.methodInitLighting.of(c).call();
if (bc.getTotalRelight() == 0 && !fixAll) { if (bc.getTotalRelight() != 0 || fixAll) {
return true; Object[] sections = (Object[]) this.fieldSections.of(c).get();
} Object w = this.fieldWorld.of(c).get();
Object[] sections = (Object[]) this.fieldSections.of(c).get(); int X = chunk.getX() << 4;
Object w = this.fieldWorld.of(c).get(); int Z = chunk.getZ() << 4;
ReflectionUtils.RefMethod.RefExecutor relight = this.methodW.of(w);
int X = chunk.getX() << 4; for (int j = 0; j < sections.length; j++) {
int Z = chunk.getZ() << 4; Object section = sections[j];
if (section == null) {
ReflectionUtils.RefMethod.RefExecutor relight = this.methodW.of(w); continue;
for (int j = 0; j < sections.length; j++) { }
Object section = sections[j]; if (bc.getRelight(j) == 0 && !fixAll || bc.getCount(j) == 0 || bc.getCount(j) >= 4096 && bc.getAir(j) == 0) {
if (section == null) { continue;
continue; }
} char[] array = bc.getIdArray(j);
if (bc.getRelight(j) == 0 && !fixAll || bc.getCount(j) == 0 || bc.getCount(j) >= 4096 && bc.getAir(j) == 0) { if (array != null) {
continue; int l = PseudoRandom.random.random(2);
} for (int k = 0; k < array.length; k++) {
char[] array = bc.getIdArray(j); int i = array[k];
if (array != null) { if (i < 16) {
int l = PseudoRandom.random.random(2); continue;
for (int k = 0; k < array.length; k++) { }
int i = array[k]; short id = (short) (i >> 4);
if (i < 16) { switch (id) { // Lighting
continue; default:
} if (!fixAll) {
short id = (short) (i >> 4); continue;
switch (id) { // Lighting }
default: if ((k & 1) == l) {
if (!fixAll) { l = 1 - l;
continue; continue;
} }
if ((k & 1) == l) { case 10:
l = 1 - l; case 11:
continue; case 39:
} case 40:
case 10: case 50:
case 11: case 51:
case 39: case 62:
case 40: case 74:
case 50: case 76:
case 51: case 89:
case 62: case 122:
case 74: case 124:
case 76: case 130:
case 89: case 138:
case 122: case 169:
case 124: int x = MainUtil.x_loc[j][k];
case 130: int y = MainUtil.y_loc[j][k];
case 138: int z = MainUtil.z_loc[j][k];
case 169: if (isSurrounded(bc.blocks, x, y, z)) {
int x = MainUtil.x_loc[j][k]; continue;
int y = MainUtil.y_loc[j][k]; }
int z = MainUtil.z_loc[j][k]; Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
if (isSurrounded(bc.blocks, x, y, z)) { relight.call(pos);
continue; }
}
Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
relight.call(pos);
} }
} }
} }
} }
resetLighting(result);
return true; return true;
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();