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:
Jordan
2022-06-21 14:52:02 +01:00
committed by GitHub
parent d62c88a2ca
commit 968799503f
43 changed files with 556 additions and 336 deletions

View File

@ -14,7 +14,6 @@ import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.collection.AdaptedMap;
import com.google.common.base.Suppliers;
import com.google.common.collect.Iterables;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
@ -64,9 +63,9 @@ import javax.annotation.Nonnull;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -79,7 +78,6 @@ import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks {
@ -324,21 +322,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
}
@Override
@SuppressWarnings("unchecked")
public CompoundTag getEntity(UUID uuid) {
Entity entity = serverLevel.getEntity(uuid);
if (entity != null) {
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
for (List<Entity> entry : /*getChunk().getEntitySlices()*/ new List[0]) {
if (entry != null) {
for (Entity ent : entry) {
if (uuid.equals(ent.getUUID())) {
org.bukkit.entity.Entity bukkitEnt = ent.getBukkitEntity();
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
}
for (CompoundTag tag : getEntities()) {
if (uuid.equals(tag.getUUID())) {
return tag;
}
}
return null;
@ -346,21 +338,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Override
public Set<CompoundTag> getEntities() {
List<Entity>[] slices = /*getChunk().getEntitySlices()*/ new List[0];
int size = 0;
for (List<Entity> slice : slices) {
if (slice != null) {
size += slice.size();
}
}
if (slices.length == 0) {
List<Entity> entities = PaperweightPlatformAdapter.getEntities(getChunk());
if (entities.isEmpty()) {
return Collections.emptySet();
}
int finalSize = size;
return new AbstractSet<CompoundTag>() {
int size = entities.size();
return new AbstractSet<>() {
@Override
public int size() {
return finalSize;
return size;
}
@Override
@ -373,17 +359,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
if (!(get instanceof CompoundTag getTag)) {
return false;
}
Map<String, Tag> value = getTag.getValue();
CompoundTag getParts = (CompoundTag) value.get("UUID");
UUID getUUID = new UUID(getParts.getLong("Most"), getParts.getLong("Least"));
for (List<Entity> slice : slices) {
if (slice != null) {
for (Entity entity : slice) {
UUID uuid = entity.getUUID();
if (uuid.equals(getUUID)) {
return true;
}
}
UUID getUUID = getTag.getUUID();
for (Entity entity : entities) {
UUID uuid = entity.getUUID();
if (uuid.equals(getUUID)) {
return true;
}
}
return false;
@ -392,9 +372,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
@Nonnull
@Override
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();
return (CompoundTag) adapter.toNative(input.saveWithoutId(tag));
input.save(tag);
return (CompoundTag) adapter.toNative(tag);
}).collect(Collectors.toList());
return result.iterator();
}
@ -630,23 +611,31 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
}
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) {
if (!ents.isEmpty()) {
final Iterator<Entity> iter = ents.iterator();
while (iter.hasNext()) {
final Entity entity = iter.next();
if (entityRemoves.contains(entity.getUUID())) {
if (createCopy) {
copy.storeEntity(entity);
}
iter.remove();
removeEntity(entity);
}
for (Entity entity : entities) {
UUID uuid = entity.getUUID();
if (entityRemoves.contains(uuid)) {
if (createCopy) {
copy.storeEntity(entity);
}
removeEntity(entity);
entitiesRemoved.add(uuid);
entityRemoves.remove(uuid);
}
}
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] = () -> {
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 StringTag idTag = (StringTag) entityTagMap.get("Id");
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
@ -684,12 +675,23 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
}
entity.load(tag);
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

View File

@ -74,7 +74,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
protected void storeEntity(Entity entity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
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
@ -85,18 +86,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet {
@Override
public CompoundTag getEntity(UUID uuid) {
for (CompoundTag tag : entities) {
UUID tagUUID;
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)) {
if (uuid.equals(tag.getUUID())) {
return tag;
}
}

View File

@ -30,6 +30,7 @@ import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.BitStorage;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
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.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
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));
}
}