SimpleMultipart/src/main/java/net/shadowfacts/simplemultipart/container/ContainerBlockEntity.java

198 lines
5.5 KiB
Java
Raw Normal View History

2018-12-20 00:39:10 +00:00
package net.shadowfacts.simplemultipart.container;
2018-12-24 22:16:38 +00:00
import com.google.common.collect.ImmutableSet;
import net.fabricmc.fabric.api.util.NbtType;
2018-12-20 00:39:10 +00:00
import net.fabricmc.fabric.block.entity.ClientSerializable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
2018-12-24 22:16:38 +00:00
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
2018-12-20 00:39:10 +00:00
import net.minecraft.server.world.ServerWorld;
2018-12-25 15:20:44 +00:00
import net.minecraft.util.math.BlockPos;
2018-12-24 22:16:38 +00:00
import net.minecraft.util.shape.VoxelShape;
2018-12-25 15:20:44 +00:00
import net.minecraft.world.loot.context.LootContext;
import net.minecraft.world.loot.context.Parameters;
2018-12-20 00:39:10 +00:00
import net.shadowfacts.simplemultipart.SimpleMultipart;
import net.shadowfacts.simplemultipart.api.MultipartContainer;
2018-12-20 00:39:10 +00:00
import net.shadowfacts.simplemultipart.multipart.MultipartState;
2018-12-25 15:20:44 +00:00
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntity;
import net.shadowfacts.simplemultipart.multipart.entity.MultipartEntityProvider;
2018-12-20 00:39:10 +00:00
import net.shadowfacts.simplemultipart.util.MultipartHelper;
2018-12-25 15:20:44 +00:00
import net.shadowfacts.simplemultipart.api.MultipartView;
2018-12-24 22:16:38 +00:00
import net.shadowfacts.simplemultipart.util.ShapeUtils;
2018-12-20 00:39:10 +00:00
2018-12-24 22:16:38 +00:00
import java.util.*;
2018-12-20 00:39:10 +00:00
/**
* @author shadowfacts
*/
2018-12-25 15:30:46 +00:00
public class ContainerBlockEntity extends BlockEntity implements MultipartContainer, ClientSerializable {
2018-12-20 00:39:10 +00:00
2018-12-25 15:20:44 +00:00
private Set<Entry> parts = new HashSet<>();
2018-12-20 00:39:10 +00:00
2018-12-25 15:30:46 +00:00
public ContainerBlockEntity() {
2018-12-20 00:39:10 +00:00
super(SimpleMultipart.containerBlockEntity);
}
@Override
2018-12-25 15:20:44 +00:00
public Set<MultipartView> getParts() {
2018-12-24 22:16:38 +00:00
return ImmutableSet.copyOf(parts);
2018-12-20 00:39:10 +00:00
}
@Override
2018-12-24 22:16:38 +00:00
public boolean canInsert(MultipartState partState) {
VoxelShape newShape = partState.getBoundingShape(null);
2018-12-25 15:20:44 +00:00
for (Entry e : parts) {
VoxelShape existingShape = e.state.getBoundingShape(e);
2018-12-24 22:16:38 +00:00
if (ShapeUtils.intersect(newShape, existingShape)) {
return false;
}
2018-12-20 00:39:10 +00:00
}
return true;
}
@Override
2018-12-24 22:16:38 +00:00
public void insert(MultipartState partState) {
if (!canInsert(partState)) {
return;
}
2018-12-25 15:20:44 +00:00
MultipartEntity entity = null;
if (partState.getMultipart() instanceof MultipartEntityProvider) {
entity = ((MultipartEntityProvider)partState.getMultipart()).createMultipartEntity(partState, this);
}
parts.add(new Entry(partState, entity));
2018-12-20 00:39:10 +00:00
markDirty();
world.scheduleBlockRender(pos);
}
@Override
2018-12-24 22:16:38 +00:00
public void remove(MultipartState partState) {
2018-12-25 15:20:44 +00:00
parts.removeIf(e -> e.state == partState);
2018-12-20 00:39:10 +00:00
if (parts.isEmpty()) {
world.setBlockState(pos, Blocks.AIR.getDefaultState());
}
}
@Override
2018-12-24 22:16:38 +00:00
public boolean breakPart(MultipartState partState) {
2018-12-25 15:20:44 +00:00
Optional<Entry> entry = parts.stream().filter(e -> e.state == partState).findFirst();
if (!entry.isPresent()) {
return false;
}
2018-12-20 00:39:10 +00:00
if (world instanceof ServerWorld) {
2018-12-25 15:20:44 +00:00
List<ItemStack> drops = getDroppedStacks(entry.get(), (ServerWorld)world, pos);
2018-12-20 00:39:10 +00:00
drops.forEach(stack -> Block.dropStack(world, pos, stack));
// TODO: don't drop if player is creative
}
2018-12-24 22:16:38 +00:00
remove(partState);
2018-12-20 00:39:10 +00:00
world.markDirty(pos, this);
world.scheduleBlockRender(pos);
BlockState blockState = world.getBlockState(pos);
world.updateListeners(pos, blockState, blockState, 3);
return true;
}
2018-12-25 15:30:46 +00:00
@Override
public void schedulePartSave() {
markDirty(); // see yarn #360
}
private List<ItemStack> getDroppedStacks(ContainerBlockEntity.Entry e, ServerWorld world, BlockPos pos) {
2018-12-25 15:20:44 +00:00
LootContext.Builder builder = new LootContext.Builder(world);
builder.setRandom(world.random);
builder.put(SimpleMultipart.MULTIPART_STATE_PARAMETER, e.state);
builder.put(Parameters.POSITION, pos);
return e.state.getDroppedStacks(e, builder);
}
2018-12-24 22:16:38 +00:00
private ListTag partsToTag() {
ListTag list = new ListTag();
2018-12-25 15:20:44 +00:00
for (Entry e : parts) {
CompoundTag tag = new CompoundTag();
tag.put("part", MultipartHelper.serializeMultipartState(e.state));
if (e.entity != null) {
tag.put("entity", e.entity.toTag(new CompoundTag()));
2018-12-20 00:39:10 +00:00
}
2018-12-25 15:20:44 +00:00
list.add(tag);
}
2018-12-24 22:16:38 +00:00
return list;
2018-12-20 00:39:10 +00:00
}
2018-12-24 22:16:38 +00:00
private void partsFromTag(ListTag list) {
2018-12-20 00:39:10 +00:00
parts.clear();
2018-12-24 22:16:38 +00:00
for (Tag tag : list) {
2018-12-25 15:20:44 +00:00
CompoundTag compound = (CompoundTag)tag;
MultipartState state = MultipartHelper.deserializeMultipartState(compound.getCompound("part"));
MultipartEntity entity = null;
if (state.getMultipart() instanceof MultipartEntityProvider && compound.containsKey("entity", NbtType.COMPOUND)) {
entity = ((MultipartEntityProvider)state.getMultipart()).createMultipartEntity(state, this);
entity.fromTag(compound.getCompound("entity"));
}
parts.add(new Entry(state, entity));
2018-12-20 00:39:10 +00:00
}
}
@Override
public CompoundTag toTag(CompoundTag tag) {
2018-12-24 22:16:38 +00:00
tag.put("parts", partsToTag());
2018-12-20 00:39:10 +00:00
return super.toTag(tag);
}
@Override
public void fromTag(CompoundTag tag) {
super.fromTag(tag);
2018-12-24 22:16:38 +00:00
ListTag list = tag.getList("parts", NbtType.COMPOUND);
partsFromTag(list);
2018-12-20 00:39:10 +00:00
}
@Override
public CompoundTag toClientTag(CompoundTag tag) {
2018-12-24 22:16:38 +00:00
tag.put("parts", partsToTag());
return tag;
2018-12-20 00:39:10 +00:00
}
@Override
public void fromClientTag(CompoundTag tag) {
2018-12-24 22:16:38 +00:00
ListTag list = tag.getList("parts", NbtType.COMPOUND);
partsFromTag(list);
2018-12-20 00:39:10 +00:00
world.scheduleBlockRender(pos);
}
2018-12-25 15:20:44 +00:00
public class Entry implements MultipartView {
public final MultipartState state;
public final MultipartEntity entity;
private Entry(MultipartState state, MultipartEntity entity) {
this.state = state;
this.entity = entity;
}
@Override
2018-12-25 15:30:46 +00:00
public ContainerBlockEntity getContainer() {
return ContainerBlockEntity.this; // TODO: is this bad?
2018-12-25 15:20:44 +00:00
}
@Override
public MultipartState getState() {
return state;
}
@Override
public MultipartEntity getEntity() {
return entity;
}
}
2018-12-20 00:39:10 +00:00
}