Forge/Sponge 3.5.0

This commit is contained in:
Jesse Boyd 2016-05-14 23:38:07 +10:00
parent 00c685cd93
commit 0bc703e1b9
31 changed files with 1138 additions and 465 deletions

View File

@ -6,7 +6,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
classpath 'org.ajoberstar:grgit:1.1.0' classpath 'org.ajoberstar:grgit:1.7.0'
} }
} }
@ -17,7 +17,7 @@ clean { delete "target" }
group = 'com.boydti.fawe' group = 'com.boydti.fawe'
def revision = "" def revision = ""
ext { ext {
git = org.ajoberstar.grgit.Grgit.open(file(".git/")) git = org.ajoberstar.grgit.Grgit.open(file(".git"))
revision = "-${git.head().abbreviatedId}" revision = "-${git.head().abbreviatedId}"
} }
version = "3.5.0${revision}" version = "3.5.0${revision}"

View File

@ -14,13 +14,3 @@ dependencies {
compile 'junit:junit:4.11' compile 'junit:junit:4.11'
compile 'com.sk89q.worldedit:worldedit-bukkit:6.1.1-SNAPSHOT' compile 'com.sk89q.worldedit:worldedit-bukkit:6.1.1-SNAPSHOT'
} }
processResources {
from('src/main/resources') {
include 'plugin.yml'
expand(
name: project.parent.name,
version: project.parent.version
)
}
}

View File

@ -3,6 +3,16 @@ dependencies {
compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8' compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8'
} }
processResources {
from('src/main/resources') {
include 'plugin.yml'
expand(
name: project.parent.name,
version: project.parent.version
)
}
}
apply plugin: 'com.github.johnrengelman.shadow' apply plugin: 'com.github.johnrengelman.shadow'
// We only want the shadow jar produced // We only want the shadow jar produced
jar.enabled = false jar.enabled = false

View File

@ -1,6 +1,6 @@
name: FastAsyncWorldEdit name: FastAsyncWorldEdit
main: com.boydti.fawe.bukkit.v1_8.BukkitMain_18 main: com.boydti.fawe.bukkit.v1_8.BukkitMain_18
version: 3.4.3 version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit] loadbefore: [WorldEdit]

View File

@ -3,8 +3,17 @@ dependencies {
compile 'org.bukkit.craftbukkit.v1_9R2:craftbukkitv1_9R2:1.9.4' compile 'org.bukkit.craftbukkit.v1_9R2:craftbukkitv1_9R2:1.9.4'
} }
apply plugin: 'com.github.johnrengelman.shadow' processResources {
from('src/main/resources') {
include 'plugin.yml'
expand(
name: project.parent.name,
version: project.parent.version
)
}
}
apply plugin: 'com.github.johnrengelman.shadow'
// We only want the shadow jar produced // We only want the shadow jar produced
jar.enabled = false jar.enabled = false
shadowJar { shadowJar {

View File

@ -1,6 +1,6 @@
name: FastAsyncWorldEdit name: ${name}
main: com.boydti.fawe.bukkit.v1_9.BukkitMain_19 main: com.boydti.fawe.bukkit.v1_9.BukkitMain_19
version: 3.4.3 version: ${version}
description: Fast Async WorldEdit plugin description: Fast Async WorldEdit plugin
authors: [Empire92] authors: [Empire92]
loadbefore: [WorldEdit] loadbefore: [WorldEdit]

View File

@ -226,46 +226,46 @@ public class Fawe {
* - LocalSession supports VirtualPlayers and undo on disk * - LocalSession supports VirtualPlayers and undo on disk
*/ */
try { try {
EditSession.inject(); EditSession.inject(); // Custom block placer + optimizations
LocalSession.inject(); LocalSession.inject(); // Add remember order / queue flushing
// Commands // Commands
BrushCommands.inject(); BrushCommands.inject(); // Translations + heightmap
ClipboardCommands.inject(); ClipboardCommands.inject(); // Translations + lazycopy + paste optimizations
SchematicCommands.inject(); SchematicCommands.inject(); // Translations
ScriptingCommands.inject(); ScriptingCommands.inject(); // Translations
SelectionCommand.inject(); SelectionCommand.inject(); // Translations + set optimizations
RegionCommands.inject(); RegionCommands.inject(); // Translations
HistoryCommands.inject(); HistoryCommands.inject(); // Translations
// Brushes // Brushes
GravityBrush.inject(); GravityBrush.inject(); // Fix for instant placement assumption
// Selectors // Selectors
CuboidRegionSelector.inject(); CuboidRegionSelector.inject(); // Translations
// Visitors // Visitors
BreadthFirstSearch.inject(); BreadthFirstSearch.inject(); // Translations + Optimizations
DownwardVisitor.inject(); DownwardVisitor.inject(); // Optimizations
EntityVisitor.inject(); EntityVisitor.inject(); // Translations + Optimizations
FlatRegionVisitor.inject(); FlatRegionVisitor.inject(); // Translations + Optimizations
LayerVisitor.inject(); LayerVisitor.inject(); // Optimizations
NonRisingVisitor.inject(); NonRisingVisitor.inject(); // Optimizations
RecursiveVisitor.inject(); RecursiveVisitor.inject(); // Optimizations
RegionVisitor.inject(); RegionVisitor.inject(); // Translations + Optimizations
// Entity create/remove // Entity create/remove
EntityCreate.inject(); EntityCreate.inject(); // Optimizations
EntityRemove.inject(); EntityRemove.inject(); // Optimizations
// Clipboards // Clipboards
BlockArrayClipboard.inject(); BlockArrayClipboard.inject(); // Optimizations + disk
CuboidClipboard.inject(); CuboidClipboard.inject(); // Optimizations
// Regions // Regions
CuboidRegion.inject(); CuboidRegion.inject(); // Optimizations
// Extents // Extents
BlockTransformExtent.inject(); BlockTransformExtent.inject(); // Fix for cache not being mutable
// Vector // Vector
Vector.inject(); Vector.inject(); // Optimizations
// Operations // Operations
Operations.inject(); Operations.inject(); // Optimizations
try { try {
CommandManager.inject(); CommandManager.inject(); // Async commands
PlatformManager.inject(); PlatformManager.inject(); // Async brushes / tools
} catch (Throwable e) { } catch (Throwable e) {
debug("====== UPDATE WORLDEDIT TO 6.1.1 ======"); debug("====== UPDATE WORLDEDIT TO 6.1.1 ======");
e.printStackTrace(); e.printStackTrace();
@ -284,6 +284,7 @@ public class Fawe {
e.printStackTrace(); e.printStackTrace();
debug("======================================="); debug("=======================================");
debug("Things to check: "); debug("Things to check: ");
debug(" - Using WorldEdit 6.1.1");
debug(" - AsyncWorldEdit/WorldEditRegions isn't installed"); debug(" - AsyncWorldEdit/WorldEditRegions isn't installed");
debug(" - Any other errors in the startup log"); debug(" - Any other errors in the startup log");
debug(" - Contact Empire92 for assistance!"); debug(" - Contact Empire92 for assistance!");

View File

@ -188,10 +188,8 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
char[] vs = this.ids[i]; char[] vs = this.ids[i];
if (vs == null) { if (vs == null) {
vs = this.ids[i] = new char[4096]; vs = this.ids[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
} }
this.count[i]++;
switch (id) { switch (id) {
case 0: case 0:
this.air[i]++; this.air[i]++;
@ -277,11 +275,7 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
case 146: case 146:
case 61: case 61:
case 65: case 65:
case 68: case 68: // removed
// if (data < 2) {
// data = 2;
// }
default: default:
vs[j] = (char) ((id << 4) + data); vs[j] = (char) ((id << 4) + data);
return; return;

View File

@ -109,9 +109,9 @@ public abstract class FawePlayer<T> {
} }
public void loadClipboardFromDisk() { public void loadClipboardFromDisk() {
try {
File file = new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + getUUID()); File file = new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + getUUID());
if (file.exists()) { try {
if (file.exists() && file.length() > 5) {
DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file); DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file);
Player player = getPlayer(); Player player = getPlayer();
LocalSession session = getSession(); LocalSession session = getSession();
@ -128,8 +128,13 @@ public abstract class FawePlayer<T> {
getSession().setClipboard(holder); getSession().setClipboard(holder);
} }
} }
} catch (Exception e) { } catch (Exception ignore) {
e.printStackTrace(); Fawe.debug("====== INVALID CLIPBOARD ======");
ignore.printStackTrace();
Fawe.debug("===============---=============");
Fawe.debug("This shouldn't result in any failure");
Fawe.debug("File: " + file.getName() + " (len:" + file.length() + ")");
Fawe.debug("===============---=============");
} }
} }

View File

@ -108,17 +108,29 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
final short id = (short) block.getId(); final short id = (short) block.getId();
byte data = (byte) block.getData();
final int x = location.getBlockX(); final int x = location.getBlockX();
final int y = location.getBlockY(); final int y = location.getBlockY();
final int z = location.getBlockZ(); final int z = location.getBlockZ();
switch (id) { switch (id) {
case 68: {
if (data == 0) {
data = 2;
}
}
case 63: case 63:
case 68:
if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) { if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) {
queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0); queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
return true; return true;
} }
case 54: case 54:
case 146:
case 61:
{
if (data == 0) {
data = 2;
}
}
case 130: case 130:
case 142: case 142:
case 27: case 27:
@ -138,10 +150,8 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
case 28: case 28:
case 66: case 66:
case 157: case 157:
case 61:
case 62: case 62:
case 140: case 140:
case 146:
case 149: case 149:
case 150: case 150:
case 158: case 158:
@ -157,11 +167,16 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
MainUtil.setPosition(nbt, x, y, z); MainUtil.setPosition(nbt, x, y, z);
queue.setTile(x, y, z, nbt); queue.setTile(x, y, z, nbt);
} }
queue.setBlock(x, y, z, id, (byte) block.getData()); queue.setBlock(x, y, z, id, data);
return true; return true;
} }
case 65: {
if (data == 0) {
data = 2;
}
}
default: { default: {
queue.setBlock(x, y, z, id, (byte) block.getData()); queue.setBlock(x, y, z, id, data);
return true; return true;
} }
} }

View File

@ -7,7 +7,6 @@ import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import org.bukkit.Bukkit;
public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType, Integer> { public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType, Integer> {
@ -63,7 +62,7 @@ public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType,
TaskManager.IMP.task(new Runnable() { TaskManager.IMP.task(new Runnable() {
@Override @Override
public void run() { public void run() {
long currentTick = Bukkit.getServer().getWorlds().get(0).getFullTime(); long currentTick = System.currentTimeMillis() / 50;
if (currentTick > lastTick + Settings.DISPLAY_PROGRESS_INTERVAL) { if (currentTick > lastTick + Settings.DISPLAY_PROGRESS_INTERVAL) {
lastTick = currentTick; lastTick = currentTick;
String queue = StringMan.padRight("" + amountQueue, 3); String queue = StringMan.padRight("" + amountQueue, 3);

View File

@ -97,6 +97,7 @@ public abstract class FaweQueue {
public void endSet(boolean parallel) {} public void endSet(boolean parallel) {}
public int cancel() { public int cancel() {
clear();
int count = 0; int count = 0;
for (EditSession session : sessions) { for (EditSession session : sessions) {
if (session.cancel()) { if (session.cancel()) {

View File

@ -204,7 +204,7 @@ public class LocalSession {
} }
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage) { public void remember(final EditSession editSession, final boolean append, final boolean sendMessage) {
if (editSession == null) { if (editSession == null || editSession.getChangeSet() == null) {
return; return;
} }
if (Settings.STORE_HISTORY_ON_DISK) { if (Settings.STORE_HISTORY_ON_DISK) {

View File

@ -20,8 +20,6 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandException;
@ -162,12 +160,6 @@ public class SchematicCommands {
target = clipboard; target = clipboard;
} }
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
final Closer closer = Closer.create(); final Closer closer = Closer.create();
try { try {
// Create parent directories // Create parent directories
@ -194,10 +186,6 @@ public class SchematicCommands {
} catch (final IOException ignored) {} } catch (final IOException ignored) {}
} }
} }
});
}
});
}
@Command(aliases = { "delete", "d" }, usage = "<filename>", desc = "Delete a saved schematic", help = "Delete a schematic from the schematic list", min = 1, max = 1) @Command(aliases = { "delete", "d" }, usage = "<filename>", desc = "Delete a saved schematic", help = "Delete a schematic from the schematic list", min = 1, max = 1)
@CommandPermissions("worldedit.schematic.delete") @CommandPermissions("worldedit.schematic.delete")
@ -207,23 +195,16 @@ public class SchematicCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(config.saveDir); final File dir = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
final File f = this.worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic"); final File f = this.worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
if (!f.exists()) { if (!f.exists()) {
player.printError("Schematic " + filename + " does not exist!"); player.printError("Schematic " + filename + " does not exist!");
return; return;
} }
if (!f.delete()) { if (!f.delete()) {
player.printError("Deletion of " + filename + " failed! Maybe it is read-only."); player.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
return; return;
} }
BBC.SCHEMATIC_DELETE.send(player, filename); BBC.SCHEMATIC_DELETE.send(player, filename);
} }
});
}
@Command(aliases = { "formats", "listformats", "f" }, desc = "List available formats", max = 0) @Command(aliases = { "formats", "listformats", "f" }, desc = "List available formats", max = 0)
@CommandPermissions("worldedit.schematic.formats") @CommandPermissions("worldedit.schematic.formats")

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -69,22 +67,12 @@ public class ScriptingCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir); final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir);
final File f = this.worldEdit.getSafeOpenFile(player, dir, name, "js", "js"); final File f = this.worldEdit.getSafeOpenFile(player, dir, name, "js", "js");
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
try { try {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs); ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) { } catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript."); player.printError("Error while executing CraftScript.");
} }
} }
});
}
});
}
@Command(aliases = { ".s" }, usage = "[args...]", desc = "Execute last CraftScript", min = 0, max = -1) @Command(aliases = { ".s" }, usage = "[args...]", desc = "Execute last CraftScript", min = 0, max = -1)
@CommandPermissions("worldedit.scripting.execute") @CommandPermissions("worldedit.scripting.execute")
@ -107,22 +95,12 @@ public class ScriptingCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir); final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir);
final File f = this.worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js"); final File f = this.worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js");
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
try { try {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs); ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) { } catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript."); player.printError("Error while executing CraftScript.");
} }
} }
});
}
});
}
public static Class<?> inject() { public static Class<?> inject() {
return ScriptingCommands.class; return ScriptingCommands.class;

View File

@ -125,7 +125,7 @@ public class FaweForge implements IFawe {
@Override @Override
public void startMetrics() { public void startMetrics() {
try { try {
ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.4.3"); ForgeMetrics metrics = new ForgeMetrics("FastAsyncWorldEdit", "3.5.0");
metrics.start(); metrics.start();
debug("[FAWE] &6Metrics enabled."); debug("[FAWE] &6Metrics enabled.");
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -19,7 +19,7 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.3", acceptableRemoteVersions = "*") @Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.0", acceptableRemoteVersions = "*")
public class ForgeMain { public class ForgeMain {
private static FaweForge IMP; private static FaweForge IMP;
private Logger logger; private Logger logger;

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.forge; package com.boydti.fawe.forge;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation; import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
@ -16,6 +17,16 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
super(parent); super(parent);
} }
@Override
public void sendTitle(String head, String sub) { // Not supported
Settings.DISPLAY_PROGRESS = false;
}
@Override
public void resetTitle() { // Not supported
Settings.DISPLAY_PROGRESS = false;
}
@Override @Override
public String getName() { public String getName() {
return parent.getCommandSenderName(); return parent.getCommandSenderName();

View File

@ -1,105 +1,32 @@
package com.boydti.fawe.forge.v0; package com.boydti.fawe.forge.v0;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Arrays;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.NibbleArray; import net.minecraft.world.chunk.NibbleArray;
public class ForgeChunk_All extends FaweChunk<Chunk> { public class ForgeChunk_All extends CharFaweChunk<Chunk> {
public byte[][] ids; public byte[][] byteIds;
public NibbleArray[] datas; public NibbleArray[] datas;
public short[] count;
public short[] air;
public short[] relight;
public byte[][] biomes;
public Chunk chunk;
public ForgeChunk_All(FaweQueue parent, int x, int z) { public ForgeChunk_All(FaweQueue parent, int x, int z) {
super(parent, x, z); super(parent, x, z);
this.ids = new byte[16][]; this.byteIds = new byte[16][];
this.datas = new NibbleArray[16]; this.datas = new NibbleArray[16];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
} }
@Override @Override
public Chunk getChunk() { public Chunk getNewChunk() {
if (this.chunk == null) {
World world = ((ForgeQueue_All) getParent()).getWorld(); World world = ((ForgeQueue_All) getParent()).getWorld();
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ()); return world.getChunkProvider().provideChunk(getX(), getZ());
}
return this.chunk;
} }
@Override public byte[] getByteIdArray(int i) {
public void setLoc(final FaweQueue parent, int x, int z) { return this.byteIds[i];
super.setLoc(parent, x, z);
this.chunk = null;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
/**
* Get the raw data for a section.
* @param i
* @return
*/
public byte[] getIdArray(int i) {
return this.ids[i];
} }
public NibbleArray getDataArray(int i) { public NibbleArray getDataArray(int i) {
@ -110,17 +37,20 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
public void setBlock(int x, int y, int z, int id, byte data) { public void setBlock(int x, int y, int z, int id, byte data) {
int i = FaweCache.CACHE_I[y][x][z]; int i = FaweCache.CACHE_I[y][x][z];
int j = FaweCache.CACHE_J[y][x][z]; int j = FaweCache.CACHE_J[y][x][z];
byte[] vs = this.ids[i]; byte[] vs = this.byteIds[i];
if (vs == null) { char[] vs2 = this.ids[i];
vs = this.ids[i] = new byte[4096]; if (vs2 == null) {
this.count[i]++; vs2 = this.ids[i] = new char[4096];
} else if (vs[j] == 0) {
this.count[i]++;
} }
if (vs == null) {
vs = this.byteIds[i] = new byte[4096];
}
this.count[i]++;
switch (id) { switch (id) {
case 0: case 0:
this.air[i]++; this.air[i]++;
vs[j] = -1; vs[j] = -1;
vs2[j] = (char) 1;
return; return;
case 10: case 10:
case 11: case 11:
@ -193,6 +123,7 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 191: case 191:
case 192: case 192:
vs[j] = (byte) (id); vs[j] = (byte) (id);
vs2[j] = (char) (id << 4);
return; return;
case 130: case 130:
case 76: case 76:
@ -203,38 +134,26 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 146: case 146:
case 61: case 61:
case 65: case 65:
case 68: case 68: // removed
// if (data < 2) {
// data = 2;
// }
default: default:
vs2[j] = (char) ((id << 4) + data);
vs[j] = (byte) id; vs[j] = (byte) id;
if (data != 0) {
NibbleArray dataArray = datas[i]; NibbleArray dataArray = datas[i];
if (dataArray == null) { if (dataArray == null) {
datas[i] = dataArray = new NibbleArray(4096, 4); datas[i] = dataArray = new NibbleArray(4096, 4);
} }
dataArray.set(x, y & 15, z, data); dataArray.set(x, y & 15, z, data);
}
return; return;
} }
} }
@Override @Override
public void setBiome(int x, int z, BaseBiome biome) { public CharFaweChunk<Chunk> copy(boolean shallow) {
if (this.biomes == null) {
this.biomes = new byte[16][];
}
byte[] index = this.biomes[x];
if (index == null) {
index = this.biomes[x] = new byte[16];
}
index[z] = (byte) biome.getId();
}
@Override
public FaweChunk<Chunk> copy(boolean shallow) {
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ()); ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
if (shallow) { if (shallow) {
copy.ids = ids; copy.byteIds = byteIds;
copy.datas = datas; copy.datas = datas;
copy.air = air; copy.air = air;
copy.biomes = biomes; copy.biomes = biomes;
@ -242,7 +161,7 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
copy.count = count; copy.count = count;
copy.relight = relight; copy.relight = relight;
} else { } else {
copy.ids = (byte[][]) MainUtil.copyNd(ids); copy.byteIds = (byte[][]) MainUtil.copyNd(byteIds);
copy.datas = datas.clone(); copy.datas = datas.clone();
copy.air = air.clone(); copy.air = air.clone();
copy.biomes = biomes.clone(); copy.biomes = biomes.clone();

View File

@ -2,20 +2,38 @@ package com.boydti.fawe.forge.v0;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.forge.ForgePlayer;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData; import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -32,10 +50,22 @@ import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer; import net.minecraft.world.gen.ChunkProviderServer;
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, ExtendedBlockStorage> { public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
public ForgeQueue_All(final String world) { private Method methodFromNative;
private Method methodToNative;
public ForgeQueue_All(String world) {
super(world); super(world);
try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true);
methodToNative.setAccessible(true);
} catch (Throwable e) {
throw new RuntimeException(e);
}
} }
@Override @Override
@ -44,12 +74,17 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
} }
@Override @Override
public Chunk getCachedChunk(World world, int cx, int cz) { public ExtendedBlockStorage[] getCachedChunk(World world, int cx, int cz) {
Chunk chunk = world.getChunkProvider().provideChunk(cx, cz); Chunk chunk = world.getChunkProvider().provideChunk(cx, cz);
if (chunk != null && !chunk.isChunkLoaded) { if (chunk != null && !chunk.isChunkLoaded) {
chunk.onChunkLoad(); chunk.onChunkLoad();
} }
return chunk; return chunk != null ? chunk.getBlockStorageArray() : null;
}
@Override
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] extendedBlockStorages, int cy) {
return extendedBlockStorages[cy];
} }
@Override @Override
@ -186,16 +221,75 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
} }
} }
public boolean setComponents(FaweChunk fc) { @Override
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
ForgeChunk_All fs = (ForgeChunk_All) fc; ForgeChunk_All fs = (ForgeChunk_All) fc;
Chunk forgeChunk = fs.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = forgeChunk.worldObj; net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
try { try {
boolean flag = !nmsWorld.provider.hasNoSky; boolean flag = !nmsWorld.provider.hasNoSky;
// Sections // Sections
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray(); ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<ChunkPosition, TileEntity> tiles = forgeChunk.chunkTileEntityMap; Map<ChunkPosition, TileEntity> tiles = nmsChunk.chunkTileEntityMap;
List[] entities = forgeChunk.entityLists; List<Entity>[] entities = nmsChunk.entityLists;
// Remove entities
for (int i = 0; i < 16; i++) {
int count = fs.getCount(i);
if (count == 0) {
continue;
} else if (count >= 4096) {
entities[i].clear();
} else {
char[] array = fs.getIdArray(i);
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
continue;
}
int x = ((int) Math.round(entity.posX) & 15);
int z = ((int) Math.round(entity.posZ) & 15);
int y = (int) Math.round(entity.posY);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
nmsWorld.removeEntity(entity);
}
}
}
}
// Set entities
Set<UUID> createdEntities = new HashSet<>();
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
for (CompoundTag nativeTag : entitiesToSpawn) {
Map<String, Tag> entityTagMap = nativeTag.getValue();
StringTag idTag = (StringTag) entityTagMap.get("Id");
ListTag posTag = (ListTag) entityTagMap.get("Pos");
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
if (idTag == null || posTag == null || rotTag == null) {
Fawe.debug("Unknown entity tag: " + nativeTag);
continue;
}
double x = posTag.getDouble(0);
double y = posTag.getDouble(1);
double z = posTag.getDouble(2);
float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1);
String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) {
entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity);
}
}
// Run change task if applicable
if (changeTask != null) {
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
changeTask.run(previous);
}
// Trim tiles // Trim tiles
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet(); Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator(); Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator();
@ -206,21 +300,33 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
int ly = pos.chunkPosY; int ly = pos.chunkPosY;
int lz = pos.chunkPosZ & 15; int lz = pos.chunkPosZ & 15;
int j = FaweCache.CACHE_I[ly][lx][lz]; int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz]; char[] array = fs.getIdArray(j);
byte[] array = fs.getIdArray(j);
if (array == null) { if (array == null) {
continue; continue;
} }
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) { if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove(); iterator.remove();
} }
} }
HashSet<UUID> entsToRemove = fs.getEntityRemoves();
if (entsToRemove.size() > 0) {
for (int i = 0; i < entities.length; i++) {
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entsToRemove.contains(entity.getUniqueID())) {
nmsWorld.removeEntity(entity);
}
}
}
}
// Efficiently merge sections // Efficiently merge sections
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) { if (fs.getCount(j) == 0) {
continue; continue;
} }
byte[] newIdArray = fs.getIdArray(j); byte[] newIdArray = fs.getByteIdArray(j);
if (newIdArray == null) { if (newIdArray == null) {
continue; continue;
} }
@ -232,8 +338,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
section.setBlockMetadataArray(newDataArray); section.setBlockMetadataArray(newDataArray);
continue; continue;
} }
// id + data << 8
byte[] currentIdArray = section.getBlockLSBArray(); byte[] currentIdArray = section.getBlockLSBArray();
NibbleArray currentDataArray = section.getMetadataArray(); NibbleArray currentDataArray = section.getMetadataArray();
boolean data = currentDataArray != null; boolean data = currentDataArray != null;
@ -241,6 +345,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
section.setBlockMetadataArray(newDataArray); section.setBlockMetadataArray(newDataArray);
} }
boolean fill = true; boolean fill = true;
int solid = 0;
for (int k = 0; k < newIdArray.length; k++) { for (int k = 0; k < newIdArray.length; k++) {
byte n = newIdArray[k]; byte n = newIdArray[k];
switch (n) { switch (n) {
@ -249,9 +354,13 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
continue; continue;
case -1: case -1:
fill = false; fill = false;
if (currentIdArray[k] != 0) {
solid++;
}
currentIdArray[k] = 0; currentIdArray[k] = 0;
continue; continue;
default: default:
solid++;
currentIdArray[k] = n; currentIdArray[k] = n;
if (data) { if (data) {
int x = FaweCache.CACHE_X[j][k]; int x = FaweCache.CACHE_X[j][k];
@ -266,81 +375,212 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
continue; continue;
} }
} }
setCount(0, solid, section);
if (fill) { if (fill) {
fs.setCount(j, Short.MAX_VALUE); fs.setCount(j, Short.MAX_VALUE);
} }
} }
// // Clear
} catch (Throwable e) { // Set biomes
e.printStackTrace(); int[][] biomes = fs.biomes;
}
byte[][] biomes = fs.biomes;
if (biomes != null) { if (biomes != null) {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
byte[] array = biomes[x]; int[] array = biomes[x];
if (array == null) { if (array == null) {
continue; continue;
} }
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
byte biome = array[z]; int biome = array[z];
if (biome == 0) { if (biome == 0) {
continue; continue;
} }
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome; nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
} }
} }
} }
sendChunk(fs); // Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
int bx = fs.getX() << 4;
int bz = fs.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();
int x = MathMan.unpair16x(pair.pair[0]) + bx;
int y = pair.pair[1] & 0xFF;
int z = MathMan.unpair16y(pair.pair[0]) + bz;
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
tileEntity.readFromNBT(tag); // ReadTagIntoTile
}
}
} catch (Throwable e) {
e.printStackTrace();
}
int[][] biomes = fs.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
sendChunk(fs, null);
return true; return true;
} }
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); // tickRefCount
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b"); // blockRefCount
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
@Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<ChunkPosition, TileEntity> tiles = (Map<ChunkPosition, TileEntity>) tilesGeneric;
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
CharFaweChunk previous = (CharFaweChunk) getChunk(fs.getX(), fs.getZ());
char[][] idPrevious = new char[16][];
for (int layer = 0; layer < sections.length; layer++) {
if (fs.getCount(layer) != 0 || all) {
ExtendedBlockStorage section = sections[layer];
if (section != null) {
byte[] currentIdArray = section.getBlockLSBArray();
NibbleArray currentDataArray = section.getMetadataArray();
char[] array = new char[4096];
for (int j = 0; j < currentIdArray.length; j++) {
int x = FaweCache.CACHE_X[layer][j];
int y = FaweCache.CACHE_Y[layer][j];
int z = FaweCache.CACHE_Z[layer][j];
int id = currentIdArray[j] & 0xFF;
byte data = (byte) currentDataArray.get(x, y & 15, z);
previous.setBlock(x, y, z, id, data);
}
}
}
}
previous.ids = idPrevious;
if (tiles != null) {
for (Map.Entry<ChunkPosition, TileEntity> entry : tiles.entrySet()) {
TileEntity tile = entry.getValue();
NBTTagCompound tag = new NBTTagCompound();
tile.readFromNBT(tag); // readTileEntityIntoTag
ChunkPosition pos = entry.getKey();
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
previous.setTile(pos.chunkPosX, pos.chunkPosY, pos.chunkPosZ, nativeTag);
}
}
if (entities != null) {
for (Collection<Entity> entityList : entities) {
for (Entity ent : entityList) {
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && !createdEntities.contains(ent.getUniqueID()))) {
continue;
}
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
NBTTagCompound tag = ent.getEntityData(); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
}
}
}
}
}
return previous;
}
@Override @Override
public FaweChunk getChunk(int x, int z) { public FaweChunk getChunk(int x, int z) {
return new ForgeChunk_All(this, x, z); return new ForgeChunk_All(this, x, z);
} }
@Override @Override
public boolean fixLighting(FaweChunk chunk, boolean fixAll) { public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
try { if (mode == RelightMode.NONE) {
ForgeChunk_All fc = (ForgeChunk_All) chunk;
Chunk forgeChunk = fc.getChunk();
if (!forgeChunk.isChunkLoaded) {
forgeChunk.onChunkLoad();
}
forgeChunk.generateSkylightMap();
if (fc.getTotalRelight() == 0 && !fixAll) {
return true; return true;
} }
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray(); try {
net.minecraft.world.World nmsWorld = forgeChunk.worldObj; ForgeChunk_All bc = (ForgeChunk_All) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
if (!nmsChunk.isChunkLoaded) {
return false;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
if (mode == RelightMode.ALL) {
for (int i = 0; i < sections.length; i++) {
ExtendedBlockStorage section = sections[i];
if (section != null) {
section.setSkylightArray(new NibbleArray(4096, 4));
section.setBlocklightArray(new NibbleArray(4096, 4));
}
}
}
nmsChunk.generateSkylightMap();
if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true;
}
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
int X = fc.getX() << 4; int X = fc.getX() << 4;
int Z = fc.getZ() << 4; int Z = fc.getZ() << 4;
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j]; ExtendedBlockStorage section = sections[j];
if (section == null) { if (section == null) {
continue; continue;
} }
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) { if (((bc.getRelight(j) == 0) && mode == RelightMode.MINIMAL) || (bc.getCount(j) == 0 && mode != RelightMode.ALL) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0)) || bc.getAir(j) == 4096) {
continue; continue;
} }
byte[] array = section.getBlockLSBArray(); byte[] array = section.getBlockLSBArray();
int l = PseudoRandom.random.random(2); if (mode == RelightMode.ALL) {
for (int k = 0; k < array.length; k++) { for (int k = array.length - 1; k >= 0; k--) {
int i = array[k]; final int x = FaweCache.CACHE_X[j][k];
if (i < 16) { final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }
short id = (short) (i); nmsWorld.func_147451_t(X + x, y, Z + z);
}
continue;
}
for (int k = array.length - 1; k >= 0; k--) {
final int i = array[k];
final short id = (short) (i >> 4);
switch (id) { // Lighting switch (id) { // Lighting
case 0:
continue;
default: default:
if (!fixAll) { if (mode == RelightMode.MINIMAL) {
continue; continue;
} }
if ((k & 1) == l) { if (PseudoRandom.random.random(3) != 0) {
l = 1 - l;
continue; continue;
} }
case 10: case 10:
@ -358,9 +598,9 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
case 130: case 130:
case 138: case 138:
case 169: case 169:
int x = FaweCache.CACHE_X[j][k]; final int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k]; final int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k]; final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) { if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }

View File

@ -2,7 +2,7 @@
"modid": "com.boydti.fawe", "modid": "com.boydti.fawe",
"name": "FastAsyncWorldEdit", "name": "FastAsyncWorldEdit",
"description": "Extreme WorldEdit optimizations, no lag, low memory usage, area + tile + entity limits, block logging + rollback", "description": "Extreme WorldEdit optimizations, no lag, low memory usage, area + tile + entity limits, block logging + rollback",
"version": "3.4.3", "version": "3.5.0",
"mcVersion": "1.7.10", "mcVersion": "1.7.10",
"dependencies": [ "dependencies": [
"WorldEdit" "WorldEdit"

View File

@ -126,7 +126,7 @@ public class FaweForge implements IFawe {
@Override @Override
public void startMetrics() { public void startMetrics() {
try { try {
com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.4.3"); com.boydti.fawe.forge.ForgeMetrics metrics = new com.boydti.fawe.forge.ForgeMetrics("FastAsyncWorldEdit", "3.5.0");
metrics.start(); metrics.start();
debug("[FAWE] &6Metrics enabled."); debug("[FAWE] &6Metrics enabled.");
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -19,7 +19,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.4.3", acceptableRemoteVersions = "*") @Mod(modid = "com.boydti.fawe", name = "FastAsyncWorldEdit", version = "3.5.0", acceptableRemoteVersions = "*")
public class ForgeMain { public class ForgeMain {
private static com.boydti.fawe.forge.FaweForge IMP; private static com.boydti.fawe.forge.FaweForge IMP;
private Logger logger; private Logger logger;

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.forge; package com.boydti.fawe.forge;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation; import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
@ -16,6 +17,16 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
super(parent); super(parent);
} }
@Override
public void sendTitle(String head, String sub) { // Not supported
Settings.DISPLAY_PROGRESS = false;
}
@Override
public void resetTitle() { // Not supported
Settings.DISPLAY_PROGRESS = false;
}
@Override @Override
public String getName() { public String getName() {
return parent.getName(); return parent.getName();

View File

@ -2,18 +2,36 @@ package com.boydti.fawe.forge.v0;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.forge.ForgePlayer;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData; import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -25,13 +43,26 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer; import net.minecraft.world.gen.ChunkProviderServer;
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char[]> { public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], char[]> {
public ForgeQueue_All(final String world) { private Method methodFromNative;
private Method methodToNative;
public ForgeQueue_All(String world) {
super(world); super(world);
try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true);
methodToNative.setAccessible(true);
} catch (Throwable e) {
throw new RuntimeException(e);
}
} }
@Override @Override
@ -89,12 +120,18 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
} }
@Override @Override
public Chunk getCachedChunk(World world, int x, int z) { public ExtendedBlockStorage[] getCachedChunk(World world, int x, int z) {
Chunk chunk = world.getChunkProvider().provideChunk(x, z); Chunk chunk = world.getChunkProvider().provideChunk(x, z);
if (chunk != null && !chunk.isLoaded()) { if (chunk != null && !chunk.isLoaded()) {
chunk.onChunkLoad(); chunk.onChunkLoad();
} }
return chunk; return chunk == null ? null : chunk.getBlockStorageArray();
}
@Override
public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) {
ExtendedBlockStorage value = chunk[cy];
return value == null ? null : value.getData();
} }
@Override @Override
@ -107,17 +144,251 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
return world.getChunkProvider().chunkExists(x, z); return world.getChunkProvider().chunkExists(x, z);
} }
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c");
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
@Override @Override
public boolean setComponents(FaweChunk fc) { public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
ForgeChunk_All fs = (ForgeChunk_All) fc; if (mode == RelightMode.NONE) {
Chunk forgeChunk = fs.getChunk(); return true;
net.minecraft.world.World nmsWorld = forgeChunk.getWorld(); }
try {
CharFaweChunk<Chunk> bc = (CharFaweChunk) fc;
Chunk nmsChunk = bc.getChunk();
if (!nmsChunk.isLoaded()) {
return false;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
if (mode == RelightMode.ALL) {
for (int i = 0; i < sections.length; i++) {
ExtendedBlockStorage section = sections[i];
if (section != null) {
section.setSkylightArray(new NibbleArray());
section.setBlocklightArray(new NibbleArray());
}
}
}
nmsChunk.generateSkylightMap();
if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true;
}
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = fc.getX() << 4;
int Z = fc.getZ() << 4;
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j];
if (section == null) {
continue;
}
if (((bc.getRelight(j) == 0) && mode == RelightMode.MINIMAL) || (bc.getCount(j) == 0 && mode != RelightMode.ALL) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0)) || bc.getAir(j) == 4096) {
continue;
}
char[] array = section.getData();
if (mode == RelightMode.ALL) {
for (int k = array.length - 1; k >= 0; k--) {
final int x = FaweCache.CACHE_X[j][k];
final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue;
}
pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
continue;
}
for (int k = array.length - 1; k >= 0; k--) {
final int i = array[k];
final short id = (short) (i >> 4);
switch (id) { // Lighting
case 0:
continue;
default:
if (mode == RelightMode.MINIMAL) {
continue;
}
if (PseudoRandom.random.random(3) != 0) {
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
final int x = FaweCache.CACHE_X[j][k];
final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue;
}
pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
}
}
return true;
} catch (Throwable e) {
if (Thread.currentThread() == Fawe.get().getMainThread()) {
e.printStackTrace();
}
}
return false;
}
@Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
CharFaweChunk previous = (CharFaweChunk) getChunk(fs.getX(), fs.getZ());
char[][] idPrevious = new char[16][];
for (int layer = 0; layer < sections.length; layer++) {
if (fs.getCount(layer) != 0 || all) {
ExtendedBlockStorage section = sections[layer];
if (section != null) {
idPrevious[layer] = section.getData().clone();
short solid = 0;
for (int combined : idPrevious[layer]) {
if (combined > 1) {
solid++;
}
}
previous.count[layer] = 4096;
previous.air[layer] = (short) (4096 - solid);
}
}
}
previous.ids = idPrevious;
if (tiles != null) {
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
TileEntity tile = entry.getValue();
NBTTagCompound tag = new NBTTagCompound();
tile.readFromNBT(tag); // readTileEntityIntoTag
BlockPos pos = entry.getKey();
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
}
}
if (entities != null) {
for (Collection<Entity> entityList : entities) {
for (Entity ent : entityList) {
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && !createdEntities.contains(ent.getUniqueID()))) {
continue;
}
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
NBTTagCompound tag = ent.getNBTTagCompound(); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
}
}
}
}
}
return previous;
}
@Override
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
CharFaweChunk<Chunk> fs = (CharFaweChunk) fc;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
try { try {
boolean flag = !nmsWorld.provider.getHasNoSky(); boolean flag = !nmsWorld.provider.getHasNoSky();
// Sections // Sections
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray(); ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<BlockPos, TileEntity> tiles = forgeChunk.getTileEntityMap(); Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
ClassInheritanceMultiMap<Entity>[] entities = forgeChunk.getEntityLists(); ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
// Remove entities
for (int i = 0; i < 16; i++) {
int count = fs.getCount(i);
if (count == 0) {
continue;
} else if (count >= 4096) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
} else {
char[] array = fs.getIdArray(i);
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
continue;
}
int x = ((int) Math.round(entity.posX) & 15);
int z = ((int) Math.round(entity.posZ) & 15);
int y = (int) Math.round(entity.posY);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
nmsWorld.removeEntity(entity);
}
}
}
}
// Set entities
Set<UUID> createdEntities = new HashSet<>();
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
for (CompoundTag nativeTag : entitiesToSpawn) {
Map<String, Tag> entityTagMap = nativeTag.getValue();
StringTag idTag = (StringTag) entityTagMap.get("Id");
ListTag posTag = (ListTag) entityTagMap.get("Pos");
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
if (idTag == null || posTag == null || rotTag == null) {
Fawe.debug("Unknown entity tag: " + nativeTag);
continue;
}
double x = posTag.getDouble(0);
double y = posTag.getDouble(1);
double z = posTag.getDouble(2);
float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1);
String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) {
entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity);
}
}
// Run change task if applicable
if (changeTask != null) {
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
changeTask.run(previous);
}
// Trim tiles // Trim tiles
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet(); Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator(); Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
@ -128,24 +399,31 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
int ly = pos.getY(); int ly = pos.getY();
int lz = pos.getZ() & 15; int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz]; int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz];
char[] array = fs.getIdArray(j); char[] array = fs.getIdArray(j);
if (array == null) { if (array == null) {
continue; continue;
} }
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) { if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove(); iterator.remove();
} }
} }
// Trim entities HashSet<UUID> entsToRemove = fs.getEntityRemoves();
for (int i = 0; i < 16; i++) { if (entsToRemove.size() > 0) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { for (int i = 0; i < entities.length; i++) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class); Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entsToRemove.contains(entity.getUniqueID())) {
nmsWorld.removeEntity(entity);
}
}
} }
} }
// Efficiently merge sections // Efficiently merge sections
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) { int count = fs.getCount(j);
if (count == 0) {
continue; continue;
} }
char[] newArray = fs.getIdArray(j); char[] newArray = fs.getIdArray(j);
@ -153,14 +431,20 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
continue; continue;
} }
ExtendedBlockStorage section = sections[j]; ExtendedBlockStorage section = sections[j];
if ((section == null) || (fs.getCount(j) >= 4096)) {
if ((section == null)) {
section = new ExtendedBlockStorage(j << 4, flag); section = new ExtendedBlockStorage(j << 4, flag);
section.setData(newArray); section.setData(newArray);
sections[j] = section; sections[j] = section;
continue; continue;
} else if (count >= 4096){
section.setData(newArray);
setCount(0, count - fs.getAir(j), section);
continue;
} }
char[] currentArray = section.getData(); char[] currentArray = section.getData();
boolean fill = true; boolean fill = true;
int solid = 0;
for (int k = 0; k < newArray.length; k++) { for (int k = 0; k < newArray.length; k++) {
char n = newArray[k]; char n = newArray[k];
switch (n) { switch (n) {
@ -169,18 +453,55 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
continue; continue;
case 1: case 1:
fill = false; fill = false;
if (currentArray[k] > 1) {
solid++;
}
currentArray[k] = 0; currentArray[k] = 0;
continue; continue;
default: default:
solid++;
currentArray[k] = n; currentArray[k] = n;
continue; continue;
} }
} }
setCount(0, solid, section);
if (fill) { if (fill) {
fs.setCount(j, Short.MAX_VALUE); fs.setCount(j, Short.MAX_VALUE);
} }
} }
// // Clear
// Set biomes
int[][] biomes = fs.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
int bx = fs.getX() << 4;
int bz = fs.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();
BlockPos pos = new BlockPos(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
tileEntity.readFromNBT(tag); // ReadTagIntoTile
}
}
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -196,11 +517,11 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
if (biome == 0) { if (biome == 0) {
continue; continue;
} }
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
} }
} }
} }
sendChunk(fs); sendChunk(fs, null);
return true; return true;
} }
@ -240,85 +561,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
return new ForgeChunk_All(this, x, z); return new ForgeChunk_All(this, x, z);
} }
@Override
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
try {
ForgeChunk_All fc = (ForgeChunk_All) chunk;
Chunk forgeChunk = fc.getChunk();
if (!forgeChunk.isLoaded()) {
forgeChunk.onChunkLoad();
}
forgeChunk.generateSkylightMap();
if (fc.getTotalRelight() == 0 && !fixAll) {
return true;
}
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
int X = fc.getX() << 4;
int Z = fc.getZ() << 4;
for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j];
if (section == null) {
continue;
}
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
continue;
}
char[] array = section.getData();
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) {
int i = array[k];
if (i < 16) {
continue;
}
short id = (short) (i >> 4);
switch (id) { // Lighting
default:
if (!fixAll) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue;
}
BlockPos pos = new BlockPos(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
}
}
return true;
} catch (Throwable e) {
if (Thread.currentThread() == Fawe.get().getMainThread()) {
e.printStackTrace();
}
}
return false;
}
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) { public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z)) return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z)) && isSolid(getId(sections, x + 1, y - 1, z))

View File

@ -8,7 +8,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<artifactId>FastAsyncWorldEdit</artifactId> <artifactId>FastAsyncWorldEdit</artifactId>
<version>3.4.3</version> <version>3.5.0</version>
<name>FastAsyncWorldEdit</name> <name>FastAsyncWorldEdit</name>
<packaging>jar</packaging> <packaging>jar</packaging>
<build> <build>

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.IFawe; import com.boydti.fawe.IFawe;
import com.boydti.fawe.SpongeCommand; import com.boydti.fawe.SpongeCommand;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.EditSessionWrapper;
import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
@ -109,7 +110,7 @@ public class FaweSponge implements IFawe {
@Override @Override
public FaweQueue getNewQueue(String world, boolean fast) { public FaweQueue getNewQueue(String world, boolean fast) {
if (fast) { if (fast || Settings.COMBINE_HISTORY_STAGE) {
try { try {
return new SpongeQueue_1_8(world); return new SpongeQueue_1_8(world);
} catch (Throwable e) { } catch (Throwable e) {

View File

@ -18,7 +18,7 @@ import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.profile.GameProfileManager; import org.spongepowered.api.profile.GameProfileManager;
import org.spongepowered.api.world.World; import org.spongepowered.api.world.World;
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.4.3", authors = "Empire92") @Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.5.0", authors = "Empire92")
public class SpongeMain { public class SpongeMain {
public PluginContainer plugin; public PluginContainer plugin;

View File

@ -8,7 +8,9 @@ import java.util.UUID;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.text.serializer.TextSerializers; import org.spongepowered.api.text.serializer.TextSerializers;
import org.spongepowered.api.text.title.Title;
import org.spongepowered.api.world.Location; import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World; import org.spongepowered.api.world.World;
@ -17,6 +19,19 @@ public class SpongePlayer extends FawePlayer<Player> {
super(parent); super(parent);
} }
@Override
public void sendTitle(String head, String sub) { // Not supported
Text headText = TextSerializers.LEGACY_FORMATTING_CODE.deserialize(BBC.color(head));
Text subText = TextSerializers.LEGACY_FORMATTING_CODE.deserialize(BBC.color(sub));
final Title title = Title.builder().title(headText).subtitle(subText).fadeIn(0).stay(60).fadeOut(20).build();
parent.sendTitle(title);
}
@Override
public void resetTitle() { // Not supported
parent.resetTitle();
}
@Override @Override
public String getName() { public String getName() {
return this.parent.getName(); return this.parent.getName();

View File

@ -2,17 +2,35 @@ package com.boydti.fawe.sponge.v1_8;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData; import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -21,6 +39,7 @@ import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.LongHashMap; import net.minecraft.util.LongHashMap;
import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer; import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
@ -30,8 +49,20 @@ import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World; import org.spongepowered.api.world.World;
public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.world.chunk.Chunk, ExtendedBlockStorage[], char[]> { public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.world.chunk.Chunk, ExtendedBlockStorage[], char[]> {
private Method methodFromNative;
private Method methodToNative;
public SpongeQueue_1_8(String world) { public SpongeQueue_1_8(String world) {
super(world); super(world);
try {
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
this.methodFromNative = converter.getDeclaredMethod("toNative", Tag.class);
this.methodToNative = converter.getDeclaredMethod("fromNative", NBTBase.class);
methodFromNative.setAccessible(true);
methodToNative.setAccessible(true);
} catch (Throwable e) {
throw new RuntimeException(e);
}
} }
@Override @Override
@ -120,7 +151,71 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
} }
@Override @Override
public boolean setComponents(FaweChunk fc) { public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<BlockPos, TileEntity> tiles = (Map<BlockPos, TileEntity>) tilesGeneric;
ClassInheritanceMultiMap<Entity>[] entities = (ClassInheritanceMultiMap<Entity>[]) entitiesGeneric;
CharFaweChunk previous = (CharFaweChunk) getChunk(fs.getX(), fs.getZ());
char[][] idPrevious = new char[16][];
for (int layer = 0; layer < sections.length; layer++) {
if (fs.getCount(layer) != 0 || all) {
ExtendedBlockStorage section = sections[layer];
if (section != null) {
idPrevious[layer] = section.getData().clone();
short solid = 0;
for (int combined : idPrevious[layer]) {
if (combined > 1) {
solid++;
}
}
previous.count[layer] = solid;
previous.air[layer] = (short) (4096 - solid);
}
}
}
previous.ids = idPrevious;
if (tiles != null) {
for (Map.Entry<BlockPos, TileEntity> entry : tiles.entrySet()) {
TileEntity tile = entry.getValue();
NBTTagCompound tag = new NBTTagCompound();
tile.readFromNBT(tag); // readTileEntityIntoTag
BlockPos pos = entry.getKey();
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
}
}
if (entities != null) {
for (Collection<Entity> entityList : entities) {
for (Entity ent : entityList) {
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && !createdEntities.contains(ent.getUniqueID()))) {
continue;
}
int x = ((int) Math.round(ent.posX) & 15);
int z = ((int) Math.round(ent.posZ) & 15);
int y = (int) Math.round(ent.posY);
int i = FaweCache.CACHE_I[y][x][z];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
String id = EntityList.getEntityString(ent);
if (id != null) {
NBTTagCompound tag = ent.getNBTTagCompound(); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(null, tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
}
}
}
}
}
return previous;
}
@Override
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc; SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
@ -130,6 +225,65 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray(); ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap(); Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists(); ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
// Remove entities
for (int i = 0; i < 16; i++) {
int count = fs.getCount(i);
if (count == 0) {
continue;
} else if (count >= 4096) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
} else {
char[] array = fs.getIdArray(i);
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
continue;
}
int x = ((int) Math.round(entity.posX) & 15);
int z = ((int) Math.round(entity.posZ) & 15);
int y = (int) Math.round(entity.posY);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][x][z];
if (array[j] != 0) {
nmsWorld.removeEntity(entity);
}
}
}
}
// Set entities
Set<UUID> createdEntities = new HashSet<>();
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
for (CompoundTag nativeTag : entitiesToSpawn) {
Map<String, Tag> entityTagMap = nativeTag.getValue();
StringTag idTag = (StringTag) entityTagMap.get("Id");
ListTag posTag = (ListTag) entityTagMap.get("Pos");
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
if (idTag == null || posTag == null || rotTag == null) {
Fawe.debug("Unknown entity tag: " + nativeTag);
continue;
}
double x = posTag.getDouble(0);
double y = posTag.getDouble(1);
double z = posTag.getDouble(2);
float yaw = rotTag.getFloat(0);
float pitch = rotTag.getFloat(1);
String id = idTag.getValue();
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
if (entity != null) {
entity.setPositionAndRotation(x, y, z, yaw, pitch);
nmsWorld.spawnEntityInWorld(entity);
}
}
// Run change task if applicable
if (changeTask != null) {
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
changeTask.run(previous);
}
// Trim tiles // Trim tiles
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet(); Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator(); Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
@ -140,19 +294,25 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
int ly = pos.getY(); int ly = pos.getY();
int lz = pos.getZ() & 15; int lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz]; int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz];
char[] array = fs.getIdArray(j); char[] array = fs.getIdArray(j);
if (array == null) { if (array == null) {
continue; continue;
} }
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) { if (array[k] != 0) {
tile.getValue().invalidate();
iterator.remove(); iterator.remove();
} }
} }
// Trim entities HashSet<UUID> entsToRemove = fs.getEntityRemoves();
for (int i = 0; i < 16; i++) { if (entsToRemove.size() > 0) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) { for (int i = 0; i < entities.length; i++) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class); Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entsToRemove.contains(entity.getUniqueID())) {
nmsWorld.removeEntity(entity);
}
}
} }
} }
// Efficiently merge sections // Efficiently merge sections
@ -204,6 +364,39 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
fs.setCount(j, Short.MAX_VALUE); fs.setCount(j, Short.MAX_VALUE);
} }
} }
// Set biomes
int[][] biomes = fs.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
// Set tiles
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
int bx = fs.getX() << 4;
int bz = fs.getZ() << 4;
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
BytePair pair = entry.getKey();
BlockPos pos = new BlockPos(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
tileEntity.readFromNBT(tag); // ReadTagIntoTile
}
}
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -223,7 +416,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
} }
} }
} }
sendChunk(fs); sendChunk(fs, null);
return true; return true;
} }
@ -244,49 +437,69 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
@Override @Override
public boolean fixLighting(FaweChunk fc, boolean fixAll) { public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
try { try {
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc; SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
if (!nmsChunk.isLoaded()) { if (!nmsChunk.isLoaded()) {
if (!((Chunk) nmsChunk).loadChunk(false)) {
return false; return false;
} }
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
if (mode == RelightMode.ALL) {
for (int i = 0; i < sections.length; i++) {
ExtendedBlockStorage section = sections[i];
if (section != null) {
section.setSkylightArray(new NibbleArray());
section.setBlocklightArray(new NibbleArray());
}
}
} }
nmsChunk.generateSkylightMap(); nmsChunk.generateSkylightMap();
if (bc.getTotalRelight() == 0 && !fixAll) { if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true; return true;
} }
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = bc.getX() << 4; int X = fc.getX() << 4;
int Z = bc.getZ() << 4; int Z = fc.getZ() << 4;
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j]; ExtendedBlockStorage section = sections[j];
if (section == null) { if (section == null) {
continue; continue;
} }
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) { if (((bc.getRelight(j) == 0) && mode == RelightMode.MINIMAL) || (bc.getCount(j) == 0 && mode != RelightMode.ALL) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0)) || bc.getAir(j) == 4096) {
continue; continue;
} }
char[] array = section.getData(); char[] array = section.getData();
int l = PseudoRandom.random.random(2); if (mode == RelightMode.ALL) {
for (int k = 0; k < array.length; k++) { for (int k = array.length - 1; k >= 0; k--) {
int i = array[k]; final int x = FaweCache.CACHE_X[j][k];
if (i < 16) { final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }
short id = (short) (i >> 4); pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
continue;
}
for (int k = array.length - 1; k >= 0; k--) {
final int i = array[k];
final short id = (short) (i >> 4);
switch (id) { // Lighting switch (id) { // Lighting
case 0:
continue;
default: default:
if (!fixAll) { if (mode == RelightMode.MINIMAL) {
continue; continue;
} }
if ((k & 1) == l) { if (PseudoRandom.random.random(3) != 0) {
l = 1 - l;
continue; continue;
} }
case 10: case 10:
@ -304,13 +517,13 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
case 130: case 130:
case 138: case 138:
case 169: case 169:
int x = FaweCache.CACHE_X[j][k]; final int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k]; final int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k]; final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) { if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }
BlockPos pos = new BlockPos(X + x, y, Z + z); pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos); nmsWorld.checkLight(pos);
} }
} }
@ -368,4 +581,6 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
public int getCombinedId4Data(char[] chars, int x, int y, int z) { public int getCombinedId4Data(char[] chars, int x, int y, int z) {
return chars[FaweCache.CACHE_J[y][x & 15][z & 15]]; return chars[FaweCache.CACHE_J[y][x & 15][z & 15]];
} }
} }

View File

@ -2,12 +2,18 @@ package com.boydti.fawe.sponge.v1_8;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RunnableVal;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
@ -17,6 +23,7 @@ import net.minecraft.util.BlockPos;
import net.minecraft.util.LongHashMap; import net.minecraft.util.LongHashMap;
import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer; import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.api.Sponge; import org.spongepowered.api.Sponge;
@ -125,7 +132,11 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
private BlockState AIR = BlockTypes.AIR.getDefaultState(); private BlockState AIR = BlockTypes.AIR.getDefaultState();
@Override @Override
public boolean setComponents(FaweChunk fc) { public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
if (changeTask != null) {
Settings.COMBINE_HISTORY_STAGE = false;
throw new UnsupportedOperationException("Combine stages not supported");
}
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc; SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
Chunk spongeChunk = (Chunk) nmsChunk; Chunk spongeChunk = (Chunk) nmsChunk;
@ -162,7 +173,7 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
} }
} }
}); });
sendChunk(fs); sendChunk(fs, null);
return true; return true;
} }
@ -181,51 +192,76 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
return new SpongeChunk_1_8(this, x, z); return new SpongeChunk_1_8(this, x, z);
} }
@Override
public CharFaweChunk getPrevious(CharFaweChunk fs, ExtendedBlockStorage[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Settings.COMBINE_HISTORY_STAGE = false;
throw new UnsupportedOperationException("Combine stages not supported");
}
@Override @Override
public boolean fixLighting(FaweChunk fc, boolean fixAll) { public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
try { try {
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc; SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk(); net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
if (!nmsChunk.isLoaded()) { if (!nmsChunk.isLoaded()) {
if (!((Chunk) nmsChunk).loadChunk(false)) {
return false; return false;
} }
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
if (mode == RelightMode.ALL) {
for (int i = 0; i < sections.length; i++) {
ExtendedBlockStorage section = sections[i];
if (section != null) {
section.setSkylightArray(new NibbleArray());
section.setBlocklightArray(new NibbleArray());
}
}
} }
nmsChunk.generateSkylightMap(); nmsChunk.generateSkylightMap();
if (bc.getTotalRelight() == 0 && !fixAll) { if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true; return true;
} }
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = bc.getX() << 4; int X = fc.getX() << 4;
int Z = bc.getZ() << 4; int Z = fc.getZ() << 4;
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j]; ExtendedBlockStorage section = sections[j];
if (section == null) { if (section == null) {
continue; continue;
} }
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) { if (((bc.getRelight(j) == 0) && mode == RelightMode.MINIMAL) || (bc.getCount(j) == 0 && mode != RelightMode.ALL) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0)) || bc.getAir(j) == 4096) {
continue; continue;
} }
char[] array = section.getData(); char[] array = section.getData();
int l = PseudoRandom.random.random(2); if (mode == RelightMode.ALL) {
for (int k = 0; k < array.length; k++) { for (int k = array.length - 1; k >= 0; k--) {
int i = array[k]; final int x = FaweCache.CACHE_X[j][k];
if (i < 16) { final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }
short id = (short) (i >> 4); pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
continue;
}
for (int k = array.length - 1; k >= 0; k--) {
final int i = array[k];
final short id = (short) (i >> 4);
switch (id) { // Lighting switch (id) { // Lighting
case 0:
continue;
default: default:
if (!fixAll) { if (mode == RelightMode.MINIMAL) {
continue; continue;
} }
if ((k & 1) == l) { if (PseudoRandom.random.random(3) != 0) {
l = 1 - l;
continue; continue;
} }
case 10: case 10:
@ -243,13 +279,13 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
case 130: case 130:
case 138: case 138:
case 169: case 169:
int x = FaweCache.CACHE_X[j][k]; final int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k]; final int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k]; final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(sections, x, y, z)) { if (isSurrounded(sections, x, y, z)) {
continue; continue;
} }
BlockPos pos = new BlockPos(X + x, y, Z + z); pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos); nmsWorld.checkLight(pos);
} }
} }