mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
宝贝实体方块渲染雏形
This commit is contained in:
@@ -6,4 +6,4 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypes;
|
||||
|
||||
public class BukkitBlockEntityTypes extends BlockEntityTypes {
|
||||
public static final BlockEntityType<SimpleStorageBlockEntity> SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import org.bukkit.GameEvent;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -200,6 +199,4 @@ public class SimpleStorageBlockEntity extends BlockEntity {
|
||||
}
|
||||
this.inventory.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -237,6 +237,10 @@ public final class WorldStorageInjector {
|
||||
chunk.removeBlockEntity(pos);
|
||||
}
|
||||
}
|
||||
if (previous.hasBlockEntityRenderer()) {
|
||||
BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z);
|
||||
chunk.removeBlockEntityRenderer(pos);
|
||||
}
|
||||
if (Config.enableLightSystem()) {
|
||||
// 自定义块到原版块,只需要判断旧块是否和客户端一直
|
||||
BlockStateWrapper wrapper = previous.vanillaBlockState();
|
||||
@@ -266,6 +270,10 @@ public final class WorldStorageInjector {
|
||||
chunk.removeBlockEntity(pos);
|
||||
}
|
||||
}
|
||||
if (previousImmutableBlockState.hasBlockEntityRenderer()) {
|
||||
BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z);
|
||||
chunk.removeBlockEntityRenderer(pos);
|
||||
}
|
||||
}
|
||||
if (newImmutableBlockState.hasBlockEntity()) {
|
||||
BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z);
|
||||
@@ -285,6 +293,10 @@ public final class WorldStorageInjector {
|
||||
chunk.replaceOrCreateTickingBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
if (newImmutableBlockState.hasBlockEntityRenderer()) {
|
||||
BlockPos pos = new BlockPos(chunk.chunkPos.x * 16 + x, section.sectionY * 16 + y, chunk.chunkPos.z * 16 + z);
|
||||
chunk.addBlockEntityRenderer(pos, newImmutableBlockState);
|
||||
}
|
||||
// 如果新方块的光照属性和客户端认为的不同
|
||||
if (Config.enableLightSystem()) {
|
||||
if (previousImmutableBlockState.isEmpty()) {
|
||||
|
||||
@@ -37,6 +37,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementHolder;
|
||||
import net.momirealms.craftengine.core.advancement.network.AdvancementProgress;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
@@ -64,6 +65,7 @@ import net.momirealms.craftengine.core.plugin.network.*;
|
||||
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||
import net.momirealms.craftengine.core.world.chunk.ChunkStatus;
|
||||
import net.momirealms.craftengine.core.world.chunk.Palette;
|
||||
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
|
||||
@@ -261,14 +263,24 @@ public class PacketConsumers {
|
||||
|
||||
public static final BiConsumer<NetWorkUser, ByteBufPacketEvent> FORGET_LEVEL_CHUNK = (user, event) -> {
|
||||
try {
|
||||
BukkitServerPlayer player = (BukkitServerPlayer) user;
|
||||
FriendlyByteBuf buf = event.getBuffer();
|
||||
CEWorld ceWorld = BukkitWorldManager.instance().getWorld(player.world().uuid());
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
long chunkPos = buf.readLong();
|
||||
user.removeTrackedChunk(chunkPos);
|
||||
CEChunk ceChunk = ceWorld.getChunkAtIfLoaded(chunkPos);
|
||||
if (ceChunk != null) {
|
||||
ceChunk.despawnBlockEntities(player);
|
||||
}
|
||||
} else {
|
||||
int x = buf.readInt();
|
||||
int y = buf.readInt();
|
||||
user.removeTrackedChunk(ChunkPos.asLong(x, y));
|
||||
CEChunk ceChunk = ceWorld.getChunkAtIfLoaded(x, y);
|
||||
if (ceChunk != null) {
|
||||
ceChunk.despawnBlockEntities(player);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundForgetLevelChunkPacket", e);
|
||||
@@ -401,6 +413,12 @@ public class PacketConsumers {
|
||||
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
// 记录加载的区块
|
||||
player.addTrackedChunk(chunkPos.longKey, new ChunkStatus());
|
||||
|
||||
CEWorld ceWorld = BukkitWorldManager.instance().getWorld(player.world().uuid());
|
||||
CEChunk ceChunk = ceWorld.getChunkAtIfLoaded(chunkPos.longKey);
|
||||
if (ceChunk != null) {
|
||||
ceChunk.spawnBlockEntities(player);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundLevelChunkWithLightPacket", e);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import io.netty.channel.ChannelHandler;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.BlockEntityHolder;
|
||||
import net.momirealms.craftengine.bukkit.block.entity.SimpleStorageBlockEntity;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
@@ -48,7 +47,6 @@ import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.LightUtils;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRenderer;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRendererConfig;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.SectionPosUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.SectionPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
@@ -39,4 +42,9 @@ public class BukkitCEWorld extends CEWorld {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntityRenderer createBlockEntityRenderer(BlockEntityRendererConfig config, BlockPos pos) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntityType;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRendererConfig;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
@@ -30,6 +31,8 @@ public final class ImmutableBlockState extends BlockStateHolder {
|
||||
private Integer hashCode;
|
||||
private BlockSettings settings;
|
||||
private BlockEntityType<? extends BlockEntity> blockEntityType;
|
||||
@Nullable
|
||||
private BlockEntityRendererConfig rendererConfig;
|
||||
|
||||
ImmutableBlockState(
|
||||
Holder<CustomBlock> owner,
|
||||
@@ -66,6 +69,11 @@ public final class ImmutableBlockState extends BlockStateHolder {
|
||||
return this == EmptyBlock.STATE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BlockEntityRendererConfig entityRenderer() {
|
||||
return this.rendererConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -85,6 +93,10 @@ public final class ImmutableBlockState extends BlockStateHolder {
|
||||
return this.blockEntityType != null;
|
||||
}
|
||||
|
||||
public boolean hasBlockEntityRenderer() {
|
||||
return this.rendererConfig != null;
|
||||
}
|
||||
|
||||
public BlockStateWrapper customBlockState() {
|
||||
return this.customBlockState;
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
public final class BlockEntityTypeKeys {
|
||||
private BlockEntityTypeKeys() {}
|
||||
|
||||
public static final Key UNSAFE_COMPOSITE = Key.of("craftengine:unsafe_composite");
|
||||
public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.momirealms.craftengine.core.block.entity.render;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
|
||||
public abstract class BlockEntityRenderer {
|
||||
private final int entityId;
|
||||
|
||||
public BlockEntityRenderer(int entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public int entityId() {
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
public abstract void spawn();
|
||||
|
||||
public abstract void despawn();
|
||||
|
||||
public abstract void spawn(Player player);
|
||||
|
||||
public abstract void despawn(Player player);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package net.momirealms.craftengine.core.block.entity.render;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
|
||||
public class BlockEntityRendererConfig {
|
||||
private final float yRot;
|
||||
private final float xRot;
|
||||
private final ItemDisplayContext displayContext;
|
||||
private final Item<?> item;
|
||||
private final float scale;
|
||||
|
||||
public BlockEntityRendererConfig(ItemDisplayContext displayContext,
|
||||
float yRot,
|
||||
float xRot,
|
||||
Item<?> item,
|
||||
float scale) {
|
||||
this.displayContext = displayContext;
|
||||
this.yRot = yRot;
|
||||
this.xRot = xRot;
|
||||
this.item = item;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public ItemDisplayContext displayContext() {
|
||||
return displayContext;
|
||||
}
|
||||
|
||||
public Item<?> item() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public float xRot() {
|
||||
return xRot;
|
||||
}
|
||||
|
||||
public float yRot() {
|
||||
return yRot;
|
||||
}
|
||||
|
||||
public float scale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private ItemDisplayContext displayContext = ItemDisplayContext.NONE;
|
||||
private Item<?> item;
|
||||
private float xRot;
|
||||
private float yRot;
|
||||
private float scale = 1f;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder displayContext(ItemDisplayContext displayContext) {
|
||||
this.displayContext = displayContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder item(Item<?> item) {
|
||||
this.item = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder xRot(float xRot) {
|
||||
this.xRot = xRot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder yRot(float yRot) {
|
||||
this.yRot = yRot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder scale(float scale) {
|
||||
this.scale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockEntityRendererConfig build() {
|
||||
return new BlockEntityRendererConfig(this.displayContext, this.yRot, this.xRot, this.item, this.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -4,6 +4,8 @@ import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTabl
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRenderer;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRendererConfig;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.TickingBlockEntity;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
@@ -110,6 +112,11 @@ public abstract class CEWorld {
|
||||
return getChunkAtIfLoaded(ChunkPos.asLong(x, z));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CEChunk getChunkAtIfLoaded(ChunkPos chunkPos) {
|
||||
return getChunkAtIfLoaded(chunkPos.longKey);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ImmutableBlockState getBlockStateAtIfLoaded(int x, int y, int z) {
|
||||
CEChunk chunk = getChunkAtIfLoaded(x >> 4, z >> 4);
|
||||
@@ -208,4 +215,6 @@ public abstract class CEWorld {
|
||||
this.tickingBlockEntities.removeAll(toRemove);
|
||||
this.isTickingBlockEntities = false;
|
||||
}
|
||||
|
||||
public abstract BlockEntityRenderer createBlockEntityRenderer(BlockEntityRendererConfig config, BlockPos pos);
|
||||
}
|
||||
|
||||
@@ -4,15 +4,20 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.momirealms.craftengine.core.block.EmptyBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRenderer;
|
||||
import net.momirealms.craftengine.core.block.entity.render.BlockEntityRendererConfig;
|
||||
import net.momirealms.craftengine.core.block.entity.tick.*;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntityRendererSerializer;
|
||||
import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntitySerializer;
|
||||
import net.momirealms.sparrow.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class CEChunk {
|
||||
public final CEWorld world;
|
||||
@@ -20,23 +25,25 @@ public class CEChunk {
|
||||
public final CESection[] sections;
|
||||
public final WorldHeight worldHeightAccessor;
|
||||
public final Map<BlockPos, BlockEntity> blockEntities;
|
||||
public final Map<BlockPos, BlockEntityRenderer> blockEntityRenderers;
|
||||
private final ReentrantReadWriteLock renderLock = new ReentrantReadWriteLock();
|
||||
private volatile boolean dirty;
|
||||
private volatile boolean loaded;
|
||||
protected final Map<BlockPos, ReplaceableTickingBlockEntity> tickingBlockEntitiesByPos = new HashMap<>();
|
||||
protected final Map<BlockPos, ReplaceableTickingBlockEntity> tickingBlockEntitiesByPos = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
|
||||
public CEChunk(CEWorld world, ChunkPos chunkPos) {
|
||||
this.world = world;
|
||||
this.chunkPos = chunkPos;
|
||||
this.worldHeightAccessor = world.worldHeight();
|
||||
this.sections = new CESection[this.worldHeightAccessor.getSectionsCount()];
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(16, 0.5f);
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.blockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
this.fillEmptySection();
|
||||
}
|
||||
|
||||
public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, ListTag blockEntitiesTag) {
|
||||
public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, @Nullable ListTag blockEntitiesTag, @Nullable ListTag itemDisplayBlockRenders) {
|
||||
this.world = world;
|
||||
this.chunkPos = chunkPos;
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(Math.max(blockEntitiesTag.size(), 16), 0.5f);
|
||||
this.worldHeightAccessor = world.worldHeight();
|
||||
int sectionCount = this.worldHeightAccessor.getSectionsCount();
|
||||
this.sections = new CESection[sectionCount];
|
||||
@@ -49,9 +56,75 @@ public class CEChunk {
|
||||
}
|
||||
}
|
||||
this.fillEmptySection();
|
||||
List<BlockEntity> blockEntities = DefaultBlockEntitySerializer.deserialize(this, blockEntitiesTag);
|
||||
for (BlockEntity blockEntity : blockEntities) {
|
||||
this.setBlockEntity(blockEntity);
|
||||
if (blockEntitiesTag != null) {
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(Math.max(blockEntitiesTag.size(), 10), 0.5f);
|
||||
List<BlockEntity> blockEntities = DefaultBlockEntitySerializer.deserialize(this, blockEntitiesTag);
|
||||
for (BlockEntity blockEntity : blockEntities) {
|
||||
this.setBlockEntity(blockEntity);
|
||||
}
|
||||
} else {
|
||||
this.blockEntities = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
}
|
||||
if (itemDisplayBlockRenders != null) {
|
||||
this.blockEntityRenderers = new Object2ObjectOpenHashMap<>(Math.max(itemDisplayBlockRenders.size(), 10), 0.5f);
|
||||
List<BlockPos> blockEntityRendererPoses = DefaultBlockEntityRendererSerializer.deserialize(this.chunkPos, itemDisplayBlockRenders);
|
||||
for (BlockPos pos : blockEntityRendererPoses) {
|
||||
this.addBlockEntityRenderer(pos);
|
||||
}
|
||||
} else {
|
||||
this.blockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public void spawnBlockEntities(Player player) {
|
||||
try {
|
||||
this.renderLock.readLock().lock();
|
||||
for (BlockEntityRenderer renderer : this.blockEntityRenderers.values()) {
|
||||
renderer.spawn(player);
|
||||
}
|
||||
} finally {
|
||||
this.renderLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void despawnBlockEntities(Player player) {
|
||||
try {
|
||||
this.renderLock.readLock().lock();
|
||||
for (BlockEntityRenderer renderer : this.blockEntityRenderers.values()) {
|
||||
renderer.despawn(player);
|
||||
}
|
||||
} finally {
|
||||
this.renderLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void addBlockEntityRenderer(BlockPos pos) {
|
||||
this.addBlockEntityRenderer(pos, this.getBlockState(pos));
|
||||
}
|
||||
|
||||
public void addBlockEntityRenderer(BlockPos pos, ImmutableBlockState state) {
|
||||
BlockEntityRendererConfig config = state.entityRenderer();
|
||||
if (config != null) {
|
||||
BlockEntityRenderer renderer = this.world.createBlockEntityRenderer(config, pos);
|
||||
renderer.spawn();
|
||||
try {
|
||||
this.renderLock.writeLock().lock();
|
||||
this.blockEntityRenderers.put(pos, renderer);
|
||||
} finally {
|
||||
this.renderLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeBlockEntityRenderer(BlockPos pos) {
|
||||
try {
|
||||
this.renderLock.writeLock().lock();
|
||||
BlockEntityRenderer removed = this.blockEntityRenderers.remove(pos);
|
||||
if (removed != null) {
|
||||
removed.despawn();
|
||||
}
|
||||
} finally {
|
||||
this.renderLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +225,17 @@ public class CEChunk {
|
||||
return Objects.requireNonNull(blockState.behavior().getEntityBehavior()).createBlockEntity(pos, blockState);
|
||||
}
|
||||
|
||||
public Map<BlockPos, BlockEntity> blockEntities() {
|
||||
return Collections.unmodifiableMap(this.blockEntities);
|
||||
public Collection<BlockEntity> blockEntities() {
|
||||
return Collections.unmodifiableCollection(this.blockEntities.values());
|
||||
}
|
||||
|
||||
public List<BlockPos> blockEntityRenderers() {
|
||||
try {
|
||||
this.renderLock.readLock().lock();
|
||||
return new ArrayList<>(this.blockEntityRenderers.keySet());
|
||||
} finally {
|
||||
this.renderLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dirty() {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.momirealms.craftengine.core.world.chunk.serialization;
|
||||
|
||||
import net.momirealms.craftengine.core.block.entity.BlockEntity;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.ListTag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class DefaultBlockEntityRendererSerializer {
|
||||
|
||||
public static List<BlockPos> deserialize(ChunkPos chunkPos, ListTag blockEntitiesTag) {
|
||||
List<BlockPos> blockEntities = new ArrayList<>(blockEntitiesTag.size());
|
||||
for (int i = 0; i < blockEntitiesTag.size(); i++) {
|
||||
CompoundTag tag = blockEntitiesTag.getCompound(i);
|
||||
BlockPos blockPos = BlockEntity.readPosAndVerify(tag, chunkPos);
|
||||
blockEntities.add(blockPos);
|
||||
}
|
||||
return blockEntities;
|
||||
}
|
||||
|
||||
public static ListTag serialize(List<BlockPos> poses) {
|
||||
ListTag listTag = new ListTag();
|
||||
for (BlockPos pos : poses) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("x", pos.x());
|
||||
tag.putInt("y", pos.y());
|
||||
tag.putInt("z", pos.z());
|
||||
listTag.add(tag);
|
||||
}
|
||||
return listTag;
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,14 @@ import net.momirealms.sparrow.nbt.CompoundTag;
|
||||
import net.momirealms.sparrow.nbt.ListTag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class DefaultBlockEntitySerializer {
|
||||
|
||||
public static ListTag serialize(Map<BlockPos, BlockEntity> tiles) {
|
||||
public static ListTag serialize(Collection<BlockEntity> entities) {
|
||||
ListTag result = new ListTag();
|
||||
for (Map.Entry<BlockPos, BlockEntity> entry : tiles.entrySet()) {
|
||||
BlockEntity entity = entry.getValue();
|
||||
for (BlockEntity entity : entities) {
|
||||
if (entity.isValid()) {
|
||||
result.add(entity.saveAsTag());
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import net.momirealms.sparrow.nbt.ListTag;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class DefaultChunkSerializer {
|
||||
|
||||
@Nullable
|
||||
@@ -28,7 +26,14 @@ public final class DefaultChunkSerializer {
|
||||
if (sections.isEmpty()) return null;
|
||||
CompoundTag chunkNbt = new CompoundTag();
|
||||
chunkNbt.put("sections", sections);
|
||||
chunkNbt.put("block_entities", DefaultBlockEntitySerializer.serialize(chunk.blockEntities()));
|
||||
ListTag blockEntities = DefaultBlockEntitySerializer.serialize(chunk.blockEntities());
|
||||
if (!blockEntities.isEmpty()) {
|
||||
chunkNbt.put("block_entities", blockEntities);
|
||||
}
|
||||
ListTag blockEntityRenders = DefaultBlockEntityRendererSerializer.serialize(chunk.blockEntityRenderers());
|
||||
if (!blockEntityRenders.isEmpty()) {
|
||||
chunkNbt.put("block_entity_renders", blockEntityRenders);
|
||||
}
|
||||
return chunkNbt;
|
||||
}
|
||||
|
||||
@@ -46,7 +51,8 @@ public final class DefaultChunkSerializer {
|
||||
}
|
||||
}
|
||||
}
|
||||
ListTag blockEntities = Optional.ofNullable(chunkNbt.getList("block_entities")).orElse(new ListTag());
|
||||
return new CEChunk(world, pos, sectionArray, blockEntities);
|
||||
ListTag blockEntities = chunkNbt.getList("block_entities");
|
||||
ListTag itemDisplayBlockRenders = chunkNbt.getList("block_entity_renderers");
|
||||
return new CEChunk(world, pos, sectionArray, blockEntities, itemDisplayBlockRenders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.momirealms.craftengine.core.world.collision;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.MCUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.EntityHitResult;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
|
||||
Reference in New Issue
Block a user