geforkt von Mirrors/FastAsyncWorldEdit
delete some classes
Dieser Commit ist enthalten in:
Ursprung
b3601eb858
Commit
21caf0cf94
@ -1,150 +0,0 @@
|
|||||||
package com.boydti.fawe.bukkit.adapter.v1_13_1;
|
|
||||||
|
|
||||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|
||||||
import net.minecraft.server.v1_13_R2.Block;
|
|
||||||
import net.minecraft.server.v1_13_R2.EnumPistonReaction;
|
|
||||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
|
||||||
import net.minecraft.server.v1_13_R2.ITileEntity;
|
|
||||||
import net.minecraft.server.v1_13_R2.Material;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData;
|
|
||||||
|
|
||||||
public class BlockMaterial_1_13 implements BlockMaterial {
|
|
||||||
private final Block block;
|
|
||||||
private final IBlockData defaultState;
|
|
||||||
private final Material material;
|
|
||||||
private final boolean isTranslucent;
|
|
||||||
private final CraftBlockData craftBlockData;
|
|
||||||
|
|
||||||
public BlockMaterial_1_13(Block block) {
|
|
||||||
this(block, block.getBlockData());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockMaterial_1_13(Block block, IBlockData defaultState) {
|
|
||||||
this.block = block;
|
|
||||||
this.defaultState = defaultState;
|
|
||||||
this.material = defaultState.getMaterial();
|
|
||||||
this.craftBlockData = CraftBlockData.fromData(defaultState);
|
|
||||||
this.isTranslucent = block.f(defaultState); //isSolid
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock() {
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBlockData getState() {
|
|
||||||
return defaultState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CraftBlockData getCraftBlockData() {
|
|
||||||
return craftBlockData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Material getMaterial() {
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAir() {
|
|
||||||
return defaultState.isAir();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFullCube() {
|
|
||||||
return defaultState.g();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOpaque() {
|
|
||||||
return material.f();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPowerSource() {
|
|
||||||
return defaultState.isPowerSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLiquid() {
|
|
||||||
return material.isLiquid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSolid() {
|
|
||||||
return material.isBuildable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getHardness() {
|
|
||||||
return block.strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getResistance() {
|
|
||||||
return block.getDurability();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public float getSlipperiness() {
|
|
||||||
return block.n();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLightValue() {
|
|
||||||
return defaultState.e();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLightOpacity() {
|
|
||||||
return isTranslucent() ? 15 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFragileWhenPushed() {
|
|
||||||
return material.getPushReaction() == EnumPistonReaction.DESTROY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUnpushable() {
|
|
||||||
return material.getPushReaction() == EnumPistonReaction.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTicksRandomly() {
|
|
||||||
return block.isTicking(defaultState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isMovementBlocker() {
|
|
||||||
return material.isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBurnable() {
|
|
||||||
return material.isBurnable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isToolRequired() {
|
|
||||||
return !material.isAlwaysDestroyable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReplacedDuringPlacement() {
|
|
||||||
return material.isReplaceable();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTranslucent() {
|
|
||||||
return isTranslucent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasContainer() {
|
|
||||||
return block instanceof ITileEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMapColor() {
|
|
||||||
return material.i().rgb;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,579 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.boydti.fawe.bukkit.adapter.v1_13_1;
|
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.jnbt.*;
|
|
||||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
|
||||||
import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.entity.LazyBaseEntity;
|
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldedit.registry.state.BooleanProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.DirectionalProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.EnumProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.IntegerProperty;
|
|
||||||
import com.sk89q.worldedit.registry.state.Property;
|
|
||||||
import com.sk89q.worldedit.util.Direction;
|
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
|
||||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|
||||||
import net.minecraft.server.v1_13_R2.*;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.CraftChunk;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.CraftServer;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData;
|
|
||||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
public final class Spigot_v1_13_R2 extends CachedBukkitAdapter implements BukkitImplAdapter<NBTBase>{
|
|
||||||
|
|
||||||
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
|
|
||||||
|
|
||||||
private final Field nbtListTagListField;
|
|
||||||
private final Method nbtCreateTagMethod;
|
|
||||||
|
|
||||||
static {
|
|
||||||
// A simple test
|
|
||||||
if (!Bukkit.getServer().getClass().getName().endsWith("DummyServer")) CraftServer.class.cast(Bukkit.getServer());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Code that may break between versions of Minecraft
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
public Spigot_v1_13_R2() throws NoSuchFieldException, NoSuchMethodException {
|
|
||||||
// A simple test
|
|
||||||
CraftServer.class.cast(Bukkit.getServer());
|
|
||||||
|
|
||||||
// The list of tags on an NBTTagList
|
|
||||||
nbtListTagListField = NBTTagList.class.getDeclaredField("list");
|
|
||||||
nbtListTagListField.setAccessible(true);
|
|
||||||
|
|
||||||
// The method to create an NBTBase tag given its type ID
|
|
||||||
nbtCreateTagMethod = NBTBase.class.getDeclaredMethod("createTag", byte.class);
|
|
||||||
nbtCreateTagMethod.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public char[] idbToStateOrdinal;
|
|
||||||
|
|
||||||
private synchronized boolean init() {
|
|
||||||
if (idbToStateOrdinal != null) return false;
|
|
||||||
idbToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
|
||||||
for (int i = 0; i < idbToStateOrdinal.length; i++) {
|
|
||||||
BlockState state = BlockTypes.states[i];
|
|
||||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
|
||||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
|
||||||
idbToStateOrdinal[id] = state.getOrdinalChar();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the given NBT data into the given tile entity.
|
|
||||||
*
|
|
||||||
* @param tileEntity the tile entity
|
|
||||||
* @param tag the tag
|
|
||||||
*/
|
|
||||||
private static void readTagIntoTileEntity(NBTTagCompound tag, TileEntity tileEntity) {
|
|
||||||
try {
|
|
||||||
tileEntity.load(tag);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Fawe.debug("Invalid tag " + tag + " | " + tileEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the tile entity's NBT data to the given tag.
|
|
||||||
*
|
|
||||||
* @param tileEntity the tile entity
|
|
||||||
* @param tag the tag
|
|
||||||
*/
|
|
||||||
private static void readTileEntityIntoTag(TileEntity tileEntity, NBTTagCompound tag) {
|
|
||||||
tileEntity.save(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the ID string of the given entity.
|
|
||||||
*
|
|
||||||
* @param entity the entity
|
|
||||||
* @return the entity ID or null if one is not known
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private static String getEntityId(Entity entity) {
|
|
||||||
MinecraftKey minecraftkey = EntityTypes.getName(entity.getBukkitEntity().getHandle().P());
|
|
||||||
|
|
||||||
return minecraftkey == null ? null : minecraftkey.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an entity using the given entity ID.
|
|
||||||
*
|
|
||||||
* @param id the entity ID
|
|
||||||
* @param world the world
|
|
||||||
* @return an entity or null
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private static Entity createEntityFromId(String id, World world) {
|
|
||||||
return EntityTypes.a(world, new MinecraftKey(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the given NBT data into the given entity.
|
|
||||||
*
|
|
||||||
* @param entity the entity
|
|
||||||
* @param tag the tag
|
|
||||||
*/
|
|
||||||
private static void readTagIntoEntity(NBTTagCompound tag, Entity entity) {
|
|
||||||
entity.f(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the entity's NBT data to the given tag.
|
|
||||||
*
|
|
||||||
* @param entity the entity
|
|
||||||
* @param tag the tag
|
|
||||||
*/
|
|
||||||
private static void readEntityIntoTag(Entity entity, NBTTagCompound tag) {
|
|
||||||
entity.save(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockMaterial getMaterial(BlockType blockType) {
|
|
||||||
return new BlockMaterial_1_13(getBlock(blockType));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockMaterial getMaterial(BlockState state) {
|
|
||||||
IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState();
|
|
||||||
return new BlockMaterial_1_13(bs.getBlock(), bs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getBlock(BlockType blockType) {
|
|
||||||
return IRegistry.BLOCK.getOrDefault(new MinecraftKey(blockType.getNamespace(), blockType.getResource()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseBlock getBlock(Location location) {
|
|
||||||
checkNotNull(location);
|
|
||||||
|
|
||||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
|
||||||
int x = location.getBlockX();
|
|
||||||
int y = location.getBlockY();
|
|
||||||
int z = location.getBlockZ();
|
|
||||||
|
|
||||||
org.bukkit.block.Block bukkitBlock = location.getBlock();
|
|
||||||
BlockState state = BukkitAdapter.adapt(bukkitBlock.getBlockData());
|
|
||||||
if (state.getBlockType().getMaterial().hasContainer()) {
|
|
||||||
//Read the NBT data
|
|
||||||
TileEntity te = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z));
|
|
||||||
if (te != null) {
|
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
|
||||||
readTileEntityIntoTag(te, tag); // Load data
|
|
||||||
return state.toBaseBlock((CompoundTag) toNative(tag));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state.toBaseBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChunkInUse(org.bukkit.Chunk chunk) {
|
|
||||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
|
||||||
PlayerChunkMap chunkMap = ((WorldServer) craftChunk.getHandle().getWorld()).getPlayerChunkMap();
|
|
||||||
return chunkMap.isChunkInUse(chunk.getX(), chunk.getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) {
|
|
||||||
CraftChunk craftChunk = (CraftChunk) chunk;
|
|
||||||
Chunk nmsChunk = craftChunk.getHandle();
|
|
||||||
World nmsWorld = nmsChunk.getWorld();
|
|
||||||
|
|
||||||
IBlockData blockData = ((BlockMaterial_1_13) state.getMaterial()).getState();
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
int y4 = y >> 4;
|
|
||||||
ChunkSection section = sections[y4];
|
|
||||||
|
|
||||||
IBlockData existing;
|
|
||||||
if (section == null) {
|
|
||||||
existing = ((BlockMaterial_1_13) BlockTypes.AIR.getDefaultState().getMaterial()).getState();
|
|
||||||
} else {
|
|
||||||
existing = section.getType(x & 15, y & 15, z & 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockPosition pos = new BlockPosition(x, y, z);
|
|
||||||
|
|
||||||
nmsChunk.d(pos); // Force delete the old tile entity
|
|
||||||
|
|
||||||
CompoundTag nativeTag = state instanceof BaseBlock ? state.getNbtData() : null;
|
|
||||||
if (nativeTag != null || existing instanceof TileEntityBlock) {
|
|
||||||
nmsWorld.setTypeAndData(pos, blockData, 0);
|
|
||||||
// remove tile
|
|
||||||
if (nativeTag != null) {
|
|
||||||
// We will assume that the tile entity was created for us,
|
|
||||||
// though we do not do this on the Forge version
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag);
|
|
||||||
tag.set("x", new NBTTagInt(x));
|
|
||||||
tag.set("y", new NBTTagInt(y));
|
|
||||||
tag.set("z", new NBTTagInt(z));
|
|
||||||
readTagIntoTileEntity(tag, tileEntity); // Load data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (existing == blockData) return true;
|
|
||||||
if (section == null) {
|
|
||||||
if (blockData.isAir()) return true;
|
|
||||||
sections[y4] = section = new ChunkSection(y4 << 4, nmsWorld.worldProvider.g());
|
|
||||||
}
|
|
||||||
if (existing.e() != blockData.e() || existing.getMaterial().f() != blockData.getMaterial().f()) {
|
|
||||||
nmsChunk.setType(pos = new BlockPosition(x, y, z), blockData, false);
|
|
||||||
} else {
|
|
||||||
section.setType(x & 15, y & 15, z & 15, blockData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (update) {
|
|
||||||
nmsWorld.getMinecraftWorld().notify(pos, existing, blockData, 0);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseEntity getEntity(org.bukkit.entity.Entity entity) {
|
|
||||||
checkNotNull(entity);
|
|
||||||
|
|
||||||
CraftEntity craftEntity = ((CraftEntity) entity);
|
|
||||||
Entity mcEntity = craftEntity.getHandle();
|
|
||||||
|
|
||||||
String id = getEntityId(mcEntity);
|
|
||||||
|
|
||||||
if (id != null) {
|
|
||||||
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
|
|
||||||
Supplier<CompoundTag> saveTag = new Supplier<CompoundTag>() {
|
|
||||||
@Override
|
|
||||||
public CompoundTag get() {
|
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
|
||||||
readEntityIntoTag(mcEntity, tag);
|
|
||||||
return (CompoundTag) toNative(tag);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return new LazyBaseEntity(type, saveTag);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) {
|
|
||||||
checkNotNull(location);
|
|
||||||
checkNotNull(state);
|
|
||||||
if (state.getType() == com.sk89q.worldedit.world.entity.EntityTypes.PLAYER) return null;
|
|
||||||
CraftWorld craftWorld = ((CraftWorld) location.getWorld());
|
|
||||||
WorldServer worldServer = craftWorld.getHandle();
|
|
||||||
|
|
||||||
Entity createdEntity = createEntityFromId(state.getType().getId(), craftWorld.getHandle());
|
|
||||||
|
|
||||||
if (createdEntity != null) {
|
|
||||||
CompoundTag nativeTag = state.getNbtData();
|
|
||||||
if (nativeTag != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag);
|
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
|
||||||
tag.remove(name);
|
|
||||||
}
|
|
||||||
readTagIntoEntity(tag, createdEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
createdEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
||||||
|
|
||||||
worldServer.addEntity(createdEntity, SpawnReason.CUSTOM);
|
|
||||||
return createdEntity.getBukkitEntity();
|
|
||||||
} else {
|
|
||||||
Fawe.debug("Invalid entity " + state.getType().getId());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
|
||||||
Block block;
|
|
||||||
try {
|
|
||||||
block = IRegistry.BLOCK.getOrDefault(new MinecraftKey(blockType.getNamespace(), blockType.getResource()));
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
if (block == null) {
|
|
||||||
logger.warning("Failed to find properties for " + blockType.getId());
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
Map<String, Property<?>> properties = Maps.newLinkedHashMap();
|
|
||||||
BlockStateList<Block, IBlockData> blockStateList = block.getStates();
|
|
||||||
for (IBlockState state : blockStateList.d()) {
|
|
||||||
Property property;
|
|
||||||
if (state instanceof BlockStateBoolean) {
|
|
||||||
property = new BooleanProperty(state.a(), ImmutableList.copyOf(state.d()));
|
|
||||||
} else if (state instanceof BlockStateDirection) {
|
|
||||||
property = new DirectionalProperty(state.a(),
|
|
||||||
(List<Direction>) state.d().stream().map(e -> Direction.valueOf(((INamable) e).getName().toUpperCase(Locale.ROOT))).collect(Collectors.toList()));
|
|
||||||
} else if (state instanceof BlockStateEnum) {
|
|
||||||
property = new EnumProperty(state.a(),
|
|
||||||
(List<String>) state.d().stream().map(e -> ((INamable) e).getName()).collect(Collectors.toList()));
|
|
||||||
} else if (state instanceof BlockStateInteger) {
|
|
||||||
property = new IntegerProperty(state.a(), ImmutableList.copyOf(state.d()));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("WorldEdit needs an update to support " + state.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
|
|
||||||
properties.put(property.getName(), property);
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts from a non-native NMS NBT structure to a native WorldEdit NBT
|
|
||||||
* structure.
|
|
||||||
*
|
|
||||||
* @param foreign non-native NMS NBT structure
|
|
||||||
* @return native WorldEdit NBT structure
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Tag toNative(NBTBase foreign) {
|
|
||||||
if (foreign == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (foreign instanceof NBTTagCompound) {
|
|
||||||
Map<String, Tag> values = new HashMap<>();
|
|
||||||
Set<String> foreignKeys = ((NBTTagCompound) foreign).getKeys(); // map.keySet
|
|
||||||
|
|
||||||
for (String str : foreignKeys) {
|
|
||||||
NBTBase base = ((NBTTagCompound) foreign).get(str);
|
|
||||||
values.put(str, toNative(base));
|
|
||||||
}
|
|
||||||
return new CompoundTag(values);
|
|
||||||
} else if (foreign instanceof NBTTagByte) {
|
|
||||||
return new ByteTag(((NBTTagByte) foreign).asByte());
|
|
||||||
} else if (foreign instanceof NBTTagByteArray) {
|
|
||||||
return new ByteArrayTag(((NBTTagByteArray) foreign).c()); // data
|
|
||||||
} else if (foreign instanceof NBTTagDouble) {
|
|
||||||
return new DoubleTag(((NBTTagDouble) foreign).asDouble()); // getDouble
|
|
||||||
} else if (foreign instanceof NBTTagFloat) {
|
|
||||||
return new FloatTag(((NBTTagFloat) foreign).asFloat());
|
|
||||||
} else if (foreign instanceof NBTTagInt) {
|
|
||||||
return new IntTag(((NBTTagInt) foreign).asInt());
|
|
||||||
} else if (foreign instanceof NBTTagIntArray) {
|
|
||||||
return new IntArrayTag(((NBTTagIntArray) foreign).d()); // data
|
|
||||||
} else if (foreign instanceof NBTTagLongArray) {
|
|
||||||
return new LongArrayTag(((NBTTagLongArray) foreign).d()); // data
|
|
||||||
} else if (foreign instanceof NBTTagList) {
|
|
||||||
try {
|
|
||||||
return toNativeList((NBTTagList) foreign);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
logger.log(Level.WARNING, "Failed to convert NBTTagList", e);
|
|
||||||
return new ListTag(ByteTag.class, new ArrayList<ByteTag>());
|
|
||||||
}
|
|
||||||
} else if (foreign instanceof NBTTagLong) {
|
|
||||||
return new LongTag(((NBTTagLong) foreign).asLong());
|
|
||||||
} else if (foreign instanceof NBTTagShort) {
|
|
||||||
return new ShortTag(((NBTTagShort) foreign).asShort());
|
|
||||||
} else if (foreign instanceof NBTTagString) {
|
|
||||||
return new StringTag(foreign.asString());
|
|
||||||
} else if (foreign instanceof NBTTagEnd) {
|
|
||||||
return new EndTag();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a foreign NBT list tag into a native WorldEdit one.
|
|
||||||
*
|
|
||||||
* @param foreign the foreign tag
|
|
||||||
* @return the converted tag
|
|
||||||
* @throws NoSuchFieldException on error
|
|
||||||
* @throws SecurityException on error
|
|
||||||
* @throws IllegalArgumentException on error
|
|
||||||
* @throws IllegalAccessException on error
|
|
||||||
*/
|
|
||||||
private ListTag toNativeList(NBTTagList foreign) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
|
||||||
List<Tag> values = new ArrayList<>();
|
|
||||||
int type = foreign.d();
|
|
||||||
|
|
||||||
List foreignList;
|
|
||||||
foreignList = (List) nbtListTagListField.get(foreign);
|
|
||||||
for (int i = 0; i < foreign.size(); i++) {
|
|
||||||
NBTBase element = (NBTBase) foreignList.get(i);
|
|
||||||
values.add(toNative(element)); // List elements shouldn't have names
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<? extends Tag> cls = NBTConstants.getClassFromType(type);
|
|
||||||
return new ListTag(cls, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a WorldEdit-native NBT structure to a NMS structure.
|
|
||||||
*
|
|
||||||
* @param foreign structure to convert
|
|
||||||
* @return non-native structure
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public NBTBase fromNative(Tag foreign) {
|
|
||||||
if (foreign == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (foreign instanceof CompoundTag) {
|
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
|
||||||
for (Map.Entry<String, Tag> entry : ((CompoundTag) foreign)
|
|
||||||
.getValue().entrySet()) {
|
|
||||||
tag.set(entry.getKey(), fromNative(entry.getValue()));
|
|
||||||
}
|
|
||||||
return tag;
|
|
||||||
} else if (foreign instanceof ByteTag) {
|
|
||||||
return new NBTTagByte(((ByteTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof ByteArrayTag) {
|
|
||||||
return new NBTTagByteArray(((ByteArrayTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof DoubleTag) {
|
|
||||||
return new NBTTagDouble(((DoubleTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof FloatTag) {
|
|
||||||
return new NBTTagFloat(((FloatTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof IntTag) {
|
|
||||||
return new NBTTagInt(((IntTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof IntArrayTag) {
|
|
||||||
return new NBTTagIntArray(((IntArrayTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof LongArrayTag) {
|
|
||||||
return new NBTTagLongArray(((LongArrayTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof ListTag) {
|
|
||||||
NBTTagList tag = new NBTTagList();
|
|
||||||
ListTag foreignList = (ListTag) foreign;
|
|
||||||
for (Tag t : foreignList.getValue()) {
|
|
||||||
tag.add(fromNative(t));
|
|
||||||
}
|
|
||||||
return tag;
|
|
||||||
} else if (foreign instanceof LongTag) {
|
|
||||||
return new NBTTagLong(((LongTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof ShortTag) {
|
|
||||||
return new NBTTagShort(((ShortTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof StringTag) {
|
|
||||||
return new NBTTagString(((StringTag) foreign).getValue());
|
|
||||||
} else if (foreign instanceof EndTag) {
|
|
||||||
try {
|
|
||||||
return (NBTBase) nbtCreateTagMethod.invoke(null, (byte) 0);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockState adapt(BlockData blockData) {
|
|
||||||
CraftBlockData cbd = ((CraftBlockData) blockData);
|
|
||||||
IBlockData ibd = cbd.getState();
|
|
||||||
return adapt(ibd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState adapt(IBlockData ibd) {
|
|
||||||
return BlockTypes.states[adaptToInt(ibd)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public int adaptToInt(IBlockData ibd) {
|
|
||||||
try {
|
|
||||||
int id = Block.REGISTRY_ID.getId(ibd);
|
|
||||||
return idbToStateOrdinal[id];
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
init();
|
|
||||||
return adaptToInt(ibd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public char adaptToChar(IBlockData ibd) {
|
|
||||||
try {
|
|
||||||
int id = Block.REGISTRY_ID.getId(ibd);
|
|
||||||
return idbToStateOrdinal[id];
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
init();
|
|
||||||
return adaptToChar(ibd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockData adapt(BlockStateHolder state) {
|
|
||||||
BlockMaterial_1_13 material = (BlockMaterial_1_13) state.getMaterial();
|
|
||||||
return material.getCraftBlockData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendFakeNBT(Player player, BlockVector3 pos, CompoundTag nbtData) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyAndLightBlock(Location position, BlockState previousType) {
|
|
||||||
this.setBlock(position.getChunk(), position.getBlockX(), position.getBlockY(), position.getBlockZ(), previousType, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setBlock(Location location, BlockStateHolder<?> state, boolean notifyAndLight) {
|
|
||||||
return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendFakeOP(Player player) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,356 +0,0 @@
|
|||||||
package com.boydti.fawe.bukkit.beta;
|
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
|
||||||
import com.boydti.fawe.beta.IChunkGet;
|
|
||||||
import com.boydti.fawe.beta.IQueueExtent;
|
|
||||||
import com.boydti.fawe.beta.IChunkSet;
|
|
||||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
|
||||||
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
|
|
||||||
import com.boydti.fawe.util.MemUtil;
|
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.LongTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
import net.minecraft.server.v1_14_R1.BiomeBase;
|
|
||||||
import net.minecraft.server.v1_14_R1.BlockPosition;
|
|
||||||
import net.minecraft.server.v1_14_R1.Chunk;
|
|
||||||
import net.minecraft.server.v1_14_R1.ChunkSection;
|
|
||||||
import net.minecraft.server.v1_14_R1.Entity;
|
|
||||||
import net.minecraft.server.v1_14_R1.EntityTypes;
|
|
||||||
import net.minecraft.server.v1_14_R1.NBTTagCompound;
|
|
||||||
import net.minecraft.server.v1_14_R1.NBTTagInt;
|
|
||||||
import net.minecraft.server.v1_14_R1.TileEntity;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.Biome;
|
|
||||||
import org.bukkit.craftbukkit.v1_14_R1.block.CraftBlock;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
|
|
||||||
@Override
|
|
||||||
public void init(final IQueueExtent extent, final int chunkX, final int chunkZ) {
|
|
||||||
super.init(extent, chunkX, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IChunkGet get() {
|
|
||||||
BukkitQueue extent = (BukkitQueue) getExtent();
|
|
||||||
return new BukkitGetBlocks(extent.getNmsWorld(), getX(), getZ(), MemUtil.isMemoryFree());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateGet(BukkitGetBlocks get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) {
|
|
||||||
synchronized (get) {
|
|
||||||
if (get.nmsChunk != nmsChunk) {
|
|
||||||
get.nmsChunk = nmsChunk;
|
|
||||||
get.sections = sections.clone();
|
|
||||||
get.reset();
|
|
||||||
}
|
|
||||||
if (get.sections == null) {
|
|
||||||
get.sections = sections.clone();
|
|
||||||
}
|
|
||||||
if (get.sections[layer] != section) {
|
|
||||||
get.sections[layer] = section;
|
|
||||||
}
|
|
||||||
get.blocks[layer] = arr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeEntity(Entity entity) {
|
|
||||||
entity.die();
|
|
||||||
entity.valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized T call() {
|
|
||||||
try {
|
|
||||||
int X = getX();
|
|
||||||
int Z = getZ();
|
|
||||||
BukkitQueue extent = (BukkitQueue) getExtent();
|
|
||||||
BukkitGetBlocks get = (BukkitGetBlocks) getOrCreateGet();
|
|
||||||
IChunkSet set = getOrCreateSet();
|
|
||||||
|
|
||||||
Chunk nmsChunk = extent.ensureLoaded(X, Z);
|
|
||||||
|
|
||||||
// Remove existing tiles
|
|
||||||
{
|
|
||||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
|
||||||
if (!tiles.isEmpty()) {
|
|
||||||
final Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
final Map.Entry<BlockPosition, TileEntity> entry = iterator.next();
|
|
||||||
final BlockPosition pos = entry.getKey();
|
|
||||||
final int lx = pos.getX() & 15;
|
|
||||||
final int ly = pos.getY();
|
|
||||||
final int lz = pos.getZ() & 15;
|
|
||||||
final int layer = ly >> 4;
|
|
||||||
if (!set.hasSection(layer)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (set.getBlock(lx, ly, lz).getOrdinal() != 0) {
|
|
||||||
TileEntity tile = entry.getValue();
|
|
||||||
tile.n();
|
|
||||||
tile.invalidateBlockCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int bitMask = 0;
|
|
||||||
synchronized (nmsChunk) {
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
World world = extent.getBukkitWorld();
|
|
||||||
boolean hasSky = world.getEnvironment() == World.Environment.NORMAL;
|
|
||||||
|
|
||||||
for (int layer = 0; layer < 16; layer++) {
|
|
||||||
if (!set.hasSection(layer)) continue;
|
|
||||||
|
|
||||||
bitMask |= 1 << layer;
|
|
||||||
|
|
||||||
char[] setArr = set.getArray(layer);
|
|
||||||
ChunkSection newSection;
|
|
||||||
ChunkSection existingSection = sections[layer];
|
|
||||||
if (existingSection == null) {
|
|
||||||
newSection = extent.newChunkSection(layer, setArr);
|
|
||||||
if (BukkitQueue.setSectionAtomic(sections, null, newSection, layer)) {
|
|
||||||
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
existingSection = sections[layer];
|
|
||||||
if (existingSection == null) {
|
|
||||||
System.out.println("Skipping invalid null section. chunk:" + X + "," + Z + " layer: " + layer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DelegateLock lock = BukkitQueue.applyLock(existingSection);
|
|
||||||
synchronized (get) {
|
|
||||||
synchronized (lock) {
|
|
||||||
lock.untilFree();
|
|
||||||
|
|
||||||
ChunkSection getSection;
|
|
||||||
if (get.nmsChunk != nmsChunk) {
|
|
||||||
get.nmsChunk = nmsChunk;
|
|
||||||
get.sections = null;
|
|
||||||
get.reset();
|
|
||||||
} else {
|
|
||||||
getSection = get.getSections()[layer];
|
|
||||||
if (getSection != existingSection) {
|
|
||||||
get.sections[layer] = existingSection;
|
|
||||||
get.reset();
|
|
||||||
} else if (lock.isModified()) {
|
|
||||||
get.reset(layer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char[] getArr = get.load(layer);
|
|
||||||
for (int i = 0; i < 4096; i++) {
|
|
||||||
char value = setArr[i];
|
|
||||||
if (value != 0) {
|
|
||||||
getArr[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newSection = extent.newChunkSection(layer, getArr);
|
|
||||||
if (!BukkitQueue.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
|
||||||
System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
updateGet(get, nmsChunk, sections, newSection, setArr, layer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Biomes
|
|
||||||
BiomeType[] biomes = set.getBiomes();
|
|
||||||
if (biomes != null) {
|
|
||||||
// set biomes
|
|
||||||
final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex();
|
|
||||||
for (int i = 0; i < biomes.length; i++) {
|
|
||||||
final BiomeType biome = biomes[i];
|
|
||||||
if (biome != null) {
|
|
||||||
final Biome craftBiome = BukkitAdapter.adapt(biome);
|
|
||||||
currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Runnable[] syncTasks = null;
|
|
||||||
|
|
||||||
net.minecraft.server.v1_14_R1.World nmsWorld = nmsChunk.getWorld();
|
|
||||||
int bx = X << 4;
|
|
||||||
int bz = Z << 4;
|
|
||||||
|
|
||||||
Set<UUID> entityRemoves = set.getEntityRemoves();
|
|
||||||
if (entityRemoves != null && !entityRemoves.isEmpty()) {
|
|
||||||
if (syncTasks == null) syncTasks = new Runnable[3];
|
|
||||||
|
|
||||||
syncTasks[2] = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
|
||||||
|
|
||||||
for (int i = 0; i < entities.length; i++) {
|
|
||||||
final Collection<Entity> ents = entities[i];
|
|
||||||
if (!ents.isEmpty()) {
|
|
||||||
final Iterator<Entity> iter = ents.iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
final Entity entity = iter.next();
|
|
||||||
if (entityRemoves.contains(entity.getUniqueID())) {
|
|
||||||
iter.remove();
|
|
||||||
removeEntity(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<CompoundTag> entities = set.getEntities();
|
|
||||||
if (entities != null && !entities.isEmpty()) {
|
|
||||||
if (syncTasks == null) syncTasks = new Runnable[2];
|
|
||||||
|
|
||||||
syncTasks[1] = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (final CompoundTag nativeTag : entities) {
|
|
||||||
final Map<String, Tag> entityTagMap = ReflectionUtils.getMap(nativeTag.getValue());
|
|
||||||
final StringTag idTag = (StringTag) entityTagMap.get("Id");
|
|
||||||
final ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
|
||||||
final ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
|
||||||
if (idTag == null || posTag == null || rotTag == null) {
|
|
||||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final double x = posTag.getDouble(0);
|
|
||||||
final double y = posTag.getDouble(1);
|
|
||||||
final double z = posTag.getDouble(2);
|
|
||||||
final float yaw = rotTag.getFloat(0);
|
|
||||||
final float pitch = rotTag.getFloat(1);
|
|
||||||
final String id = idTag.getValue();
|
|
||||||
|
|
||||||
EntityTypes<?> type = EntityTypes.a(id).orElse(null);
|
|
||||||
if (type != null) {
|
|
||||||
Entity entity = type.a(nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
UUID uuid = entity.getUniqueID();
|
|
||||||
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
|
|
||||||
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
|
|
||||||
if (nativeTag != null) {
|
|
||||||
final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_14.fromNative(nativeTag);
|
|
||||||
for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
|
||||||
tag.remove(name);
|
|
||||||
}
|
|
||||||
entity.f(tag);
|
|
||||||
}
|
|
||||||
entity.setLocation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// set tiles
|
|
||||||
Map<Short, CompoundTag> tiles = set.getTiles();
|
|
||||||
if (tiles != null && !tiles.isEmpty()) {
|
|
||||||
if (syncTasks == null) syncTasks = new Runnable[1];
|
|
||||||
|
|
||||||
syncTasks[0] = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (final Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
|
|
||||||
final CompoundTag nativeTag = entry.getValue();
|
|
||||||
final short blockHash = entry.getKey();
|
|
||||||
final int x = (blockHash >> 12 & 0xF) + bx;
|
|
||||||
final int y = (blockHash & 0xFF);
|
|
||||||
final int z = (blockHash >> 8 & 0xF) + bz;
|
|
||||||
final BlockPosition pos = new BlockPosition(x, y, z);
|
|
||||||
synchronized (nmsWorld) {
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
if (tileEntity == null || tileEntity.isRemoved()) {
|
|
||||||
nmsWorld.removeTileEntity(pos);
|
|
||||||
tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
}
|
|
||||||
if (tileEntity != null) {
|
|
||||||
final NBTTagCompound tag = (NBTTagCompound) fromNative(nativeTag);
|
|
||||||
tag.set("x", new NBTTagInt(x));
|
|
||||||
tag.set("y", new NBTTagInt(y));
|
|
||||||
tag.set("z", new NBTTagInt(z));
|
|
||||||
tileEntity.load(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Runnable callback;
|
|
||||||
if (bitMask == 0) {
|
|
||||||
callback = null;
|
|
||||||
} else {
|
|
||||||
int finalMask = bitMask;
|
|
||||||
callback = () -> {
|
|
||||||
// Set Modified
|
|
||||||
nmsChunk.d(true); // Set Modified
|
|
||||||
nmsChunk.mustNotSave = false;
|
|
||||||
nmsChunk.markDirty();
|
|
||||||
// send to player
|
|
||||||
extent.sendChunk(X, Z, finalMask);
|
|
||||||
|
|
||||||
extent.returnToPool(BukkitChunkHolder.this);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (syncTasks != null) {
|
|
||||||
QueueHandler queueHandler = Fawe.get().getQueueHandler();
|
|
||||||
Runnable[] finalSyncTasks = syncTasks;
|
|
||||||
|
|
||||||
// Chain the sync tasks and the callback
|
|
||||||
Callable<Future> chain = new Callable<Future>() {
|
|
||||||
@Override
|
|
||||||
public Future call() {
|
|
||||||
// Run the sync tasks
|
|
||||||
for (int i = 1; i < finalSyncTasks.length; i++) {
|
|
||||||
Runnable task = finalSyncTasks[i];
|
|
||||||
if (task != null) {
|
|
||||||
task.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (callback == null) {
|
|
||||||
extent.returnToPool(BukkitChunkHolder.this);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return queueHandler.async(callback, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (T) (Future) queueHandler.sync(chain);
|
|
||||||
} else {
|
|
||||||
if (callback == null) {
|
|
||||||
extent.returnToPool(BukkitChunkHolder.this);
|
|
||||||
} else {
|
|
||||||
callback.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package com.boydti.fawe.beta.implementation;
|
|
||||||
|
|
||||||
import com.boydti.fawe.beta.IChunkGet;
|
|
||||||
import com.boydti.fawe.beta.Trimable;
|
|
||||||
import com.sk89q.worldedit.world.World;
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IGetBlocks may be cached by the WorldChunkCache so that it can be used between multiple
|
|
||||||
* IQueueExtents - avoids conversion between palette and raw data on every block get
|
|
||||||
*/
|
|
||||||
public class WorldChunkCache implements Trimable {
|
|
||||||
|
|
||||||
protected final Long2ObjectLinkedOpenHashMap<WeakReference<IChunkGet>> getCache;
|
|
||||||
private final World world;
|
|
||||||
|
|
||||||
protected WorldChunkCache(World world) {
|
|
||||||
this.world = world;
|
|
||||||
this.getCache = new Long2ObjectLinkedOpenHashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public World getWorld() {
|
|
||||||
return world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int size() {
|
|
||||||
return getCache.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get or create the IGetBlocks
|
|
||||||
*
|
|
||||||
* @param index chunk index {@link com.boydti.fawe.util.MathMan#pairInt(int, int)}
|
|
||||||
* @param provider used to create if it isn't already cached
|
|
||||||
* @return cached IGetBlocks
|
|
||||||
*/
|
|
||||||
public synchronized IChunkGet get(long index, Supplier<IChunkGet> provider) {
|
|
||||||
final WeakReference<IChunkGet> ref = getCache.get(index);
|
|
||||||
if (ref != null) {
|
|
||||||
final IChunkGet blocks = ref.get();
|
|
||||||
if (blocks != null) {
|
|
||||||
return blocks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final IChunkGet blocks = provider.get();
|
|
||||||
getCache.put(index, new WeakReference<>(blocks));
|
|
||||||
return blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized boolean trim(boolean aggressive) {
|
|
||||||
boolean result = true;
|
|
||||||
if (!getCache.isEmpty()) {
|
|
||||||
final ObjectIterator<Long2ObjectMap.Entry<WeakReference<IChunkGet>>> iter = getCache
|
|
||||||
.long2ObjectEntrySet().fastIterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
final Long2ObjectMap.Entry<WeakReference<IChunkGet>> entry = iter.next();
|
|
||||||
final WeakReference<IChunkGet> value = entry.getValue();
|
|
||||||
final IChunkGet igb = value.get();
|
|
||||||
if (igb == null) {
|
|
||||||
iter.remove();
|
|
||||||
} else {
|
|
||||||
result = false;
|
|
||||||
if (!aggressive) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
synchronized (igb) {
|
|
||||||
igb.trim(aggressive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package com.boydti.fawe.object.collection;
|
|
||||||
|
|
||||||
public class ByteStore extends IterableThreadLocal<byte[]> {
|
|
||||||
private final int size;
|
|
||||||
|
|
||||||
public ByteStore(int size) {
|
|
||||||
this.size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] init() {
|
|
||||||
return new byte[size];
|
|
||||||
}
|
|
||||||
}
|
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren