package de.ellpeck.prettypipes.entities; import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.network.NetworkLocation; import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.pipe.PipeBlock; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.item.ItemFrameEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.FilledMapItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.network.IPacket; import net.minecraft.network.PacketBuffer; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.GameRules; import net.minecraft.world.World; import net.minecraft.world.storage.MapData; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.network.NetworkHooks; import javax.annotation.Nullable; import java.util.List; public class PipeFrameEntity extends ItemFrameEntity implements IEntityAdditionalSpawnData { private static final DataParameter AMOUNT = EntityDataManager.createKey(PipeFrameEntity.class, DataSerializers.VARINT); public PipeFrameEntity(EntityType type, World world) { super(type, world); } public PipeFrameEntity(EntityType type, World world, BlockPos pos, Direction dir) { this(type, world); this.hangingPosition = pos; this.updateFacingWithBoundingBox(dir); } @Override protected void registerData() { super.registerData(); this.dataManager.register(AMOUNT, -1); } @Override public void tick() { super.tick(); if (this.world.isRemote) return; if (this.ticksExisted % 40 != 0) return; PipeNetwork network = PipeNetwork.get(this.world); BlockPos attached = getAttachedPipe(this.world, this.hangingPosition, this.facingDirection); if (attached != null) { BlockPos node = network.getNodeFromPipe(attached); if (node != null) { ItemStack stack = this.getDisplayedItem(); if (!stack.isEmpty()) { List items = network.getOrderedNetworkItems(node); int amount = items.stream().mapToInt(i -> i.getItemAmount(this.world, stack)).sum(); this.dataManager.set(AMOUNT, amount); return; } } } this.dataManager.set(AMOUNT, -1); } @Override public boolean onValidSurface() { return super.onValidSurface() && canPlace(this.world, this.hangingPosition, this.facingDirection); } private static BlockPos getAttachedPipe(World world, BlockPos pos, Direction direction) { for (int i = 1; i <= 2; i++) { BlockPos offset = pos.offset(direction.getOpposite(), i); BlockState state = world.getBlockState(offset); if (state.getBlock() instanceof PipeBlock) return offset; } return null; } public static boolean canPlace(World world, BlockPos pos, Direction direction) { return getAttachedPipe(world, pos, direction) != null; } public int getAmount() { return this.dataManager.get(AMOUNT); } @Override public boolean attackEntityFrom(DamageSource source, float amount) { if (this.isInvulnerableTo(source)) { return false; } else if (!source.isExplosion() && !this.getDisplayedItem().isEmpty()) { if (!this.world.isRemote) { this.dropItemOrSelf(source.getTrueSource(), false); this.playSound(SoundEvents.ENTITY_ITEM_FRAME_REMOVE_ITEM, 1.0F, 1.0F); } return true; } else { return super.attackEntityFrom(source, amount); } } @Override public void onBroken(@Nullable Entity brokenEntity) { this.playSound(SoundEvents.ENTITY_ITEM_FRAME_BREAK, 1.0F, 1.0F); this.dropItemOrSelf(brokenEntity, true); } private void dropItemOrSelf(@Nullable Entity entityIn, boolean b) { if (!this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { if (entityIn == null) this.getDisplayedItem().setAttachedEntity(null); } else { ItemStack itemstack = this.getDisplayedItem(); this.setDisplayedItem(ItemStack.EMPTY); if (entityIn instanceof PlayerEntity) { PlayerEntity playerentity = (PlayerEntity) entityIn; if (playerentity.abilities.isCreativeMode) { itemstack.setAttachedEntity(null); return; } } if (b) this.entityDropItem(Registry.pipeFrameItem); if (!itemstack.isEmpty()) { itemstack = itemstack.copy(); itemstack.setAttachedEntity(null); this.entityDropItem(itemstack); } } } @Override public ActionResultType processInitialInteract(PlayerEntity player, Hand hand) { if (this.getDisplayedItem().isEmpty()) return super.processInitialInteract(player, hand); return ActionResultType.FAIL; } @Override public ItemStack getPickedResult(RayTraceResult target) { return new ItemStack(Registry.pipeFrameItem); } @Override public IPacket createSpawnPacket() { return NetworkHooks.getEntitySpawningPacket(this); } @Override public void writeSpawnData(PacketBuffer buffer) { buffer.writeBlockPos(this.hangingPosition); buffer.writeInt(this.facingDirection.getIndex()); } @Override public void readSpawnData(PacketBuffer additionalData) { this.hangingPosition = additionalData.readBlockPos(); this.updateFacingWithBoundingBox(Direction.values()[additionalData.readInt()]); } }