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 {
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'
def revision = ""
ext {
git = org.ajoberstar.grgit.Grgit.open(file(".git/"))
git = org.ajoberstar.grgit.Grgit.open(file(".git"))
revision = "-${git.head().abbreviatedId}"
}
version = "3.5.0${revision}"

View File

@ -13,14 +13,4 @@ dependencies {
compile 'com.worldcretornica:plotme_core:0.16.3'
compile 'junit:junit:4.11'
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'
}
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
jar.enabled = false

View File

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

View File

@ -3,8 +3,17 @@ dependencies {
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
jar.enabled = false
shadowJar {

View File

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

View File

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

View File

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

View File

@ -109,9 +109,9 @@ public abstract class FawePlayer<T> {
}
public void loadClipboardFromDisk() {
File file = new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + getUUID());
try {
File file = new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + getUUID());
if (file.exists()) {
if (file.exists() && file.length() > 5) {
DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file);
Player player = getPlayer();
LocalSession session = getSession();
@ -128,8 +128,13 @@ public abstract class FawePlayer<T> {
getSession().setClipboard(holder);
}
}
} catch (Exception e) {
e.printStackTrace();
} catch (Exception ignore) {
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
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
final short id = (short) block.getId();
byte data = (byte) block.getData();
final int x = location.getBlockX();
final int y = location.getBlockY();
final int z = location.getBlockZ();
switch (id) {
case 68: {
if (data == 0) {
data = 2;
}
}
case 63:
case 68:
if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) {
queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
return true;
}
case 54:
case 146:
case 61:
{
if (data == 0) {
data = 2;
}
}
case 130:
case 142:
case 27:
@ -138,10 +150,8 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
@ -157,11 +167,16 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
MainUtil.setPosition(nbt, x, y, z);
queue.setTile(x, y, z, nbt);
}
queue.setBlock(x, y, z, id, (byte) block.getData());
queue.setBlock(x, y, z, id, data);
return true;
}
case 65: {
if (data == 0) {
data = 2;
}
}
default: {
queue.setBlock(x, y, z, id, (byte) block.getData());
queue.setBlock(x, y, z, id, data);
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.StringMan;
import com.boydti.fawe.util.TaskManager;
import org.bukkit.Bukkit;
public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType, Integer> {
@ -63,7 +62,7 @@ public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType,
TaskManager.IMP.task(new Runnable() {
@Override
public void run() {
long currentTick = Bukkit.getServer().getWorlds().get(0).getFullTime();
long currentTick = System.currentTimeMillis() / 50;
if (currentTick > lastTick + Settings.DISPLAY_PROGRESS_INTERVAL) {
lastTick = currentTick;
String queue = StringMan.padRight("" + amountQueue, 3);

View File

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

View File

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

View File

@ -20,8 +20,6 @@
package com.sk89q.worldedit.command;
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.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
@ -162,41 +160,31 @@ public class SchematicCommands {
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();
try {
// Create parent directories
final File parent = f.getParentFile();
if ((parent != null) && !parent.exists()) {
if (!parent.mkdirs()) {
log.info("Could not create folder for schematics!");
return;
}
}
final FileOutputStream fos = closer.register(new FileOutputStream(f));
final BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
final ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target, holder.getWorldData());
log.info(player.getName() + " saved " + f.getCanonicalPath());
BBC.SCHEMATIC_SAVED.send(player, filename);
} catch (final IOException e) {
player.printError("Schematic could not written: " + e.getMessage());
log.log(Level.WARNING, "Failed to write a saved clipboard", e);
} finally {
try {
closer.close();
} catch (final IOException ignored) {}
}
}
});
final Closer closer = Closer.create();
try {
// Create parent directories
final File parent = f.getParentFile();
if ((parent != null) && !parent.exists()) {
if (!parent.mkdirs()) {
log.info("Could not create folder for schematics!");
return;
}
}
});
final FileOutputStream fos = closer.register(new FileOutputStream(f));
final BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
final ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target, holder.getWorldData());
log.info(player.getName() + " saved " + f.getCanonicalPath());
BBC.SCHEMATIC_SAVED.send(player, filename);
} catch (final IOException e) {
player.printError("Schematic could not written: " + e.getMessage());
log.log(Level.WARNING, "Failed to write a saved clipboard", e);
} finally {
try {
closer.close();
} 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)
@ -207,22 +195,15 @@ public class SchematicCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
final File f = this.worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
if (!f.exists()) {
player.printError("Schematic " + filename + " does not exist!");
return;
}
if (!f.delete()) {
player.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
return;
}
BBC.SCHEMATIC_DELETE.send(player, filename);
}
});
if (!f.exists()) {
player.printError("Schematic " + filename + " does not exist!");
return;
}
if (!f.delete()) {
player.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
return;
}
BBC.SCHEMATIC_DELETE.send(player, filename);
}
@Command(aliases = { "formats", "listformats", "f" }, desc = "List available formats", max = 0)

View File

@ -19,8 +19,6 @@
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.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -69,21 +67,11 @@ public class ScriptingCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir);
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 {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript.");
}
}
});
}
});
try {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript.");
}
}
@Command(aliases = { ".s" }, usage = "[args...]", desc = "Execute last CraftScript", min = 0, max = -1)
@ -107,21 +95,11 @@ public class ScriptingCommands {
final File dir = this.worldEdit.getWorkingDirectoryFile(this.worldEdit.getConfiguration().scriptsDir);
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 {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript.");
}
}
});
}
});
try {
ScriptingCommands.this.worldEdit.runScript(player, f, scriptArgs);
} catch (final WorldEditException ex) {
player.printError("Error while executing CraftScript.");
}
}
public static Class<?> inject() {

View File

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

View File

@ -19,7 +19,7 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
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 {
private static FaweForge IMP;
private Logger logger;

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.forge;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.entity.Player;
@ -16,6 +17,16 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
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
public String getName() {
return parent.getCommandSenderName();

View File

@ -1,105 +1,32 @@
package com.boydti.fawe.forge.v0;
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.MainUtil;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Arrays;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
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 short[] count;
public short[] air;
public short[] relight;
public byte[][] biomes;
public Chunk chunk;
public ForgeChunk_All(FaweQueue parent, int x, int z) {
super(parent, x, z);
this.ids = new byte[16][];
this.byteIds = new byte[16][];
this.datas = new NibbleArray[16];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public Chunk getChunk() {
if (this.chunk == null) {
World world = ((ForgeQueue_All) getParent()).getWorld();
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ());
}
return this.chunk;
}
@Override
public void setLoc(final FaweQueue parent, int x, int z) {
super.setLoc(parent, x, z);
this.chunk = null;
public Chunk getNewChunk() {
World world = ((ForgeQueue_All) getParent()).getWorld();
return world.getChunkProvider().provideChunk(getX(), getZ());
}
/**
* 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 byte[] getByteIdArray(int i) {
return this.byteIds[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) {
int i = FaweCache.CACHE_I[y][x][z];
int j = FaweCache.CACHE_J[y][x][z];
byte[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new byte[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
byte[] vs = this.byteIds[i];
char[] vs2 = this.ids[i];
if (vs2 == null) {
vs2 = this.ids[i] = new char[4096];
}
if (vs == null) {
vs = this.byteIds[i] = new byte[4096];
}
this.count[i]++;
switch (id) {
case 0:
this.air[i]++;
vs[j] = -1;
vs2[j] = (char) 1;
return;
case 10:
case 11:
@ -193,6 +123,7 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 191:
case 192:
vs[j] = (byte) (id);
vs2[j] = (char) (id << 4);
return;
case 130:
case 76:
@ -203,38 +134,26 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
case 146:
case 61:
case 65:
case 68:
// if (data < 2) {
// data = 2;
// }
case 68: // removed
default:
vs2[j] = (char) ((id << 4) + data);
vs[j] = (byte) id;
NibbleArray dataArray = datas[i];
if (dataArray == null) {
datas[i] = dataArray = new NibbleArray(4096, 4);
if (data != 0) {
NibbleArray dataArray = datas[i];
if (dataArray == null) {
datas[i] = dataArray = new NibbleArray(4096, 4);
}
dataArray.set(x, y & 15, z, data);
}
dataArray.set(x, y & 15, z, data);
return;
}
}
@Override
public void setBiome(int x, int z, BaseBiome biome) {
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) {
public CharFaweChunk<Chunk> copy(boolean shallow) {
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
if (shallow) {
copy.ids = ids;
copy.byteIds = byteIds;
copy.datas = datas;
copy.air = air;
copy.biomes = biomes;
@ -242,7 +161,7 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
copy.count = count;
copy.relight = relight;
} else {
copy.ids = (byte[][]) MainUtil.copyNd(ids);
copy.byteIds = (byte[][]) MainUtil.copyNd(byteIds);
copy.datas = datas.clone();
copy.air = air.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.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.forge.ForgePlayer;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.IntegerPair;
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.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
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.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData;
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.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);
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
@ -44,12 +74,17 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
}
@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);
if (chunk != null && !chunk.isChunkLoaded) {
chunk.onChunkLoad();
}
return chunk;
return chunk != null ? chunk.getBlockStorageArray() : null;
}
@Override
public ExtendedBlockStorage getCachedSection(ExtendedBlockStorage[] extendedBlockStorages, int cy) {
return extendedBlockStorages[cy];
}
@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;
Chunk forgeChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
try {
boolean flag = !nmsWorld.provider.hasNoSky;
// Sections
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
Map<ChunkPosition, TileEntity> tiles = forgeChunk.chunkTileEntityMap;
List[] entities = forgeChunk.entityLists;
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<ChunkPosition, TileEntity> tiles = nmsChunk.chunkTileEntityMap;
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
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
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 lz = pos.chunkPosZ & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz];
byte[] array = fs.getIdArray(j);
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) {
tile.getValue().invalidate();;
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
for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) {
continue;
}
byte[] newIdArray = fs.getIdArray(j);
byte[] newIdArray = fs.getByteIdArray(j);
if (newIdArray == null) {
continue;
}
@ -232,8 +338,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
section.setBlockMetadataArray(newDataArray);
continue;
}
// id + data << 8
byte[] currentIdArray = section.getBlockLSBArray();
NibbleArray currentDataArray = section.getMetadataArray();
boolean data = currentDataArray != null;
@ -241,6 +345,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
section.setBlockMetadataArray(newDataArray);
}
boolean fill = true;
int solid = 0;
for (int k = 0; k < newIdArray.length; k++) {
byte n = newIdArray[k];
switch (n) {
@ -249,9 +354,13 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
continue;
case -1:
fill = false;
if (currentIdArray[k] != 0) {
solid++;
}
currentIdArray[k] = 0;
continue;
default:
solid++;
currentIdArray[k] = n;
if (data) {
int x = FaweCache.CACHE_X[j][k];
@ -266,81 +375,212 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
continue;
}
}
setCount(0, solid, section);
if (fill) {
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();
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();
}
byte[][] biomes = fs.biomes;
int[][] biomes = fs.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
byte[] array = biomes[x];
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
byte biome = array[z];
int biome = array[z];
if (biome == 0) {
continue;
}
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome;
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
}
}
}
sendChunk(fs);
sendChunk(fs, null);
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
public FaweChunk getChunk(int x, int z) {
return new ForgeChunk_All(this, x, z);
}
@Override
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
try {
ForgeChunk_All fc = (ForgeChunk_All) chunk;
Chunk forgeChunk = fc.getChunk();
if (!forgeChunk.isChunkLoaded) {
forgeChunk.onChunkLoad();
ForgeChunk_All bc = (ForgeChunk_All) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
if (!nmsChunk.isChunkLoaded) {
return false;
}
forgeChunk.generateSkylightMap();
if (fc.getTotalRelight() == 0 && !fixAll) {
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;
}
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
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)) {
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;
}
byte[] array = section.getBlockLSBArray();
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) {
int i = array[k];
if (i < 16) {
continue;
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;
}
nmsWorld.func_147451_t(X + x, y, Z + z);
}
short id = (short) (i);
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 (!fixAll) {
if (mode == RelightMode.MINIMAL) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
if (PseudoRandom.random.random(3) != 0) {
continue;
}
case 10:
@ -358,9 +598,9 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, Exte
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];
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;
}

View File

@ -2,7 +2,7 @@
"modid": "com.boydti.fawe",
"name": "FastAsyncWorldEdit",
"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",
"dependencies": [
"WorldEdit"

View File

@ -126,7 +126,7 @@ public class FaweForge implements IFawe {
@Override
public void startMetrics() {
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();
debug("[FAWE] &6Metrics enabled.");
} catch (Throwable e) {

View File

@ -19,7 +19,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
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 {
private static com.boydti.fawe.forge.FaweForge IMP;
private Logger logger;

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.forge;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.entity.Player;
@ -16,6 +17,16 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
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
public String 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.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.forge.ForgePlayer;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
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.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
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.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.server.MinecraftServer;
@ -25,13 +43,26 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
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);
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
@ -89,12 +120,18 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
}
@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);
if (chunk != null && !chunk.isLoaded()) {
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
@ -107,17 +144,251 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
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
public boolean setComponents(FaweChunk fc) {
ForgeChunk_All fs = (ForgeChunk_All) fc;
Chunk forgeChunk = fs.getChunk();
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
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 {
boolean flag = !nmsWorld.provider.getHasNoSky();
// Sections
ExtendedBlockStorage[] sections = forgeChunk.getBlockStorageArray();
Map<BlockPos, TileEntity> tiles = forgeChunk.getTileEntityMap();
ClassInheritanceMultiMap<Entity>[] entities = forgeChunk.getEntityLists();
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
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
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
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 lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) {
tile.getValue().invalidate();;
iterator.remove();
}
}
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
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
for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) {
int count = fs.getCount(j);
if (count == 0) {
continue;
}
char[] newArray = fs.getIdArray(j);
@ -153,14 +431,20 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
continue;
}
ExtendedBlockStorage section = sections[j];
if ((section == null) || (fs.getCount(j) >= 4096)) {
if ((section == null)) {
section = new ExtendedBlockStorage(j << 4, flag);
section.setData(newArray);
sections[j] = section;
continue;
} else if (count >= 4096){
section.setData(newArray);
setCount(0, count - fs.getAir(j), section);
continue;
}
char[] currentArray = section.getData();
boolean fill = true;
int solid = 0;
for (int k = 0; k < newArray.length; k++) {
char n = newArray[k];
switch (n) {
@ -169,18 +453,55 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
continue;
case 1:
fill = false;
if (currentArray[k] > 1) {
solid++;
}
currentArray[k] = 0;
continue;
default:
solid++;
currentArray[k] = n;
continue;
}
}
setCount(0, solid, section);
if (fill) {
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) {
e.printStackTrace();
}
@ -196,11 +517,11 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
if (biome == 0) {
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;
}
@ -240,85 +561,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char
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) {
return isSolid(getId(sections, x, 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>
</properties>
<artifactId>FastAsyncWorldEdit</artifactId>
<version>3.4.3</version>
<version>3.5.0</version>
<name>FastAsyncWorldEdit</name>
<packaging>jar</packaging>
<build>

View File

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

View File

@ -8,7 +8,9 @@ import java.util.UUID;
import net.minecraft.entity.player.EntityPlayerMP;
import org.spongepowered.api.Sponge;
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.title.Title;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
@ -17,6 +19,19 @@ public class SpongePlayer extends FawePlayer<Player> {
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
public String 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.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.BytePair;
import com.boydti.fawe.object.FaweChunk;
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.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
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.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.tileentity.TileEntity;
@ -21,6 +39,7 @@ import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.LongHashMap;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.api.Sponge;
@ -30,8 +49,20 @@ import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
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) {
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
@ -120,7 +151,71 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
}
@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;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
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();
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
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
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
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 lz = pos.getZ() & 15;
int j = FaweCache.CACHE_I[ly][lx][lz];
int k = FaweCache.CACHE_J[ly][lx][lz];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
int k = FaweCache.CACHE_J[ly][lx][lz];
if (array[k] != 0) {
tile.getValue().invalidate();
iterator.remove();
}
}
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
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
@ -204,6 +364,39 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
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) {
e.printStackTrace();
}
@ -223,7 +416,7 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
}
}
}
sendChunk(fs);
sendChunk(fs, null);
return true;
}
@ -244,49 +437,69 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
@Override
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
try {
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
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();
if (bc.getTotalRelight() == 0 && !fixAll) {
if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = bc.getX() << 4;
int Z = bc.getZ() << 4;
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 && !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;
}
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;
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);
}
short id = (short) (i >> 4);
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 (!fixAll) {
if (mode == RelightMode.MINIMAL) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
if (PseudoRandom.random.random(3) != 0) {
continue;
}
case 10:
@ -304,13 +517,13 @@ public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.wor
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];
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;
}
BlockPos pos = new BlockPos(X + x, y, Z + z);
pos.set(X + x, y, Z + z);
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) {
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.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RunnableVal;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayerMP;
@ -17,6 +23,7 @@ import net.minecraft.util.BlockPos;
import net.minecraft.util.LongHashMap;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.NibbleArray;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.minecraft.world.gen.ChunkProviderServer;
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();
@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;
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
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;
}
@ -181,51 +192,76 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
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
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
public boolean fixLighting(FaweChunk<?> fc, RelightMode mode) {
if (mode == RelightMode.NONE) {
return true;
}
try {
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
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();
if (bc.getTotalRelight() == 0 && !fixAll) {
if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
return true;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = bc.getX() << 4;
int Z = bc.getZ() << 4;
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 && !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;
}
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;
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);
}
short id = (short) (i >> 4);
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 (!fixAll) {
if (mode == RelightMode.MINIMAL) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
if (PseudoRandom.random.random(3) != 0) {
continue;
}
case 10:
@ -243,13 +279,13 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
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];
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;
}
BlockPos pos = new BlockPos(X + x, y, Z + z);
pos.set(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
}