Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-24 18:10:08 +01:00
tile/biome/entity set
Dieser Commit ist enthalten in:
Ursprung
ad52e01e9f
Commit
8dcc005ec1
@ -1,18 +1,51 @@
|
|||||||
package com.boydti.fawe.bukkit.beta;
|
package com.boydti.fawe.bukkit.beta;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.beta.Filter;
|
import com.boydti.fawe.beta.Filter;
|
||||||
import com.boydti.fawe.beta.IChunk;
|
import com.boydti.fawe.beta.IChunk;
|
||||||
import com.boydti.fawe.beta.IGetBlocks;
|
import com.boydti.fawe.beta.IGetBlocks;
|
||||||
import com.boydti.fawe.beta.IQueueExtent;
|
import com.boydti.fawe.beta.IQueueExtent;
|
||||||
|
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||||
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
||||||
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
||||||
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
|
import com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13;
|
||||||
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.LongTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import net.jpountz.util.UnsafeUtils;
|
import net.jpountz.util.UnsafeUtils;
|
||||||
|
import net.minecraft.server.v1_13_R2.BiomeBase;
|
||||||
|
import net.minecraft.server.v1_13_R2.BlockPosition;
|
||||||
import net.minecraft.server.v1_13_R2.Chunk;
|
import net.minecraft.server.v1_13_R2.Chunk;
|
||||||
import net.minecraft.server.v1_13_R2.ChunkSection;
|
import net.minecraft.server.v1_13_R2.ChunkSection;
|
||||||
|
import net.minecraft.server.v1_13_R2.Entity;
|
||||||
|
import net.minecraft.server.v1_13_R2.EntityTypes;
|
||||||
|
import net.minecraft.server.v1_13_R2.MinecraftKey;
|
||||||
|
import net.minecraft.server.v1_13_R2.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_13_R2.NBTTagInt;
|
||||||
|
import net.minecraft.server.v1_13_R2.TileEntity;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.atomic.AtomicReferenceArray;
|
import java.util.concurrent.atomic.AtomicReferenceArray;
|
||||||
|
|
||||||
@ -54,109 +87,263 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
|||||||
int Z = getZ();
|
int Z = getZ();
|
||||||
|
|
||||||
Chunk nmsChunk = extent.ensureLoaded(X, Z);
|
Chunk nmsChunk = extent.ensureLoaded(X, Z);
|
||||||
|
|
||||||
|
// Remove existing tiles
|
||||||
|
{
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
|
if (!tiles.isEmpty()) {
|
||||||
|
final Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final Map.Entry<BlockPosition, TileEntity> entry = iterator.next();
|
||||||
|
final BlockPosition pos = entry.getKey();
|
||||||
|
final int lx = pos.getX() & 15;
|
||||||
|
final int ly = pos.getY();
|
||||||
|
final int lz = pos.getZ() & 15;
|
||||||
|
final int layer = ly >> 4;
|
||||||
|
final char[] array = set.blocks[layer];
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final int index = (((ly & 0xF) << 8) | (lz << 4) | lx);
|
||||||
|
if (array[index] != 0) {
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
tile.z();
|
||||||
|
tile.invalidateBlockCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int bitMask = 0;
|
int bitMask = 0;
|
||||||
try {
|
synchronized (nmsChunk) {
|
||||||
synchronized (nmsChunk) {
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
World world = extent.getBukkitWorld();
|
||||||
World world = extent.getBukkitWorld();
|
boolean hasSky = world.getEnvironment() == World.Environment.NORMAL;
|
||||||
boolean hasSky = world.getEnvironment() == World.Environment.NORMAL;
|
|
||||||
|
|
||||||
for (int layer = 0; layer < 16; layer++) {
|
for (int layer = 0; layer < 16; layer++) {
|
||||||
if (!set.hasSection(layer)) continue;
|
if (!set.hasSection(layer)) continue;
|
||||||
|
|
||||||
bitMask |= 1 << layer;
|
bitMask |= 1 << layer;
|
||||||
|
|
||||||
char[] setArr = set.blocks[layer];
|
char[] setArr = set.blocks[layer];
|
||||||
ChunkSection newSection;
|
ChunkSection newSection;
|
||||||
ChunkSection existingSection = sections[layer];
|
ChunkSection existingSection = sections[layer];
|
||||||
if (existingSection == null) {
|
if (existingSection == null) {
|
||||||
newSection = extent.newChunkSection(layer, hasSky, setArr);
|
newSection = extent.newChunkSection(layer, hasSky, setArr);
|
||||||
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
|
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
|
||||||
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
existingSection = sections[layer];
|
||||||
|
if (existingSection == null) {
|
||||||
|
System.out.println("Skipping invalid null section. chunk:" + X + "," + Z + " layer: " + layer);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
existingSection = sections[layer];
|
|
||||||
if (existingSection == null) {
|
|
||||||
System.out.println("Skipping invalid null section. chunk:" + X + "," + Z + " layer: " + layer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateLock lock = BukkitQueue.applyLock(existingSection);
|
}
|
||||||
synchronized (lock) {
|
DelegateLock lock = BukkitQueue.applyLock(existingSection);
|
||||||
lock.untilFree();
|
synchronized (lock) {
|
||||||
synchronized (get) {
|
lock.untilFree();
|
||||||
ChunkSection getSection;
|
synchronized (get) {
|
||||||
if (get.nmsChunk != nmsChunk) {
|
ChunkSection getSection;
|
||||||
if (get.nmsChunk != null) System.out.println("chunk doesn't match");
|
if (get.nmsChunk != nmsChunk) {
|
||||||
get.nmsChunk = nmsChunk;
|
if (get.nmsChunk != null) System.out.println("chunk doesn't match");
|
||||||
get.sections = null;
|
get.nmsChunk = nmsChunk;
|
||||||
|
get.sections = null;
|
||||||
|
get.reset();
|
||||||
|
} else {
|
||||||
|
getSection = get.getSections()[layer];
|
||||||
|
if (getSection != existingSection) {
|
||||||
|
get.sections[layer] = existingSection;
|
||||||
get.reset();
|
get.reset();
|
||||||
} else {
|
System.out.println("Section doesn't match");
|
||||||
getSection = get.getSections()[layer];
|
} else if (lock.isModified()) {
|
||||||
if (getSection != existingSection) {
|
System.out.println("lock is outdated");
|
||||||
get.sections[layer] = existingSection;
|
get.reset(layer);
|
||||||
get.reset();
|
|
||||||
System.out.println("Section doesn't match");
|
|
||||||
} else if (lock.isModified()) {
|
|
||||||
System.out.println("lock is outdated");
|
|
||||||
get.reset(layer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
char[] getArr = get.load(layer);
|
}
|
||||||
for (int i = 0; i < 4096; i++) {
|
char[] getArr = get.load(layer);
|
||||||
char value = setArr[i];
|
for (int i = 0; i < 4096; i++) {
|
||||||
if (value != 0) {
|
char value = setArr[i];
|
||||||
getArr[i] = value;
|
if (value != 0) {
|
||||||
}
|
getArr[i] = value;
|
||||||
}
|
|
||||||
newSection = extent.newChunkSection(layer, hasSky, getArr);
|
|
||||||
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
|
||||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
newSection = extent.newChunkSection(layer, hasSky, getArr);
|
||||||
|
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||||
|
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
if (bitMask != 0) {
|
// Biomes
|
||||||
// Set Modified
|
if (set.biomes != null) {
|
||||||
nmsChunk.f(true);
|
// set biomes
|
||||||
nmsChunk.mustSave = true;
|
final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex();
|
||||||
nmsChunk.markDirty();
|
for (int i = 0; i < set.biomes.length; i++) {
|
||||||
// send to player
|
final BiomeType biome = set.biomes[i];
|
||||||
extent.sendChunk(X, Z, bitMask);
|
if (biome != null) {
|
||||||
|
final Biome craftBiome = BukkitAdapter.adapt(biome);
|
||||||
|
currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extent.returnToPool(this);
|
Runnable[] syncTasks = null;
|
||||||
|
|
||||||
|
net.minecraft.server.v1_13_R2.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
int bx = X << 4;
|
||||||
|
int bz = Z << 4;
|
||||||
|
|
||||||
|
if (set.entityRemoves != null && !set.entityRemoves.isEmpty()) {
|
||||||
|
if (syncTasks == null) syncTasks = new Runnable[3];
|
||||||
|
|
||||||
|
HashSet<UUID> entsToRemove = set.entityRemoves;
|
||||||
|
|
||||||
|
syncTasks[2] = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||||
|
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
final Collection<Entity> ents = entities[i];
|
||||||
|
if (!ents.isEmpty()) {
|
||||||
|
final Iterator<Entity> iter = ents.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
final Entity entity = iter.next();
|
||||||
|
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||||
|
iter.remove();
|
||||||
|
entity.b(false);
|
||||||
|
entity.die();
|
||||||
|
entity.valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.entities != null && !set.entities.isEmpty()) {
|
||||||
|
if (syncTasks == null) syncTasks = new Runnable[2];
|
||||||
|
|
||||||
|
HashSet<CompoundTag> entitiesToSpawn = set.entities;
|
||||||
|
|
||||||
|
syncTasks[1] = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (final CompoundTag nativeTag : entitiesToSpawn) {
|
||||||
|
final Map<String, Tag> entityTagMap = ReflectionUtils.getMap(nativeTag.getValue());
|
||||||
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
|
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
if (idTag == null || posTag == null || rotTag == null) {
|
||||||
|
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final double x = posTag.getDouble(0);
|
||||||
|
final double y = posTag.getDouble(1);
|
||||||
|
final double z = posTag.getDouble(2);
|
||||||
|
final float yaw = rotTag.getFloat(0);
|
||||||
|
final float pitch = rotTag.getFloat(1);
|
||||||
|
final String id = idTag.getValue();
|
||||||
|
final Entity entity = EntityTypes.a(nmsWorld, new MinecraftKey(id));
|
||||||
|
if (entity != null) {
|
||||||
|
final UUID uuid = entity.getUniqueID();
|
||||||
|
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
|
||||||
|
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
|
||||||
|
if (nativeTag != null) {
|
||||||
|
final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag);
|
||||||
|
for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
|
tag.remove(name);
|
||||||
|
}
|
||||||
|
entity.f(tag);
|
||||||
|
}
|
||||||
|
entity.setLocation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// set tiles
|
||||||
|
if (set.tiles != null && !set.tiles.isEmpty()) {
|
||||||
|
if (syncTasks == null) syncTasks = new Runnable[1];
|
||||||
|
|
||||||
|
HashMap<Short, CompoundTag> tiles = set.tiles;
|
||||||
|
syncTasks[0] = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (final Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
|
||||||
|
final CompoundTag nativeTag = entry.getValue();
|
||||||
|
final short blockHash = entry.getKey();
|
||||||
|
final int x = (blockHash >> 12 & 0xF) + bx;
|
||||||
|
final int y = (blockHash & 0xFF);
|
||||||
|
final int z = (blockHash >> 8 & 0xF) + bz;
|
||||||
|
final BlockPosition pos = new BlockPosition(x, y, z);
|
||||||
|
synchronized (BukkitQueue_0.class) {
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity == null || tileEntity.x()) {
|
||||||
|
nmsWorld.n(pos);
|
||||||
|
tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
}
|
||||||
|
if (tileEntity != null) {
|
||||||
|
final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag);
|
||||||
|
tag.set("x", new NBTTagInt(x));
|
||||||
|
tag.set("y", new NBTTagInt(y));
|
||||||
|
tag.set("z", new NBTTagInt(z));
|
||||||
|
tileEntity.load(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int finalMask = bitMask;
|
||||||
|
Runnable callback = () -> {
|
||||||
|
if (finalMask != 0) {
|
||||||
|
// Set Modified
|
||||||
|
nmsChunk.f(true);
|
||||||
|
nmsChunk.mustSave = true;
|
||||||
|
nmsChunk.markDirty();
|
||||||
|
// send to player
|
||||||
|
extent.sendChunk(X, Z, finalMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
extent.returnToPool(BukkitChunkHolder.this);
|
||||||
|
};
|
||||||
|
if (syncTasks != null) {
|
||||||
|
QueueHandler queueHandler = Fawe.get().getQueueHandler();
|
||||||
|
Runnable[] finalSyncTasks = syncTasks;
|
||||||
|
|
||||||
|
// Chain the sync tasks and the callback
|
||||||
|
Callable<Future> chain = new Callable<Future>() {
|
||||||
|
@Override
|
||||||
|
public Future call() {
|
||||||
|
// Run the sync tasks
|
||||||
|
for (int i = 1; i < finalSyncTasks.length; i++) {
|
||||||
|
Runnable task = finalSyncTasks[i];
|
||||||
|
if (task != null) {
|
||||||
|
task.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return queueHandler.async(callback, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (T) queueHandler.sync(chain);
|
||||||
|
} else {
|
||||||
|
callback.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
|
|
||||||
- getBlocks
|
|
||||||
- set ChunkSection lock with a tracking lock
|
|
||||||
- synchronize on chunk object (so no other FAWE thread updates it at the same time)
|
|
||||||
- verify cached section is same object as NMS chunk section
|
|
||||||
otherwise, fetch the new section, set the tracking lock and reconstruct the getBlocks array
|
|
||||||
- Merge raw getBlocks and setBlocks array
|
|
||||||
- Construct the ChunkSection
|
|
||||||
- In parallel on the main thread
|
|
||||||
- if the tracking lock has had no updates and the cached ChunkSection == the NMS chunk section
|
|
||||||
- Otherwise, reconstruct the ChunkSection (TODO: Benchmark if this is a performance concern)
|
|
||||||
- swap in the new ChunkSection
|
|
||||||
- Update tile entities/entities (if necessary)
|
|
||||||
- Merge the biome array (if necessary)
|
|
||||||
- set chunk status to needs relighting
|
|
||||||
- mark as dirty
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// throw new UnsupportedOperationException("Not implemented");
|
|
||||||
// return true;
|
|
||||||
return null;
|
return null;
|
||||||
// return (T) (Future) Futures.immediateFuture(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +53,7 @@ public class BukkitGetBlocks extends CharGetBlocks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] load(int layer, char[] data) {
|
public synchronized char[] load(int layer, char[] data) {
|
||||||
ChunkSection section = getSections()[layer];
|
ChunkSection section = getSections()[layer];
|
||||||
// Section is null, return empty array
|
// Section is null, return empty array
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
@ -126,6 +126,9 @@ public class BukkitGetBlocks extends CharGetBlocks {
|
|||||||
for (int i = 0; i < 4096; i++) {
|
for (int i = 0; i < 4096; i++) {
|
||||||
char paletteVal = data[i];
|
char paletteVal = data[i];
|
||||||
data[i] = paletteToBlockChars[paletteVal];
|
data[i] = paletteToBlockChars[paletteVal];
|
||||||
|
if (data[i] == Character.MAX_VALUE) {
|
||||||
|
System.out.println("Invalid " + paletteVal + " | " + num_palette);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
for (int i = 0; i < num_palette; i++) {
|
for (int i = 0; i < num_palette; i++) {
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package com.boydti.fawe.beta;
|
package com.boydti.fawe.beta;
|
||||||
|
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for setting blocks
|
* Interface for setting blocks
|
||||||
*/
|
*/
|
||||||
@ -13,6 +17,12 @@ public interface ISetBlocks extends IBlocks {
|
|||||||
|
|
||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
|
|
||||||
|
void setTile(int x, int y, int z, CompoundTag tile);
|
||||||
|
|
||||||
|
void setEntity(CompoundTag tag);
|
||||||
|
|
||||||
|
void removeEntity(UUID uuid);
|
||||||
|
|
||||||
default void optimize() {
|
default void optimize() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,13 @@ import java.util.HashMap;
|
|||||||
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.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.ForkJoinTask;
|
import java.util.concurrent.ForkJoinTask;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,7 +36,7 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
private ForkJoinPool forkJoinPoolPrimary = new ForkJoinPool();
|
private ForkJoinPool forkJoinPoolPrimary = new ForkJoinPool();
|
||||||
private ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool();
|
private ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool();
|
||||||
private ThreadPoolExecutor blockingExecutor = FaweCache.newBlockingExecutor();
|
private ThreadPoolExecutor blockingExecutor = FaweCache.newBlockingExecutor();
|
||||||
private ConcurrentLinkedQueue<Runnable> syncTasks = new ConcurrentLinkedQueue();
|
private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue();
|
||||||
|
|
||||||
private Map<World, WeakReference<WorldChunkCache>> chunkCache = new HashMap<>();
|
private Map<World, WeakReference<WorldChunkCache>> chunkCache = new HashMap<>();
|
||||||
private IterableThreadLocal<IQueueExtent> queuePool = new IterableThreadLocal<IQueueExtent>() {
|
private IterableThreadLocal<IQueueExtent> queuePool = new IterableThreadLocal<IQueueExtent>() {
|
||||||
@ -44,6 +46,32 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public <T> Future<T> async(Runnable run, T value) {
|
||||||
|
return forkJoinPoolSecondary.submit(run, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Future<T> async(Callable<T> call) {
|
||||||
|
return forkJoinPoolSecondary.submit(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Future<T> sync(Runnable run, T value) {
|
||||||
|
FutureTask<T> result = new FutureTask<>(run, value);
|
||||||
|
syncTasks.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Future<T> sync(Runnable run) {
|
||||||
|
FutureTask<T> result = new FutureTask<>(run, null);
|
||||||
|
syncTasks.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Future<T> sync(Callable<T> call) {
|
||||||
|
FutureTask<T> result = new FutureTask<>(call);
|
||||||
|
syncTasks.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public <T extends Future<T>> T submit(IChunk<T> chunk) {
|
public <T extends Future<T>> T submit(IChunk<T> chunk) {
|
||||||
if (MemUtil.isMemoryFree()) {
|
if (MemUtil.isMemoryFree()) {
|
||||||
// return (T) forkJoinPoolSecondary.submit(chunk);
|
// return (T) forkJoinPoolSecondary.submit(chunk);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.boydti.fawe.beta.implementation.blocks;
|
package com.boydti.fawe.beta.implementation.blocks;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.ISetBlocks;
|
import com.boydti.fawe.beta.ISetBlocks;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
@ -10,10 +11,10 @@ import java.util.HashSet;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
||||||
private BiomeType[] biomes;
|
public BiomeType[] biomes;
|
||||||
private HashMap<Short, CompoundTag> tiles;
|
public HashMap<Short, CompoundTag> tiles;
|
||||||
private HashSet<CompoundTag> entities;
|
public HashSet<CompoundTag> entities;
|
||||||
private HashSet<UUID> entityRemoves;
|
public HashSet<UUID> entityRemoves;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||||
@ -30,6 +31,31 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTile(int x, int y, int z, CompoundTag tile) {
|
||||||
|
if (tiles == null) {
|
||||||
|
tiles = new HashMap<>();
|
||||||
|
}
|
||||||
|
short pair = MathMan.tripleBlockCoord(x, y, z);
|
||||||
|
tiles.put(pair, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEntity(CompoundTag tag) {
|
||||||
|
if (entities == null) {
|
||||||
|
entities = new HashSet<>();
|
||||||
|
}
|
||||||
|
entities.add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeEntity(UUID uuid) {
|
||||||
|
if (entityRemoves == null) {
|
||||||
|
entityRemoves = new HashSet<>();
|
||||||
|
}
|
||||||
|
entityRemoves.add(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
if (biomes != null) return false;
|
if (biomes != null) return false;
|
||||||
@ -44,6 +70,9 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks {
|
|||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
biomes = null;
|
biomes = null;
|
||||||
|
tiles = null;
|
||||||
|
entities = null;
|
||||||
|
entityRemoves = null;
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -302,9 +302,11 @@ public class RegionCommands extends MethodCommands {
|
|||||||
for (BlockVector3 p : region) {
|
for (BlockVector3 p : region) {
|
||||||
queue.setBlock(p.getX(), p.getY(), p.getZ(), block);
|
queue.setBlock(p.getX(), p.getY(), p.getZ(), block);
|
||||||
}
|
}
|
||||||
|
long start2 = System.currentTimeMillis();
|
||||||
queue.flush();
|
queue.flush();
|
||||||
long diff = System.currentTimeMillis() - start;
|
long diff = System.currentTimeMillis() - start;
|
||||||
System.out.println(diff);
|
long diff2 = System.currentTimeMillis() - start2;
|
||||||
|
System.out.println(diff + " | " + diff2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren