API to get a BlockState without a snapshot

This allows you to get a BlockState without creating a snapshot, operating
on the real tile entity.

This is useful for where performance is needed

also Avoid NPE during CraftBlockEntityState load if could not get TE

If Tile Entity was null, correct Sign to return empty lines instead of null
This commit is contained in:
Aikar 2017-11-06 21:08:22 -05:00
parent 1d1c5a4493
commit eb20b0b160
5 changed files with 71 additions and 10 deletions

View file

@ -19,14 +19,22 @@
private static final Logger LOGGER = LogUtils.getLogger();
private final BlockEntityType<?> type;
@Nullable
@@ -74,8 +84,17 @@
@@ -43,6 +53,7 @@
this.worldPosition = pos.immutable();
this.validateBlockState(state);
this.blockState = state;
+ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
}
private void validateBlockState(BlockState state) {
@@ -74,8 +85,17 @@
return this.level != null;
}
- protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {}
+ // CraftBukkit start - read container
+ protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
+ this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY);
+ this.persistentDataContainer.clear(); // Paper - clear instead of init
+ net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues");
+ if (persistentDataTag instanceof CompoundTag) {
@ -38,7 +46,7 @@
public final void loadWithComponents(CompoundTag nbt, HolderLookup.Provider registries) {
this.loadAdditional(nbt, registries);
BlockEntity.ComponentHelper.COMPONENTS_CODEC.parse(registries.createSerializationContext(NbtOps.INSTANCE), nbt).resultOrPartial((s) -> {
@@ -114,6 +133,11 @@
@@ -114,6 +134,11 @@
}).ifPresent((nbtbase) -> {
nbttagcompound.merge((CompoundTag) nbtbase);
});
@ -50,7 +58,7 @@
return nbttagcompound;
}
@@ -234,7 +258,12 @@
@@ -234,7 +259,12 @@
public void fillCrashReportCategory(CrashReportCategory crashReportSection) {
crashReportSection.setDetail("Name", this::getNameForReporting);
if (this.level != null) {
@ -64,7 +72,7 @@
CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition));
}
}
@@ -263,13 +292,19 @@
@@ -263,13 +293,19 @@
}
public final void applyComponents(DataComponentMap defaultComponents, DataComponentPatch components) {
@ -86,7 +94,7 @@
@Nullable
@Override
public <T> T get(DataComponentType<T> type) {
@@ -284,9 +319,13 @@
@@ -284,9 +320,13 @@
}
});
Objects.requireNonNull(set);
@ -101,14 +109,21 @@
}
protected void collectImplicitComponents(DataComponentMap.Builder builder) {}
@@ -321,6 +360,15 @@
@@ -321,6 +361,22 @@
}
}
+ // CraftBukkit start - add method
+ public InventoryHolder getOwner() {
+ // Paper start
+ return getOwner(true);
+ }
+ public InventoryHolder getOwner(boolean useSnapshot) {
+ // Paper end
+ if (this.level == null) return null;
+ org.bukkit.block.BlockState state = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()).getState();
+ org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
+ if (block.getType() == org.bukkit.Material.AIR) return null;
+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
+ if (state instanceof InventoryHolder) return (InventoryHolder) state;
+ return null;
+ }

View file

@ -328,6 +328,13 @@ public class CraftBlock implements Block {
return CraftBlockStates.getBlockState(this);
}
// Paper start
@Override
public BlockState getState(boolean useSnapshot) {
return CraftBlockStates.getBlockState(this, useSnapshot);
}
// Paper end
@Override
public Biome getBiome() {
return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ());

View file

@ -24,15 +24,26 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
private final T tileEntity;
private final T snapshot;
public boolean snapshotDisabled; // Paper
public static boolean DISABLE_SNAPSHOT = false; // Paper
public CraftBlockEntityState(World world, T tileEntity) {
super(world, tileEntity.getBlockPos(), tileEntity.getBlockState());
this.tileEntity = tileEntity;
// Paper start
this.snapshotDisabled = DISABLE_SNAPSHOT;
if (DISABLE_SNAPSHOT) {
this.snapshot = this.tileEntity;
} else {
this.snapshot = this.createSnapshot(tileEntity);
}
// copy tile entity data:
this.snapshot = this.createSnapshot(tileEntity);
this.load(this.snapshot);
if (this.snapshot != null) {
this.load(this.snapshot);
}
// Paper end
}
protected CraftBlockEntityState(CraftBlockEntityState<T> state, Location location) {
@ -184,4 +195,11 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
public CraftBlockEntityState<T> copy(Location location) {
return new CraftBlockEntityState<>(this, location);
}
// Paper start
@Override
public boolean isSnapshot() {
return !this.snapshotDisabled;
}
// Paper end
}

View file

@ -393,15 +393,30 @@ public final class CraftBlockStates {
}
public static BlockState getBlockState(Block block) {
// Paper start
return CraftBlockStates.getBlockState(block, true);
}
public static BlockState getBlockState(Block block, boolean useSnapshot) {
// Paper end
Preconditions.checkNotNull(block, "block is null");
CraftBlock craftBlock = (CraftBlock) block;
CraftWorld world = (CraftWorld) block.getWorld();
BlockPos blockPosition = craftBlock.getPosition();
net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS();
BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition);
// Paper start - block state snapshots
boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
try {
// Paper end
CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity);
blockState.setWorldHandle(craftBlock.getHandle()); // Inject the block's generator access
return blockState;
// Paper start
} finally {
CraftBlockEntityState.DISABLE_SNAPSHOT = prev;
}
// Paper end
}
@Deprecated

View file

@ -177,4 +177,10 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
public String serialize() {
return CraftNBTTagConfigSerializer.serialize(this.toTagCompound());
}
// Paper start
public void clear() {
this.customDataTags.clear();
}
// Paper end
}