added pipe covering

This commit is contained in:
Ell 2020-10-17 00:58:31 +02:00
parent cd1c508b6a
commit ff5368b108
8 changed files with 158 additions and 40 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

View file

@ -18,6 +18,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.text.*;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.INBTSerializable;
@ -33,7 +34,7 @@ import java.util.stream.Stream;
public final class Utility {
public static <T extends TileEntity> T getTileEntity(Class<T> type, World world, BlockPos pos) {
public static <T extends TileEntity> T getTileEntity(Class<T> type, IBlockReader world, BlockPos pos) {
TileEntity tile = world.getTileEntity(pos);
return type.isInstance(tile) ? (T) tile : null;
}
@ -115,7 +116,7 @@ public final class Utility {
public static void sendTileEntityToClients(TileEntity tile) {
ServerWorld world = (ServerWorld) tile.getWorld();
Stream<ServerPlayerEntity> entities = world.getChunkProvider().chunkManager.getTrackingPlayers(new ChunkPos(tile.getPos()), false);
SUpdateTileEntityPacket packet = tile.getUpdatePacket();
SUpdateTileEntityPacket packet = new SUpdateTileEntityPacket(tile.getPos(), -1, tile.write(new CompoundNBT()));
entities.forEach(e -> e.connection.sendPacket(packet));
}

View file

@ -1,13 +1,20 @@
package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.pipe.PipeBlock;
import de.ellpeck.prettypipes.pipe.ConnectionType;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.loot.LootContext;
import net.minecraft.state.EnumProperty;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
@ -16,11 +23,15 @@ import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import java.util.List;
import java.util.Map;
public class WrenchItem extends Item {
public WrenchItem() {
super(new Item.Properties().maxStackSize(1).group(Registry.GROUP));
}
@ -29,20 +40,54 @@ public class WrenchItem extends Item {
public ActionResultType onItemUse(ItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos();
PlayerEntity player = context.getPlayer();
BlockState state = world.getBlockState(pos);
if (!(state.getBlock() instanceof PipeBlock))
return ActionResultType.PASS;
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos);
if (tile == null)
return ActionResultType.FAIL;
if (context.getPlayer().isSneaking()) {
if (player.isSneaking()) {
if (!world.isRemote) {
Block.spawnDrops(state, world, pos, world.getTileEntity(pos), null, ItemStack.EMPTY);
if (tile.cover != null) {
// remove the cover
List<ItemStack> drops = Block.getDrops(tile.cover, (ServerWorld) world, pos, null, player, player.getHeldItem(context.getHand()));
for (ItemStack drop : drops)
Block.spawnAsEntity(world, pos, drop);
tile.cover = null;
Utility.sendTileEntityToClients(tile);
} else {
// remove the pipe
Block.spawnDrops(state, world, pos, tile, null, ItemStack.EMPTY);
world.removeBlock(pos, false);
}
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_REMOVE_ITEM, SoundCategory.PLAYERS, 1, 1);
world.removeBlock(pos, false);
}
return ActionResultType.SUCCESS;
return ActionResultType.func_233537_a_(world.isRemote);
}
// Blocking
// placing covers
if (tile.cover == null) {
ItemStack offhand = player.getHeldItemOffhand();
if (offhand.getItem() instanceof BlockItem) {
if (!world.isRemote) {
BlockItemUseContext blockContext = new BlockItemUseContext(context);
Block block = ((BlockItem) offhand.getItem()).getBlock();
BlockState cover = block.getStateForPlacement(blockContext);
if (cover != null && !block.hasTileEntity(cover)) {
tile.cover = cover;
Utility.sendTileEntityToClients(tile);
offhand.shrink(1);
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.PLAYERS, 1, 1);
}
}
return ActionResultType.func_233537_a_(world.isRemote);
}
}
// disabling directions
for (Map.Entry<Direction, VoxelShape> entry : PipeBlock.DIR_SHAPES.entrySet()) {
AxisAlignedBB box = entry.getValue().getBoundingBox().offset(pos).grow(0.001F);
if (!box.contains(context.getHitVec()))
@ -66,8 +111,28 @@ public class WrenchItem extends Item {
PipeBlock.onStateChanged(world, pos, newState);
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ROTATE_ITEM, SoundCategory.PLAYERS, 1, 1);
}
return ActionResultType.SUCCESS;
return ActionResultType.func_233537_a_(world.isRemote);
}
return ActionResultType.PASS;
}
@Override
public void addInformation(ItemStack stack, World worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn) {
Utility.addTooltip(this.getRegistryName().getPath(), tooltip);
}
@Override
public boolean isEnchantable(ItemStack stack) {
return true;
}
@Override
public int getItemEnchantability(ItemStack stack) {
return 1;
}
@Override
public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) {
return enchantment == Enchantments.SILK_TOUCH;
}
}

View file

@ -24,6 +24,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
@ -34,6 +35,7 @@ import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.HashMap;
@ -42,7 +44,7 @@ import java.util.Map;
public class PipeBlock extends ContainerBlock implements IPipeConnectable {
public static final Map<Direction, EnumProperty<ConnectionType>> DIRECTIONS = new HashMap<>();
private static final Map<BlockState, VoxelShape> SHAPE_CACHE = new HashMap<>();
private static final Map<Pair<BlockState, BlockState>, VoxelShape> SHAPE_CACHE = new HashMap<>();
private static final VoxelShape CENTER_SHAPE = makeCuboidShape(5, 5, 5, 11, 11, 11);
public static final Map<Direction, VoxelShape> DIR_SHAPES = ImmutableMap.<Direction, VoxelShape>builder()
.put(Direction.UP, makeCuboidShape(5, 10, 5, 11, 16, 11))
@ -131,16 +133,29 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
@Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
VoxelShape shape = SHAPE_CACHE.get(state);
if (shape != null)
return shape;
shape = CENTER_SHAPE;
for (Map.Entry<Direction, EnumProperty<ConnectionType>> entry : DIRECTIONS.entrySet()) {
if (state.get(entry.getValue()).isConnected())
shape = VoxelShapes.or(shape, DIR_SHAPES.get(entry.getKey()));
VoxelShape coverShape = null;
BlockState cover = null;
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
if (tile != null && tile.cover != null) {
cover = tile.cover;
// try catch since the block might expect to find itself at the position
try {
coverShape = cover.getShape(worldIn, pos, context);
} catch (Exception ignored) {
}
}
Pair<BlockState, BlockState> key = Pair.of(state, cover);
VoxelShape shape = SHAPE_CACHE.get(key);
if (shape == null) {
shape = CENTER_SHAPE;
for (Map.Entry<Direction, EnumProperty<ConnectionType>> entry : DIRECTIONS.entrySet()) {
if (state.get(entry.getValue()).isConnected())
shape = VoxelShapes.or(shape, DIR_SHAPES.get(entry.getKey()));
}
if (coverShape != null)
shape = VoxelShapes.or(shape, coverShape);
SHAPE_CACHE.put(key, shape);
}
SHAPE_CACHE.put(state, shape);
return shape;
}

View file

@ -1,17 +1,22 @@
package de.ellpeck.prettypipes.pipe;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.network.PipeItem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import java.util.Random;
@ -24,17 +29,30 @@ public class PipeRenderer extends TileEntityRenderer<PipeTileEntity> {
}
@Override
public void render(PipeTileEntity tile, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer iRenderTypeBuffer, int k, int i1) {
if (tile.getItems().isEmpty())
return;
matrixStack.push();
BlockPos tilePos = tile.getPos();
matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ());
for (PipeItem item : tile.getItems()) {
public void render(PipeTileEntity tile, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int light, int overlay) {
if (!tile.getItems().isEmpty()) {
matrixStack.push();
item.render(tile, matrixStack, this.random, partialTicks, k, i1, iRenderTypeBuffer);
BlockPos tilePos = tile.getPos();
matrixStack.translate(-tilePos.getX(), -tilePos.getY(), -tilePos.getZ());
for (PipeItem item : tile.getItems()) {
matrixStack.push();
item.render(tile, matrixStack, this.random, partialTicks, light, overlay, buffer);
matrixStack.pop();
}
matrixStack.pop();
}
if (tile.cover != null) {
matrixStack.push();
BlockModelRenderer.enableCache();
for (RenderType layer : RenderType.getBlockRenderTypes()) {
if (!RenderTypeLookup.canRenderInLayer(tile.cover, layer))
continue;
ForgeHooksClient.setRenderLayer(layer);
Minecraft.getInstance().getBlockRendererDispatcher().renderBlock(tile.cover, matrixStack, buffer, light, overlay, EmptyModelData.INSTANCE);
}
ForgeHooksClient.setRenderLayer(null);
BlockModelRenderer.disableCache();
matrixStack.pop();
}
matrixStack.pop();
}
}

View file

@ -12,6 +12,7 @@ import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
import de.ellpeck.prettypipes.pressurizer.PressurizerTileEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ChestBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
@ -21,15 +22,21 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
import net.minecraft.profiler.IProfiler;
import net.minecraft.tileentity.ChestTileEntity;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
@ -66,6 +73,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public final Queue<NetworkLock> craftIngredientRequests = new LinkedList<>();
public final List<Pair<BlockPos, ItemStack>> craftResultRequests = new ArrayList<>();
public PressurizerTileEntity pressurizer;
public BlockState cover;
public int moduleDropCheck;
protected List<PipeItem> items;
private int lastItemAmount;
@ -84,6 +92,8 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
compound.put("modules", this.modules.serializeNBT());
compound.putInt("module_drop_check", this.moduleDropCheck);
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests));
if (this.cover != null)
compound.put("cover", NBTUtil.writeBlockState(this.cover));
ListNBT results = new ListNBT();
for (Pair<BlockPos, ItemStack> triple : this.craftResultRequests) {
CompoundNBT nbt = new CompoundNBT();
@ -99,6 +109,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public void read(BlockState state, CompoundNBT compound) {
this.modules.deserializeNBT(compound.getCompound("modules"));
this.moduleDropCheck = compound.getInt("module_drop_check");
this.cover = compound.contains("cover") ? NBTUtil.readBlockState(compound.getCompound("cover")) : null;
this.craftIngredientRequests.clear();
this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
this.craftResultRequests.clear();
@ -128,6 +139,11 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
items.addAll(Utility.deserializeAll(nbt.getList("items", NBT.TAG_COMPOUND), PipeItem::load));
}
@Override
public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
this.read(this.getBlockState(), pkt.getNbtCompound());
}
@Override
public void tick() {
// invalidate our pressurizer reference if it was removed
@ -355,4 +371,11 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new MainPipeContainer(Registry.pipeContainer, window, player, PipeTileEntity.this.pos);
}
@Override
@OnlyIn(Dist.CLIENT)
public AxisAlignedBB getRenderBoundingBox() {
// our render bounding box should always be the full block in case we're covered
return new AxisAlignedBB(this.pos);
}
}

View file

@ -78,11 +78,6 @@ public class PressurizerTileEntity extends TileEntity implements INamedContainer
this.read(state, tag);
}
@Override
public SUpdateTileEntityPacket getUpdatePacket() {
return new SUpdateTileEntityPacket(this.pos, -1, this.write(new CompoundNBT()));
}
@Override
public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
this.read(this.getBlockState(), pkt.getNbtCompound());

View file

@ -1,5 +1,6 @@
{
"item.prettypipes.wrench": "Pipe Wrench",
"info.prettypipes.wrench": "Allows modifying pipe connections\nPlaces blocks in offhand as covers\nSneak to remove cover or pipe",
"item.prettypipes.blank_module": "Blank Module",
"item.prettypipes.pipe_frame": "Pipe Frame",
"info.prettypipes.pipe_frame": "Attach to a pipe or pipe-adjacent block\nShows amount of an item in the pipe's network",