mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
Re-implement full Entity support in history, entity removal, entity creation, etc. (#1812)
Co-authored-by: Alexander Brandes <mc.cache@web.de>
This commit is contained in:
parent
d62c88a2ca
commit
968799503f
@ -14,7 +14,6 @@ import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
|
|||||||
import com.fastasyncworldedit.core.util.MathMan;
|
import com.fastasyncworldedit.core.util.MathMan;
|
||||||
import com.fastasyncworldedit.core.util.collection.AdaptedMap;
|
import com.fastasyncworldedit.core.util.collection.AdaptedMap;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -64,9 +63,9 @@ import javax.annotation.Nonnull;
|
|||||||
import java.util.AbstractSet;
|
import java.util.AbstractSet;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -79,7 +78,6 @@ import java.util.concurrent.locks.ReadWriteLock;
|
|||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
|
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
|
||||||
|
|
||||||
@ -324,21 +322,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
Entity entity = serverLevel.getEntity(uuid);
|
Entity entity = serverLevel.getEntity(uuid);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||||
}
|
}
|
||||||
for (List<Entity> entry : /*getChunk().getEntitySlices()*/ new List[0]) {
|
for (CompoundTag tag : getEntities()) {
|
||||||
if (entry != null) {
|
if (uuid.equals(tag.getUUID())) {
|
||||||
for (Entity ent : entry) {
|
return tag;
|
||||||
if (uuid.equals(ent.getUUID())) {
|
|
||||||
org.bukkit.entity.Entity bukkitEnt = ent.getBukkitEntity();
|
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -346,21 +338,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<CompoundTag> getEntities() {
|
public Set<CompoundTag> getEntities() {
|
||||||
List<Entity>[] slices = /*getChunk().getEntitySlices()*/ new List[0];
|
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||||
int size = 0;
|
if (entities.isEmpty()) {
|
||||||
for (List<Entity> slice : slices) {
|
|
||||||
if (slice != null) {
|
|
||||||
size += slice.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slices.length == 0) {
|
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
int finalSize = size;
|
int size = entities.size();
|
||||||
return new AbstractSet<CompoundTag>() {
|
return new AbstractSet<>() {
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return finalSize;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -373,17 +359,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (!(get instanceof CompoundTag getTag)) {
|
if (!(get instanceof CompoundTag getTag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Map<String, Tag> value = getTag.getValue();
|
UUID getUUID = getTag.getUUID();
|
||||||
CompoundTag getParts = (CompoundTag) value.get("UUID");
|
for (Entity entity : entities) {
|
||||||
UUID getUUID = new UUID(getParts.getLong("Most"), getParts.getLong("Least"));
|
UUID uuid = entity.getUUID();
|
||||||
for (List<Entity> slice : slices) {
|
if (uuid.equals(getUUID)) {
|
||||||
if (slice != null) {
|
return true;
|
||||||
for (Entity entity : slice) {
|
|
||||||
UUID uuid = entity.getUUID();
|
|
||||||
if (uuid.equals(getUUID)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -392,9 +372,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Iterator<CompoundTag> iterator() {
|
public Iterator<CompoundTag> iterator() {
|
||||||
Iterable<CompoundTag> result = StreamSupport.stream(Iterables.concat(slices).spliterator(), false).map(input -> {
|
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
return (CompoundTag) adapter.toNative(input.saveWithoutId(tag));
|
input.save(tag);
|
||||||
|
return (CompoundTag) adapter.toNative(tag);
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return result.iterator();
|
return result.iterator();
|
||||||
}
|
}
|
||||||
@ -630,23 +611,31 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[2] = () -> {
|
syncTasks[2] = () -> {
|
||||||
final List<Entity>[] entities = /*nmsChunk.e()*/ new List[0];
|
Set<UUID> entitiesRemoved = new HashSet<>();
|
||||||
|
final List<Entity> entities = PaperweightPlatformAdapter.getEntities(nmsChunk);
|
||||||
|
|
||||||
for (final Collection<Entity> ents : entities) {
|
for (Entity entity : entities) {
|
||||||
if (!ents.isEmpty()) {
|
UUID uuid = entity.getUUID();
|
||||||
final Iterator<Entity> iter = ents.iterator();
|
if (entityRemoves.contains(uuid)) {
|
||||||
while (iter.hasNext()) {
|
if (createCopy) {
|
||||||
final Entity entity = iter.next();
|
copy.storeEntity(entity);
|
||||||
if (entityRemoves.contains(entity.getUUID())) {
|
}
|
||||||
if (createCopy) {
|
removeEntity(entity);
|
||||||
copy.storeEntity(entity);
|
entitiesRemoved.add(uuid);
|
||||||
}
|
entityRemoves.remove(uuid);
|
||||||
iter.remove();
|
}
|
||||||
removeEntity(entity);
|
}
|
||||||
}
|
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
|
||||||
|
for (UUID uuid : entityRemoves) {
|
||||||
|
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid);
|
||||||
|
if (entity != null) {
|
||||||
|
removeEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only save entities that were actually removed to history
|
||||||
|
set.getEntityRemoves().clear();
|
||||||
|
set.getEntityRemoves().addAll(entitiesRemoved);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,7 +646,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[1] = () -> {
|
syncTasks[1] = () -> {
|
||||||
for (final CompoundTag nativeTag : entities) {
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
@ -684,12 +675,23 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
entity.load(tag);
|
entity.load(tag);
|
||||||
entity.absMoveTo(x, y, z, yaw, pitch);
|
entity.absMoveTo(x, y, z, yaw, pitch);
|
||||||
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
entity.setUUID(nativeTag.getUUID());
|
||||||
|
if (!nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
|
||||||
|
id,
|
||||||
|
nmsWorld.getWorld().getName(),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z
|
||||||
|
);
|
||||||
|
// Unsuccessful create should not be saved to history
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set tiles
|
// set tiles
|
||||||
|
@ -74,7 +74,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
protected void storeEntity(Entity entity) {
|
protected void storeEntity(Entity entity) {
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||||
entities.add((CompoundTag) adapter.toNative(entity.save(compoundTag)));
|
entity.save(compoundTag);
|
||||||
|
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,18 +86,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
@Override
|
@Override
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
for (CompoundTag tag : entities) {
|
for (CompoundTag tag : entities) {
|
||||||
UUID tagUUID;
|
if (uuid.equals(tag.getUUID())) {
|
||||||
if (tag.containsKey("UUID")) {
|
|
||||||
int[] arr = tag.getIntArray("UUID");
|
|
||||||
tagUUID = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
|
||||||
} else if (tag.containsKey("UUIDMost")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
|
|
||||||
} else if (tag.containsKey("PersistentIDMSB")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (uuid.equals(tagUUID)) {
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import net.minecraft.server.level.ChunkMap;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.util.BitStorage;
|
import net.minecraft.util.BitStorage;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
@ -53,6 +54,7 @@ import java.lang.invoke.MethodHandles;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -470,4 +472,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<Entity> getEntities(LevelChunk chunk) {
|
||||||
|
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -315,21 +316,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
Entity entity = serverLevel.getEntity(uuid);
|
Entity entity = serverLevel.getEntity(uuid);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||||
}
|
}
|
||||||
for (List<Entity> entry : /*getChunk().getEntitySlices()*/ new List[0]) {
|
for (CompoundTag tag : getEntities()) {
|
||||||
if (entry != null) {
|
if (uuid.equals(tag.getUUID())) {
|
||||||
for (Entity ent : entry) {
|
return tag;
|
||||||
if (uuid.equals(ent.getUUID())) {
|
|
||||||
org.bukkit.entity.Entity bukkitEnt = ent.getBukkitEntity();
|
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -337,21 +332,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<CompoundTag> getEntities() {
|
public Set<CompoundTag> getEntities() {
|
||||||
List<Entity>[] slices = /*getChunk().getEntitySlices()*/ new List[0];
|
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||||
int size = 0;
|
if (entities.isEmpty()) {
|
||||||
for (List<Entity> slice : slices) {
|
|
||||||
if (slice != null) {
|
|
||||||
size += slice.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slices.length == 0) {
|
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
int finalSize = size;
|
int size = entities.size();
|
||||||
return new AbstractSet<CompoundTag>() {
|
return new AbstractSet<>() {
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return finalSize;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -364,17 +353,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (!(get instanceof CompoundTag getTag)) {
|
if (!(get instanceof CompoundTag getTag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Map<String, Tag> value = getTag.getValue();
|
UUID getUUID = getTag.getUUID();
|
||||||
CompoundTag getParts = (CompoundTag) value.get("UUID");
|
for (Entity entity : entities) {
|
||||||
UUID getUUID = new UUID(getParts.getLong("Most"), getParts.getLong("Least"));
|
UUID uuid = entity.getUUID();
|
||||||
for (List<Entity> slice : slices) {
|
if (uuid.equals(getUUID)) {
|
||||||
if (slice != null) {
|
return true;
|
||||||
for (Entity entity : slice) {
|
|
||||||
UUID uuid = entity.getUUID();
|
|
||||||
if (uuid.equals(getUUID)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -383,9 +366,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Iterator<CompoundTag> iterator() {
|
public Iterator<CompoundTag> iterator() {
|
||||||
Iterable<CompoundTag> result = StreamSupport.stream(Iterables.concat(slices).spliterator(), false).map(input -> {
|
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
return (CompoundTag) adapter.toNative(input.saveWithoutId(tag));
|
input.save(tag);
|
||||||
|
return (CompoundTag) adapter.toNative(tag);
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return result.iterator();
|
return result.iterator();
|
||||||
}
|
}
|
||||||
@ -677,23 +661,31 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[2] = () -> {
|
syncTasks[2] = () -> {
|
||||||
final List<Entity>[] entities = /*nmsChunk.e()*/ new List[0];
|
Set<UUID> entitiesRemoved = new HashSet<>();
|
||||||
|
final List<Entity> entities = PaperweightPlatformAdapter.getEntities(nmsChunk);
|
||||||
|
|
||||||
for (final Collection<Entity> ents : entities) {
|
for (Entity entity : entities) {
|
||||||
if (!ents.isEmpty()) {
|
UUID uuid = entity.getUUID();
|
||||||
final Iterator<Entity> iter = ents.iterator();
|
if (entityRemoves.contains(uuid)) {
|
||||||
while (iter.hasNext()) {
|
if (createCopy) {
|
||||||
final Entity entity = iter.next();
|
copy.storeEntity(entity);
|
||||||
if (entityRemoves.contains(entity.getUUID())) {
|
}
|
||||||
if (createCopy) {
|
removeEntity(entity);
|
||||||
copy.storeEntity(entity);
|
entitiesRemoved.add(uuid);
|
||||||
}
|
entityRemoves.remove(uuid);
|
||||||
iter.remove();
|
}
|
||||||
removeEntity(entity);
|
}
|
||||||
}
|
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
|
||||||
|
for (UUID uuid : entityRemoves) {
|
||||||
|
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid);
|
||||||
|
if (entity != null) {
|
||||||
|
removeEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only save entities that were actually removed to history
|
||||||
|
set.getEntityRemoves().clear();
|
||||||
|
set.getEntityRemoves().addAll(entitiesRemoved);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +696,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[1] = () -> {
|
syncTasks[1] = () -> {
|
||||||
for (final CompoundTag nativeTag : entities) {
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
@ -731,12 +725,23 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
entity.load(tag);
|
entity.load(tag);
|
||||||
entity.absMoveTo(x, y, z, yaw, pitch);
|
entity.absMoveTo(x, y, z, yaw, pitch);
|
||||||
nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
entity.setUUID(nativeTag.getUUID());
|
||||||
|
if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
|
||||||
|
id,
|
||||||
|
nmsWorld.getWorld().getName(),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z
|
||||||
|
);
|
||||||
|
// Unsuccessful create should not be saved to history
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set tiles
|
// set tiles
|
||||||
|
@ -76,7 +76,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
protected void storeEntity(Entity entity) {
|
protected void storeEntity(Entity entity) {
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||||
entities.add((CompoundTag) adapter.toNative(entity.save(compoundTag)));
|
entity.save(compoundTag);
|
||||||
|
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,18 +88,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
@Override
|
@Override
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
for (CompoundTag tag : entities) {
|
for (CompoundTag tag : entities) {
|
||||||
UUID tagUUID;
|
if (uuid.equals(tag.getUUID())) {
|
||||||
if (tag.containsKey("UUID")) {
|
|
||||||
int[] arr = tag.getIntArray("UUID");
|
|
||||||
tagUUID = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
|
||||||
} else if (tag.containsKey("UUIDMost")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
|
|
||||||
} else if (tag.containsKey("PersistentIDMSB")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (uuid.equals(tagUUID)) {
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import net.minecraft.util.BitStorage;
|
|||||||
import net.minecraft.util.SimpleBitStorage;
|
import net.minecraft.util.SimpleBitStorage;
|
||||||
import net.minecraft.util.ThreadingDetector;
|
import net.minecraft.util.ThreadingDetector;
|
||||||
import net.minecraft.util.ZeroBitStorage;
|
import net.minecraft.util.ZeroBitStorage;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
@ -599,6 +600,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<Entity> getEntities(LevelChunk chunk) {
|
||||||
|
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ));
|
||||||
|
}
|
||||||
|
|
||||||
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
|
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,9 +67,9 @@ import javax.annotation.Nonnull;
|
|||||||
import java.util.AbstractSet;
|
import java.util.AbstractSet;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -316,21 +316,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
Entity entity = serverLevel.getEntity(uuid);
|
Entity entity = serverLevel.getEntity(uuid);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
||||||
}
|
}
|
||||||
for (List<Entity> entry : /*getChunk().getEntitySlices()*/ new List[0]) {
|
for (CompoundTag tag : getEntities()) {
|
||||||
if (entry != null) {
|
if (uuid.equals(tag.getUUID())) {
|
||||||
for (Entity ent : entry) {
|
return tag;
|
||||||
if (uuid.equals(ent.getUUID())) {
|
|
||||||
org.bukkit.entity.Entity bukkitEnt = ent.getBukkitEntity();
|
|
||||||
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -338,21 +332,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<CompoundTag> getEntities() {
|
public Set<CompoundTag> getEntities() {
|
||||||
List<Entity>[] slices = /*getChunk().getEntitySlices()*/ new List[0];
|
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
|
||||||
int size = 0;
|
if (entities.isEmpty()) {
|
||||||
for (List<Entity> slice : slices) {
|
|
||||||
if (slice != null) {
|
|
||||||
size += slice.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (slices.length == 0) {
|
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
int finalSize = size;
|
int size = entities.size();
|
||||||
return new AbstractSet<CompoundTag>() {
|
return new AbstractSet<>() {
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return finalSize;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -365,17 +353,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
if (!(get instanceof CompoundTag getTag)) {
|
if (!(get instanceof CompoundTag getTag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Map<String, Tag> value = getTag.getValue();
|
UUID getUUID = getTag.getUUID();
|
||||||
CompoundTag getParts = (CompoundTag) value.get("UUID");
|
for (Entity entity : entities) {
|
||||||
UUID getUUID = new UUID(getParts.getLong("Most"), getParts.getLong("Least"));
|
UUID uuid = entity.getUUID();
|
||||||
for (List<Entity> slice : slices) {
|
if (uuid.equals(getUUID)) {
|
||||||
if (slice != null) {
|
return true;
|
||||||
for (Entity entity : slice) {
|
|
||||||
UUID uuid = entity.getUUID();
|
|
||||||
if (uuid.equals(getUUID)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -384,9 +366,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Iterator<CompoundTag> iterator() {
|
public Iterator<CompoundTag> iterator() {
|
||||||
Iterable<CompoundTag> result = StreamSupport.stream(Iterables.concat(slices).spliterator(), false).map(input -> {
|
Iterable<CompoundTag> result = entities.stream().map(input -> {
|
||||||
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag();
|
||||||
return (CompoundTag) adapter.toNative(input.saveWithoutId(tag));
|
input.save(tag);
|
||||||
|
return (CompoundTag) adapter.toNative(tag);
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
return result.iterator();
|
return result.iterator();
|
||||||
}
|
}
|
||||||
@ -677,23 +660,31 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[2] = () -> {
|
syncTasks[2] = () -> {
|
||||||
final List<Entity>[] entities = /*nmsChunk.e()*/ new List[0];
|
Set<UUID> entitiesRemoved = new HashSet<>();
|
||||||
|
final List<Entity> entities = PaperweightPlatformAdapter.getEntities(nmsChunk);
|
||||||
|
|
||||||
for (final Collection<Entity> ents : entities) {
|
for (Entity entity : entities) {
|
||||||
if (!ents.isEmpty()) {
|
UUID uuid = entity.getUUID();
|
||||||
final Iterator<Entity> iter = ents.iterator();
|
if (entityRemoves.contains(uuid)) {
|
||||||
while (iter.hasNext()) {
|
if (createCopy) {
|
||||||
final Entity entity = iter.next();
|
copy.storeEntity(entity);
|
||||||
if (entityRemoves.contains(entity.getUUID())) {
|
}
|
||||||
if (createCopy) {
|
removeEntity(entity);
|
||||||
copy.storeEntity(entity);
|
entitiesRemoved.add(uuid);
|
||||||
}
|
entityRemoves.remove(uuid);
|
||||||
iter.remove();
|
}
|
||||||
removeEntity(entity);
|
}
|
||||||
}
|
if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) {
|
||||||
|
for (UUID uuid : entityRemoves) {
|
||||||
|
Entity entity = nmsWorld.entityManager.getEntityGetter().get(uuid);
|
||||||
|
if (entity != null) {
|
||||||
|
removeEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only save entities that were actually removed to history
|
||||||
|
set.getEntityRemoves().clear();
|
||||||
|
set.getEntityRemoves().addAll(entitiesRemoved);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +695,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncTasks[1] = () -> {
|
syncTasks[1] = () -> {
|
||||||
for (final CompoundTag nativeTag : entities) {
|
Iterator<CompoundTag> iterator = entities.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final CompoundTag nativeTag = iterator.next();
|
||||||
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
final Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
@ -731,12 +724,23 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
|
|||||||
}
|
}
|
||||||
entity.load(tag);
|
entity.load(tag);
|
||||||
entity.absMoveTo(x, y, z, yaw, pitch);
|
entity.absMoveTo(x, y, z, yaw, pitch);
|
||||||
nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
entity.setUUID(nativeTag.getUUID());
|
||||||
|
if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Error creating entity of type `{}` in world `{}` at location `{},{},{}`",
|
||||||
|
id,
|
||||||
|
nmsWorld.getWorld().getName(),
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z
|
||||||
|
);
|
||||||
|
// Unsuccessful create should not be saved to history
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set tiles
|
// set tiles
|
||||||
|
@ -80,7 +80,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
protected void storeEntity(Entity entity) {
|
protected void storeEntity(Entity entity) {
|
||||||
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag();
|
||||||
entities.add((CompoundTag) adapter.toNative(entity.save(compoundTag)));
|
entity.save(compoundTag);
|
||||||
|
entities.add((CompoundTag) adapter.toNative(compoundTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,18 +92,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
|
|||||||
@Override
|
@Override
|
||||||
public CompoundTag getEntity(UUID uuid) {
|
public CompoundTag getEntity(UUID uuid) {
|
||||||
for (CompoundTag tag : entities) {
|
for (CompoundTag tag : entities) {
|
||||||
UUID tagUUID;
|
if (uuid.equals(tag.getUUID())) {
|
||||||
if (tag.containsKey("UUID")) {
|
|
||||||
int[] arr = tag.getIntArray("UUID");
|
|
||||||
tagUUID = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
|
||||||
} else if (tag.containsKey("UUIDMost")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
|
|
||||||
} else if (tag.containsKey("PersistentIDMSB")) {
|
|
||||||
tagUUID = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (uuid.equals(tagUUID)) {
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import net.minecraft.util.BitStorage;
|
|||||||
import net.minecraft.util.SimpleBitStorage;
|
import net.minecraft.util.SimpleBitStorage;
|
||||||
import net.minecraft.util.ThreadingDetector;
|
import net.minecraft.util.ThreadingDetector;
|
||||||
import net.minecraft.util.ZeroBitStorage;
|
import net.minecraft.util.ZeroBitStorage;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.biome.Biome;
|
import net.minecraft.world.level.biome.Biome;
|
||||||
@ -599,6 +600,10 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<Entity> getEntities(LevelChunk chunk) {
|
||||||
|
return chunk.level.entityManager.getEntities(new ChunkPos(chunk.locX, chunk.locZ));
|
||||||
|
}
|
||||||
|
|
||||||
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
|
record FakeIdMapBlock(int size) implements IdMap<net.minecraft.world.level.block.state.BlockState> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Binary file not shown.
@ -56,6 +56,7 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld {
|
public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld {
|
||||||
|
|
||||||
@ -167,6 +168,15 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld
|
|||||||
return clipboard.createEntity(location, entity);
|
return clipboard.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
dirty = true;
|
||||||
|
return clipboard.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
return clipboard.getBlock(position);
|
return clipboard.getBlock(position);
|
||||||
|
@ -621,6 +621,15 @@ public class Settings extends Config {
|
|||||||
})
|
})
|
||||||
public boolean KEEP_ENTITIES_IN_BLOCKS = false;
|
public boolean KEEP_ENTITIES_IN_BLOCKS = false;
|
||||||
|
|
||||||
|
@Comment({
|
||||||
|
"[SAFE] Attempt to remove entities from the world if they were not present in the expected chunk (default: true)",
|
||||||
|
" - Sometimes an entity may have moved into a different chunk to that which FAWE expected",
|
||||||
|
" - This option allows FAWE to attempt to remove the entity, even if present in a different chunk",
|
||||||
|
" - If the entity is in an unloaded or partially loaded chunk, this will fail",
|
||||||
|
" - If an entity cannot be removed, it is possible duplicate entities may be created when using undo and/or redo"
|
||||||
|
})
|
||||||
|
public boolean REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL = true;
|
||||||
|
|
||||||
@Comment({
|
@Comment({
|
||||||
"Other experimental features"
|
"Other experimental features"
|
||||||
})
|
})
|
||||||
|
@ -22,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class FaweRegionExtent extends ResettableExtent implements IBatchProcessor {
|
public abstract class FaweRegionExtent extends ResettableExtent implements IBatchProcessor {
|
||||||
|
|
||||||
@ -149,6 +150,18 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
|||||||
return super.createEntity(location, entity);
|
return super.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
if (!contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())) {
|
||||||
|
if (!limit.MAX_FAILS()) {
|
||||||
|
WEManager.weManager().cancelEditSafe(this, FaweCache.OUTSIDE_REGION);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return super.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProcessorScope getScope() {
|
public ProcessorScope getScope() {
|
||||||
return ProcessorScope.READING_SET_BLOCKS;
|
return ProcessorScope.READING_SET_BLOCKS;
|
||||||
|
@ -18,6 +18,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -78,6 +79,16 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity state, UUID uuid) {
|
||||||
|
final Entity entity = super.createEntity(location, state, uuid);
|
||||||
|
if (state != null) {
|
||||||
|
this.changeSet.addEntityCreate(state.getNbtData());
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Entity> getEntities() {
|
public List<? extends Entity> getEntities() {
|
||||||
return this.wrapEntities(super.getEntities());
|
return this.wrapEntities(super.getEntities());
|
||||||
|
@ -90,6 +90,21 @@ public class LimitExtent extends AbstractDelegateExtent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
limit.THROW_MAX_CHANGES();
|
||||||
|
limit.THROW_MAX_ENTITIES();
|
||||||
|
try {
|
||||||
|
return super.createEntity(location, entity, uuid);
|
||||||
|
} catch (FaweException e) {
|
||||||
|
if (!limit.MAX_FAILS()) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEntity(int x, int y, int z, UUID uuid) {
|
public void removeEntity(int x, int y, int z, UUID uuid) {
|
||||||
limit.THROW_MAX_CHANGES();
|
limit.THROW_MAX_CHANGES();
|
||||||
|
@ -36,6 +36,7 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
//todo This should be removed in favor of com.sk89q.worldedit.extent.NullExtent
|
//todo This should be removed in favor of com.sk89q.worldedit.extent.NullExtent
|
||||||
@ -87,6 +88,12 @@ public class NullExtent extends FaweRegionExtent implements IBatchProcessor {
|
|||||||
throw reason;
|
throw reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location arg0, BaseEntity arg1, UUID arg2) {
|
||||||
|
throw reason;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
throw reason;
|
throw reason;
|
||||||
|
@ -16,6 +16,8 @@ import com.sk89q.worldedit.world.block.BlockState;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ProcessedWEExtent extends AbstractDelegateExtent {
|
public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||||
|
|
||||||
private final FaweLimit limit;
|
private final FaweLimit limit;
|
||||||
@ -43,6 +45,18 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
|
|||||||
return super.createEntity(location, entity);
|
return super.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!limit.MAX_ENTITIES()) {
|
||||||
|
WEManager.weManager().cancelEditSafe(this, FaweCache.MAX_ENTITIES);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return super.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(int x, int y, int z) {
|
public BlockState getBlock(int x, int y, int z) {
|
||||||
if (!limit.MAX_CHECKS()) {
|
if (!limit.MAX_CHECKS()) {
|
||||||
|
@ -28,6 +28,7 @@ import java.util.Iterator;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -65,6 +66,12 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
|||||||
return super.createEntity(location, stripEntityNBT(entity));
|
return super.createEntity(location, stripEntityNBT(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return super.createEntity(location, stripEntityNBT(entity), uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <B extends BlockStateHolder<B>> B stripBlockNBT(B block) {
|
public <B extends BlockStateHolder<B>> B stripBlockNBT(B block) {
|
||||||
if (!(block instanceof BaseBlock localBlock)) {
|
if (!(block instanceof BaseBlock localBlock)) {
|
||||||
|
@ -5,23 +5,16 @@ import com.fastasyncworldedit.core.math.IntTriple;
|
|||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
import com.sk89q.jnbt.IntTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class CPUOptimizedClipboard extends LinearClipboard {
|
public class CPUOptimizedClipboard extends LinearClipboard {
|
||||||
@ -209,22 +202,4 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Entity createEntity(Location location, BaseEntity entity) {
|
|
||||||
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
|
||||||
entities.add(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends Entity> getEntities() {
|
|
||||||
return new ArrayList<>(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeEntity(Entity entity) {
|
|
||||||
this.entities.remove(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,10 @@ import com.sk89q.jnbt.NBTInputStream;
|
|||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -30,7 +28,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -48,7 +45,6 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A clipboard with disk backed storage. (lower memory + loads on crash)
|
* A clipboard with disk backed storage. (lower memory + loads on crash)
|
||||||
@ -714,47 +710,4 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Entity createEntity(Location location, BaseEntity entity) {
|
|
||||||
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
|
||||||
entities.add(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends Entity> getEntities() {
|
|
||||||
return new ArrayList<>(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends Entity> getEntities(Region region) {
|
|
||||||
return entities
|
|
||||||
.stream()
|
|
||||||
.filter(e -> region.contains(e.getLocation().toBlockPoint())).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeEntity(Entity entity) {
|
|
||||||
if (!(entity instanceof BlockArrayClipboard.ClipboardEntity)) {
|
|
||||||
Location loc = entity.getLocation();
|
|
||||||
removeEntity(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), entity.getState().getNbtData().getUUID());
|
|
||||||
} else {
|
|
||||||
this.entities.remove(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeEntity(int x, int y, int z, UUID uuid) {
|
|
||||||
Iterator<BlockArrayClipboard.ClipboardEntity> iter = this.entities.iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
BlockArrayClipboard.ClipboardEntity entity = iter.next();
|
|
||||||
UUID entUUID = entity.getState().getNbtData().getUUID();
|
|
||||||
if (uuid.equals(entUUID)) {
|
|
||||||
iter.remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,33 @@ import com.fastasyncworldedit.core.function.visitor.Order;
|
|||||||
import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader;
|
import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader;
|
||||||
import com.google.common.collect.ForwardingIterator;
|
import com.google.common.collect.ForwardingIterator;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.NBTUtils;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard.ClipboardEntity;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard.ClipboardEntity;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class LinearClipboard extends SimpleClipboard {
|
public abstract class LinearClipboard extends SimpleClipboard {
|
||||||
|
|
||||||
@ -83,6 +95,25 @@ public abstract class LinearClipboard extends SimpleClipboard {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity) {
|
||||||
|
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
||||||
|
entities.add(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
Map<String, Tag> map = new HashMap<>(entity.getNbtData().getValue());
|
||||||
|
NBTUtils.addUUIDToMap(map, uuid);
|
||||||
|
entity.setNbtData(new CompoundTag(map));
|
||||||
|
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
||||||
|
entities.add(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEntity(int x, int y, int z, UUID uuid) {
|
public void removeEntity(int x, int y, int z, UUID uuid) {
|
||||||
Iterator<ClipboardEntity> iter = this.entities.iterator();
|
Iterator<ClipboardEntity> iter = this.entities.iterator();
|
||||||
@ -96,6 +127,28 @@ public abstract class LinearClipboard extends SimpleClipboard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities() {
|
||||||
|
return new ArrayList<>(entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeEntity(Entity entity) {
|
||||||
|
if (!(entity instanceof BlockArrayClipboard.ClipboardEntity)) {
|
||||||
|
Location loc = entity.getLocation();
|
||||||
|
removeEntity(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), entity.getState().getNbtData().getUUID());
|
||||||
|
} else {
|
||||||
|
this.entities.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends Entity> getEntities(Region region) {
|
||||||
|
return entities
|
||||||
|
.stream()
|
||||||
|
.filter(e -> region.contains(e.getLocation().toBlockPoint())).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
private class LinearFilter extends AbstractFilterBlock {
|
private class LinearFilter extends AbstractFilterBlock {
|
||||||
|
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
@ -7,13 +7,8 @@ import com.fastasyncworldedit.core.util.MainUtil;
|
|||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
import com.sk89q.jnbt.IntTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard.ClipboardEntity;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -22,14 +17,10 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class MemoryOptimizedClipboard extends LinearClipboard {
|
public class MemoryOptimizedClipboard extends LinearClipboard {
|
||||||
|
|
||||||
@ -293,31 +284,4 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Entity createEntity(Location location, BaseEntity entity) {
|
|
||||||
BlockArrayClipboard.ClipboardEntity ret = new BlockArrayClipboard.ClipboardEntity(location, entity);
|
|
||||||
entities.add(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends Entity> getEntities() {
|
|
||||||
return new ArrayList<>(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends Entity> getEntities(Region region) {
|
|
||||||
return entities
|
|
||||||
.stream()
|
|
||||||
.filter(e -> region.contains(e.getLocation().toBlockPoint())).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeEntity(Entity entity) {
|
|
||||||
if (entity instanceof ClipboardEntity) {
|
|
||||||
this.entities.remove(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,13 @@ package com.fastasyncworldedit.core.extent.clipboard;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.NBTUtils;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.session.request.Request;
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
@ -14,7 +17,11 @@ import com.sk89q.worldedit.world.World;
|
|||||||
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 javax.annotation.Nullable;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
||||||
@ -103,6 +110,12 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
|||||||
throw new UnsupportedOperationException("Clipboard is immutable");
|
throw new UnsupportedOperationException("Clipboard is immutable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
throw new UnsupportedOperationException("Clipboard is immutable");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEntity(Entity entity) {
|
public void removeEntity(Entity entity) {
|
||||||
throw new UnsupportedOperationException("Clipboard is immutable");
|
throw new UnsupportedOperationException("Clipboard is immutable");
|
||||||
|
@ -12,6 +12,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MultiTransform extends RandomTransform {
|
public class MultiTransform extends RandomTransform {
|
||||||
|
|
||||||
@ -90,4 +91,14 @@ public class MultiTransform extends RandomTransform {
|
|||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
Entity created = null;
|
||||||
|
for (AbstractDelegateExtent extent : extents) {
|
||||||
|
created = extent.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ScaleTransform extends ResettableExtent {
|
public class ScaleTransform extends ResettableExtent {
|
||||||
|
|
||||||
@ -181,4 +182,17 @@ public class ScaleTransform extends ResettableExtent {
|
|||||||
return super.createEntity(newLoc, entity);
|
return super.createEntity(newLoc, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
Location newLoc = new Location(location.getExtent(),
|
||||||
|
getPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()),
|
||||||
|
location.getYaw(), location.getPitch()
|
||||||
|
);
|
||||||
|
if (!getExtent().contains(newLoc.toBlockPoint())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return super.createEntity(newLoc, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class SelectTransform extends ResettableExtent {
|
public abstract class SelectTransform extends ResettableExtent {
|
||||||
|
|
||||||
@ -52,6 +53,13 @@ public abstract class SelectTransform extends ResettableExtent {
|
|||||||
.createEntity(position, entity);
|
.createEntity(position, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location position, BaseEntity entity, UUID uuid) {
|
||||||
|
return getExtent(position.getBlockX(), position.getBlockY(), position.getBlockZ())
|
||||||
|
.createEntity(position, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||||
return getExtent(position).setBiome(position, biome);
|
return getExtent(position).setBiome(position, biome);
|
||||||
|
@ -53,15 +53,8 @@ public class MutableEntityChange implements Change {
|
|||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public void delete(UndoContext context) {
|
public void delete(UndoContext context) {
|
||||||
Map<String, Tag> map = tag.getValue();
|
Map<String, Tag> map = tag.getValue();
|
||||||
long most;
|
UUID uuid = tag.getUUID();
|
||||||
long least;
|
if (uuid == null) {
|
||||||
if (map.containsKey("UUIDMost")) {
|
|
||||||
most = ((LongTag) map.get("UUIDMost")).getValue();
|
|
||||||
least = ((LongTag) map.get("UUIDLeast")).getValue();
|
|
||||||
} else if (map.containsKey("PersistentIDMSB")) {
|
|
||||||
most = ((LongTag) map.get("PersistentIDMSB")).getValue();
|
|
||||||
least = ((LongTag) map.get("PersistentIDLSB")).getValue();
|
|
||||||
} else {
|
|
||||||
LOGGER.info("Skipping entity without uuid.");
|
LOGGER.info("Skipping entity without uuid.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -69,7 +62,6 @@ public class MutableEntityChange implements Change {
|
|||||||
int x = MathMan.roundInt(pos.get(0).getValue());
|
int x = MathMan.roundInt(pos.get(0).getValue());
|
||||||
int y = MathMan.roundInt(pos.get(1).getValue());
|
int y = MathMan.roundInt(pos.get(1).getValue());
|
||||||
int z = MathMan.roundInt(pos.get(2).getValue());
|
int z = MathMan.roundInt(pos.get(2).getValue());
|
||||||
UUID uuid = new UUID(most, least);
|
|
||||||
context.getExtent().removeEntity(x, y, z, uuid);
|
context.getExtent().removeEntity(x, y, z, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +81,7 @@ public class MutableEntityChange implements Change {
|
|||||||
String id = tag.getString("Id");
|
String id = tag.getString("Id");
|
||||||
EntityType type = EntityTypes.parse(id);
|
EntityType type = EntityTypes.parse(id);
|
||||||
BaseEntity entity = new BaseEntity(type, tag);
|
BaseEntity entity = new BaseEntity(type, tag);
|
||||||
context.getExtent().createEntity(location, entity);
|
extent.createEntity(location, entity, tag.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.sk89q.jnbt.DoubleTag;
|
|||||||
import com.sk89q.jnbt.IntArrayTag;
|
import com.sk89q.jnbt.IntArrayTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.LongTag;
|
import com.sk89q.jnbt.LongTag;
|
||||||
|
import com.sk89q.jnbt.NBTUtils;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
@ -119,6 +120,11 @@ public interface IChunkExtent<T extends IChunk> extends Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default Entity createEntity(Location location, BaseEntity entity) {
|
default Entity createEntity(Location location, BaseEntity entity) {
|
||||||
|
return createEntity(location, entity, UUID.randomUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
final IChunk chunk = getOrCreateChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
final IChunk chunk = getOrCreateChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||||
Map<String, Tag> map = new HashMap<>(entity.getNbtData().getValue()); //do not modify original entity data
|
Map<String, Tag> map = new HashMap<>(entity.getNbtData().getValue()); //do not modify original entity data
|
||||||
map.put("Id", new StringTag(entity.getType().getName()));
|
map.put("Id", new StringTag(entity.getType().getName()));
|
||||||
@ -130,23 +136,10 @@ public interface IChunkExtent<T extends IChunk> extends Extent {
|
|||||||
posList.add(new DoubleTag(location.getZ()));
|
posList.add(new DoubleTag(location.getZ()));
|
||||||
map.put("Pos", new ListTag(DoubleTag.class, posList));
|
map.put("Pos", new ListTag(DoubleTag.class, posList));
|
||||||
|
|
||||||
//set new uuid
|
NBTUtils.addUUIDToMap(map, uuid);
|
||||||
UUID newuuid = UUID.randomUUID();
|
|
||||||
int[] uuidArray = new int[4];
|
|
||||||
uuidArray[0] = (int) (newuuid.getMostSignificantBits() >> 32);
|
|
||||||
uuidArray[1] = (int) newuuid.getMostSignificantBits();
|
|
||||||
uuidArray[2] = (int) (newuuid.getLeastSignificantBits() >> 32);
|
|
||||||
uuidArray[3] = (int) newuuid.getLeastSignificantBits();
|
|
||||||
map.put("UUID", new IntArrayTag(uuidArray));
|
|
||||||
|
|
||||||
map.put("UUIDMost", new LongTag(newuuid.getMostSignificantBits()));
|
|
||||||
map.put("UUIDLeast", new LongTag(newuuid.getLeastSignificantBits()));
|
|
||||||
|
|
||||||
map.put("PersistentIDMSB", new LongTag(newuuid.getMostSignificantBits()));
|
|
||||||
map.put("PersistentIDLSB", new LongTag(newuuid.getLeastSignificantBits()));
|
|
||||||
|
|
||||||
chunk.setEntity(new CompoundTag(map));
|
chunk.setEntity(new CompoundTag(map));
|
||||||
return new IChunkEntity(this, location, newuuid, entity);
|
return new IChunkEntity(this, location, uuid, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1056,14 +1056,17 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
IChunkGet get = getOrCreateGet();
|
IChunkGet get = getOrCreateGet();
|
||||||
boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor);
|
boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor);
|
||||||
get.setCreateCopy(postProcess);
|
get.setCreateCopy(postProcess);
|
||||||
set = getExtent().processSet(this, get, set);
|
final IChunkSet iChunkSet = getExtent().processSet(this, get, set);
|
||||||
try {
|
Runnable finalizer;
|
||||||
return get.call(set, finalize);
|
if (postProcess) {
|
||||||
} finally {
|
finalizer = () -> {
|
||||||
if (postProcess) {
|
getExtent().postProcess(this, get.getCopy(), iChunkSet);
|
||||||
getExtent().postProcess(this, get.getCopy(), set);
|
finalize.run();
|
||||||
}
|
};
|
||||||
|
} else {
|
||||||
|
finalizer = finalize;
|
||||||
}
|
}
|
||||||
|
return get.call(set, finalizer);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class WorldWrapper extends AbstractWorld {
|
public class WorldWrapper extends AbstractWorld {
|
||||||
|
|
||||||
@ -326,6 +327,12 @@ public class WorldWrapper extends AbstractWorld {
|
|||||||
return parent.createEntity(location, entity);
|
return parent.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return parent.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
return parent.getBlock(position);
|
return parent.getBlock(position);
|
||||||
|
@ -340,9 +340,20 @@ public class CompoundTag extends Tag {
|
|||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
long most = getLong("UUIDMost");
|
UUID uuid;
|
||||||
long least = getLong("UUIDLeast");
|
if (containsKey("UUID")) {
|
||||||
return new UUID(most, least);
|
int[] arr = getIntArray("UUID");
|
||||||
|
uuid = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
||||||
|
} else if (containsKey("UUIDMost")) {
|
||||||
|
uuid = new UUID(getLong("UUIDMost"), getLong("UUIDLeast"));
|
||||||
|
} else if (containsKey("WorldUUIDMost")) {
|
||||||
|
uuid = new UUID(getLong("WorldUUIDMost"), getLong("WorldUUIDLeast"));
|
||||||
|
} else if (containsKey("PersistentIDMSB")) {
|
||||||
|
uuid = new UUID(getLong("PersistentIDMSB"), getLong("PersistentIDLSB"));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 getEntityPosition() {
|
public Vector3 getEntityPosition() {
|
||||||
|
@ -24,6 +24,7 @@ import com.sk89q.worldedit.util.nbt.BinaryTagTypes;
|
|||||||
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
import com.sk89q.worldedit.world.storage.InvalidFormatException;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -170,4 +171,31 @@ public final class NBTUtils {
|
|||||||
return expected.cast(tag);
|
return expected.cast(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
/**
|
||||||
|
* Add a {@link UUID} to a map for use in a {@link CompoundTag}
|
||||||
|
*
|
||||||
|
* @param map Map to add uuid to
|
||||||
|
* @param uuid {@link UUID} to add
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public static void addUUIDToMap(Map<String, Tag> map, UUID uuid) {
|
||||||
|
int[] uuidArray = new int[4];
|
||||||
|
uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32);
|
||||||
|
uuidArray[1] = (int) uuid.getMostSignificantBits();
|
||||||
|
uuidArray[2] = (int) (uuid.getLeastSignificantBits() >> 32);
|
||||||
|
uuidArray[3] = (int) uuid.getLeastSignificantBits();
|
||||||
|
map.put("UUID", new IntArrayTag(uuidArray));
|
||||||
|
|
||||||
|
map.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
|
||||||
|
map.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
|
||||||
|
|
||||||
|
map.put("WorldUUIDMost", new LongTag(uuid.getMostSignificantBits()));
|
||||||
|
map.put("WorldUUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
|
||||||
|
|
||||||
|
map.put("PersistentIDMSB", new LongTag(uuid.getMostSignificantBits()));
|
||||||
|
map.put("PersistentIDLSB", new LongTag(uuid.getLeastSignificantBits()));
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3699,6 +3699,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
try {
|
||||||
|
return this.getExtent().createEntity(location, entity, uuid);
|
||||||
|
} catch (WorldEditException e) {
|
||||||
|
throw new RuntimeException("Unexpected exception", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEntity(int x, int y, int z, UUID uuid) {
|
public void removeEntity(int x, int y, int z, UUID uuid) {
|
||||||
try {
|
try {
|
||||||
|
@ -141,6 +141,14 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
return extent.createEntity(location, entity);
|
return extent.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return extent.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Operation commit() {
|
public Operation commit() {
|
||||||
|
@ -37,6 +37,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -78,11 +79,23 @@ public class ChangeSetExtent extends AbstractDelegateExtent {
|
|||||||
public Entity createEntity(Location location, BaseEntity state) {
|
public Entity createEntity(Location location, BaseEntity state) {
|
||||||
Entity entity = super.createEntity(location, state);
|
Entity entity = super.createEntity(location, state);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
changeSet.add(new EntityCreate(location, state, entity));
|
changeSet.add(new EntityCreate(location, entity.getState(), entity));
|
||||||
}
|
}
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity state, UUID uuid) {
|
||||||
|
Entity entity = super.createEntity(location, state, uuid);
|
||||||
|
if (entity != null) {
|
||||||
|
changeSet.add(new EntityCreate(location, entity.getState(), entity));
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends Entity> getEntities() {
|
public List<? extends Entity> getEntities() {
|
||||||
return wrapEntities(super.getEntities());
|
return wrapEntities(super.getEntities());
|
||||||
|
@ -148,6 +148,21 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
|
/**
|
||||||
|
* Create an entity at the given location, forcing a UUID onto the entity
|
||||||
|
*
|
||||||
|
* Only use if you are aware of the consequences of forcing a UUID to an entity.
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param location the location
|
||||||
|
* @param uuid UUID to force the entity to have
|
||||||
|
* @return a reference to the created entity, or null if the entity could not be created
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an entity at the given location.
|
* Create an entity at the given location.
|
||||||
|
@ -38,6 +38,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An extent that returns air blocks for all blocks and does not
|
* An extent that returns air blocks for all blocks and does not
|
||||||
@ -73,6 +74,14 @@ public class NullExtent implements Extent {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
return BlockTypes.AIR.getDefaultState();
|
return BlockTypes.AIR.getDefaultState();
|
||||||
|
@ -34,6 +34,7 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An extent that can report back if an operation fails due to the extent(s) below it.
|
* An extent that can report back if an operation fails due to the extent(s) below it.
|
||||||
@ -106,6 +107,20 @@ public class TracingExtent extends AbstractDelegateExtent {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
BlockVector3 blockVector3 = location.toVector().toBlockPoint();
|
||||||
|
touchedLocations.add(blockVector3);
|
||||||
|
Entity result = super.createEntity(location, entity, uuid);
|
||||||
|
if (result == null) {
|
||||||
|
failedActions.put(blockVector3, Action.CREATE_ENTITY);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TracingExtent{delegate=" + getExtent() + "}";
|
return "TracingExtent{delegate=" + getExtent() + "}";
|
||||||
|
@ -304,6 +304,18 @@ public class BlockArrayClipboard implements Clipboard {
|
|||||||
return getParent().createEntity(l, entity);
|
return getParent().createEntity(l, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
Location l = new Location(location.getExtent(),
|
||||||
|
location.getX() - offset.getBlockX(),
|
||||||
|
location.getY() - offset.getBlockY(),
|
||||||
|
location.getZ() - offset.getBlockZ(),
|
||||||
|
location.getYaw(), location.getPitch()
|
||||||
|
);
|
||||||
|
return getParent().createEntity(l, entity, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEntity(int x, int y, int z, UUID uuid) {
|
public void removeEntity(int x, int y, int z, UUID uuid) {
|
||||||
x -= offset.getX();
|
x -= offset.getX();
|
||||||
|
@ -31,6 +31,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extent that ticks the watchdog before every world-affecting action.
|
* Extent that ticks the watchdog before every world-affecting action.
|
||||||
@ -86,6 +87,15 @@ public class WatchdogTickingExtent extends AbstractDelegateExtent {
|
|||||||
return super.createEntity(location, entity);
|
return super.createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
onOperation();
|
||||||
|
return super.createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||||
onOperation();
|
onOperation();
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.function.entity;
|
package com.sk89q.worldedit.function.entity;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.CompoundTagBuilder;
|
import com.sk89q.jnbt.CompoundTagBuilder;
|
||||||
import com.sk89q.jnbt.FloatTag;
|
import com.sk89q.jnbt.FloatTag;
|
||||||
@ -165,6 +166,8 @@ public class ExtentEntityCopy implements EntityFunction {
|
|||||||
uuid = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
uuid = new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL));
|
||||||
} else if (tag.containsKey("UUIDMost")) {
|
} else if (tag.containsKey("UUIDMost")) {
|
||||||
uuid = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
|
uuid = new UUID(tag.getLong("UUIDMost"), tag.getLong("UUIDLeast"));
|
||||||
|
} else if (tag.containsKey("WorldUUIDMost")) {
|
||||||
|
uuid = new UUID(tag.getLong("WorldUUIDMost"), tag.getLong("WorldUUIDLeast"));
|
||||||
} else if (tag.containsKey("PersistentIDMSB")) {
|
} else if (tag.containsKey("PersistentIDMSB")) {
|
||||||
uuid = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
|
uuid = new UUID(tag.getLong("PersistentIDMSB"), tag.getLong("PersistentIDLSB"));
|
||||||
}
|
}
|
||||||
@ -177,8 +180,8 @@ public class ExtentEntityCopy implements EntityFunction {
|
|||||||
uuid
|
uuid
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
TaskManager.taskManager().sync(entity::remove);
|
||||||
//FAWE end
|
//FAWE end
|
||||||
entity.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class RequestExtent implements Extent {
|
public class RequestExtent implements Extent {
|
||||||
|
|
||||||
@ -75,6 +76,14 @@ public class RequestExtent implements Extent {
|
|||||||
return getExtent().createEntity(location, entity);
|
return getExtent().createEntity(location, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return getExtent().createEntity(location, entity, uuid);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
return getExtent().getBlock(position);
|
return getExtent().getBlock(position);
|
||||||
|
@ -52,6 +52,7 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A null implementation of {@link World} that drops all changes and
|
* A null implementation of {@link World} that drops all changes and
|
||||||
@ -229,6 +230,14 @@ public class NullWorld extends AbstractWorld {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FAWE start
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an instance of this null world.
|
* Return an instance of this null world.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user