ReFramed/src/main/java/io/github/cottonmc/templates/block/TemplateEntity.java

158 lines
4.6 KiB
Java
Raw Normal View History

package io.github.cottonmc.templates.block;
import io.github.cottonmc.templates.Templates;
import io.github.cottonmc.templates.api.ThemeableBlockEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
2023-06-15 09:08:20 +02:00
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtHelper;
2023-06-15 10:24:11 +02:00
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
2023-06-15 09:08:20 +02:00
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld;
2023-06-15 09:08:20 +02:00
import net.minecraft.util.math.BlockPos;
2023-06-15 10:24:11 +02:00
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class TemplateEntity extends BlockEntity implements ThemeableBlockEntity {
protected BlockState renderedState = Blocks.AIR.getDefaultState();
2023-07-03 09:35:07 +02:00
//Whether the player has manually spent a redstone/glowstone item to upgrade the template.
//It's possible to get templates that, e.g. glow, without manually spending a glowstone on them
//(put a froglight in a template!) Same for redstone activation. We need to separately store
//whether a redstone/glowstone should be refunded when the player breaks the template, and wasting a
//blockstate for it is a little silly, so, here you go.
protected boolean spentGlowstoneDust = false;
protected boolean spentRedstoneTorch = false;
2023-07-06 05:40:12 +02:00
protected boolean spentPoppedChorus = false;
2023-06-15 07:59:48 +02:00
2023-07-08 08:29:22 +02:00
protected boolean emitsRedstone;
protected boolean isSolid = true;
public TemplateEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
2023-06-15 09:08:20 +02:00
super(type, pos, state);
}
2023-06-15 07:59:48 +02:00
@Override
2023-06-15 09:08:20 +02:00
public void readNbt(NbtCompound tag) {
super.readNbt(tag);
BlockState lastRenderedState = renderedState;
2023-06-15 09:08:20 +02:00
renderedState = NbtHelper.toBlockState(Registries.BLOCK.getReadOnlyWrapper(), tag.getCompound("BlockState"));
2023-07-08 08:29:22 +02:00
spentGlowstoneDust = tag.getBoolean("spentglow");
spentRedstoneTorch = tag.getBoolean("spentredst");
spentPoppedChorus = tag.getBoolean("spentchor");
emitsRedstone = tag.getBoolean("emitsredst");
isSolid = !tag.contains("solid") || tag.getBoolean("solid"); //default to "true" if it's nonexistent
2023-07-03 09:35:07 +02:00
//Force a chunk remesh on the client if the displayed blockstate has changed
if(world != null && world.isClient && !Objects.equals(lastRenderedState, renderedState)) {
Templates.chunkRerenderProxy.accept(world, pos);
}
}
2023-06-15 07:59:48 +02:00
@Override
2023-06-15 09:08:20 +02:00
public void writeNbt(NbtCompound tag) {
super.writeNbt(tag);
tag.put("BlockState", NbtHelper.fromBlockState(renderedState));
2023-07-08 08:29:22 +02:00
tag.putBoolean("spentglow", spentGlowstoneDust);
tag.putBoolean("spentredst", spentRedstoneTorch);
tag.putBoolean("spentchor", spentPoppedChorus);
tag.putBoolean("emitsredst", emitsRedstone);
tag.putBoolean("solid", isSolid);
}
2023-06-15 07:59:48 +02:00
2023-06-15 10:24:11 +02:00
@Nullable
@Override
2023-06-15 10:24:11 +02:00
public Packet<ClientPlayPacketListener> toUpdatePacket() {
return BlockEntityUpdateS2CPacket.create(this);
}
@Override
public NbtCompound toInitialChunkDataNbt() {
2023-07-03 09:35:07 +02:00
//TERRIBLE yarn name, this is "getUpdateTag", it's the nbt that will be sent to clients
2023-07-08 08:29:22 +02:00
//and it just calls "writeNbt"
2023-06-15 10:24:11 +02:00
return createNbt();
}
2023-06-15 07:59:48 +02:00
@Override
public BlockState getRenderAttachmentData() {
return renderedState;
}
2023-06-15 07:59:48 +02:00
2023-07-08 08:29:22 +02:00
private void dispatch() {
if(world instanceof ServerWorld sworld) sworld.getChunkManager().markForUpdate(pos);
}
2023-06-15 10:24:11 +02:00
public void setRenderedState(BlockState newState) {
2023-07-03 09:35:07 +02:00
if(!Objects.equals(renderedState, newState)) {
renderedState = newState;
markDirty();
2023-07-08 08:29:22 +02:00
dispatch();
2023-07-03 09:35:07 +02:00
}
2023-06-15 10:24:11 +02:00
}
2023-07-03 09:35:07 +02:00
public boolean hasSpentGlowstoneDust() {
return spentGlowstoneDust;
}
2023-06-15 07:59:48 +02:00
2023-07-03 09:35:07 +02:00
public void spentGlowstoneDust() {
spentGlowstoneDust = true;
markDirty();
}
2023-06-15 07:59:48 +02:00
2023-07-03 09:35:07 +02:00
public boolean hasSpentRedstoneTorch() {
return spentRedstoneTorch;
}
2023-06-15 07:59:48 +02:00
2023-07-03 09:35:07 +02:00
public void spentRedstoneTorch() {
spentRedstoneTorch = true;
markDirty();
}
2023-07-06 05:40:12 +02:00
public boolean hasSpentPoppedChorus() {
return spentPoppedChorus;
}
public void spentPoppedChorus() {
spentPoppedChorus = true;
markDirty();
}
2023-07-08 08:29:22 +02:00
public boolean emitsRedstone() {
return emitsRedstone;
}
public void setEmitsRedstone(boolean emitsRedstone) {
if(this.emitsRedstone != emitsRedstone) {
this.emitsRedstone = emitsRedstone;
markDirty();
if(world != null) world.updateNeighbors(pos, getCachedState().getBlock());
}
}
public boolean isSolid() {
return isSolid;
}
public void setSolidity(boolean isSolid) {
if(this.isSolid != isSolid) {
this.isSolid = isSolid;
markDirty();
//do i need to invalidate any shape caches or something
if(world != null) world.setBlockState(pos, getCachedState());
dispatch();
}
}
}