mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-01-31 19:16:44 +01:00
Fix bugs and allow for storing bucketed entities in jars
This commit is contained in:
parent
f0b2a8a550
commit
2784627adc
8 changed files with 474 additions and 76 deletions
|
@ -2,18 +2,38 @@ package com.minelittlepony.unicopia.block;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
|
||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
|
||||
import net.minecraft.block.BlockEntityProvider;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.InventoryProvider;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.Bucketable;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.SidedInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.TypedActionResult;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
@ -36,14 +56,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
if (hand == Hand.OFF_HAND) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
if (stack.isEmpty()) {
|
||||
return data.removeItem(world, pos);
|
||||
}
|
||||
|
||||
return data.insertItem(world, pos, player.isCreative() ? stack.copyWithCount(1) : stack.split(1));
|
||||
}).orElse(ActionResult.PASS);
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> data.interact(player, hand)).orElse(ActionResult.PASS);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
@ -51,9 +64,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
|
||||
if (!moved && !state.isOf(newState.getBlock())) {
|
||||
world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).ifPresent(data -> {
|
||||
data.getStacks().forEach(stack -> {
|
||||
dropStack(world, pos, stack);
|
||||
});
|
||||
data.getContents().onDestroyed();
|
||||
});
|
||||
}
|
||||
super.onStateReplaced(state, world, pos, newState, moved);
|
||||
|
@ -66,7 +77,10 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
|
||||
@Override
|
||||
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(data -> Math.min(16, data.getStacks().size())).orElse(0);
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR)
|
||||
.map(TileData::getItems)
|
||||
.map(data -> Math.min(16, data.getStacks().size()))
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
@ -85,34 +99,210 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
|
||||
@Override
|
||||
public SidedInventory getInventory(BlockState state, WorldAccess world, BlockPos pos) {
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).orElse(null);
|
||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(TileData::getItems).orElse(null);
|
||||
}
|
||||
|
||||
public static class TileData extends BlockEntity implements SidedInventory {
|
||||
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
|
||||
private final List<ItemStack> stacks = new ArrayList<>();
|
||||
public static class TileData extends BlockEntity {
|
||||
|
||||
private JarContents contents = new ItemsJarContents(this);
|
||||
|
||||
public TileData(BlockPos pos, BlockState state) {
|
||||
super(UBlockEntities.ITEM_JAR, pos, state);
|
||||
}
|
||||
|
||||
public ActionResult insertItem(World world, BlockPos pos, ItemStack stack) {
|
||||
if (stacks.size() >= size()) {
|
||||
return ActionResult.FAIL;
|
||||
}
|
||||
stacks.add(stack);
|
||||
markDirty();
|
||||
|
||||
return ActionResult.SUCCESS;
|
||||
public ActionResult interact(PlayerEntity player, Hand hand) {
|
||||
TypedActionResult<JarContents> result = contents.interact(player, hand);
|
||||
contents = result.getValue();
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
public ActionResult removeItem(World world, BlockPos pos) {
|
||||
if (stacks.isEmpty()) {
|
||||
return ActionResult.FAIL;
|
||||
public JarContents getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ItemsJarContents getItems() {
|
||||
return getContents() instanceof ItemsJarContents c ? c : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public EntityJarContents getEntity() {
|
||||
return getContents() instanceof EntityJarContents c ? c : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<ClientPlayPacketListener> toUpdatePacket() {
|
||||
return BlockEntityUpdateS2CPacket.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toInitialChunkDataNbt() {
|
||||
return createNbt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
super.markDirty();
|
||||
if (getWorld() instanceof ServerWorld sw) {
|
||||
sw.getChunkManager().markForUpdate(getPos());
|
||||
}
|
||||
dropStack(world, pos, stacks.remove(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNbt(NbtCompound nbt) {
|
||||
if (nbt.contains("items", NbtElement.COMPOUND_TYPE)) {
|
||||
contents = new ItemsJarContents(this);
|
||||
contents.fromNBT(nbt.getCompound("items"));
|
||||
} else if (nbt.contains("entity", NbtElement.COMPOUND_TYPE)) {
|
||||
contents = new EntityJarContents(this);
|
||||
contents.fromNBT(nbt.getCompound("entity"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeNbt(NbtCompound nbt) {
|
||||
var items = getItems();
|
||||
if (items != null) {
|
||||
nbt.put("items", items.toNBT());
|
||||
} else if (getEntity() != null) {
|
||||
nbt.put("entity", getEntity().toNBT());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface JarContents extends NbtSerialisable {
|
||||
TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand);
|
||||
|
||||
void onDestroyed();
|
||||
}
|
||||
|
||||
public static class EntityJarContents implements JarContents {
|
||||
@Nullable
|
||||
private EntityType<?> entityType;
|
||||
@Nullable
|
||||
private Entity renderEntity;
|
||||
|
||||
private final TileData tile;
|
||||
|
||||
public EntityJarContents(TileData tile) {
|
||||
this(tile, null);
|
||||
}
|
||||
|
||||
public EntityJarContents(TileData tile, EntityType<?> entityType) {
|
||||
this.tile = tile;
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getOrCreateEntity() {
|
||||
if (entityType == null && tile.getWorld() != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (renderEntity == null || renderEntity.getType() != entityType) {
|
||||
renderEntity = entityType.create(tile.getWorld());
|
||||
}
|
||||
return renderEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
if (stack.isOf(Items.BUCKET)) {
|
||||
if (getOrCreateEntity() instanceof Bucketable bucketable) {
|
||||
if (!player.isCreative()) {
|
||||
stack.decrement(1);
|
||||
if (stack.isEmpty()) {
|
||||
player.setStackInHand(hand, bucketable.getBucketItem());
|
||||
} else {
|
||||
player.giveItemStack(bucketable.getBucketItem());
|
||||
}
|
||||
}
|
||||
player.playSound(bucketable.getBucketFillSound(), 1, 1);
|
||||
}
|
||||
tile.markDirty();
|
||||
return TypedActionResult.success(new ItemsJarContents(tile));
|
||||
}
|
||||
return TypedActionResult.pass(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed() {
|
||||
tile.getWorld().setBlockState(tile.getPos(), Blocks.WATER.getDefaultState());
|
||||
Entity entity = getOrCreateEntity();
|
||||
if (entity != null) {
|
||||
entity.refreshPositionAfterTeleport(tile.getPos().toCenterPos());
|
||||
tile.getWorld().spawnEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
compound.putString("entity", EntityType.getId(entityType).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
entityType = Registries.ENTITY_TYPE.getOrEmpty(Identifier.tryParse(compound.getString("entity"))).orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ItemsJarContents implements JarContents, SidedInventory {
|
||||
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
|
||||
|
||||
private final TileData tile;
|
||||
private List<ItemStack> stacks = new ArrayList<>();
|
||||
|
||||
public ItemsJarContents(TileData tile) {
|
||||
this.tile = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||
ItemStack handStack = player.getStackInHand(hand);
|
||||
|
||||
if (handStack.isEmpty()) {
|
||||
if (stacks.isEmpty()) {
|
||||
return TypedActionResult.fail(this);
|
||||
}
|
||||
dropStack(tile.getWorld(), tile.getPos(), stacks.remove(0));
|
||||
markDirty();
|
||||
return TypedActionResult.success(this);
|
||||
}
|
||||
|
||||
if (stacks.isEmpty()) {
|
||||
if (handStack.getItem() instanceof MixinEntityBucketItem bucket) {
|
||||
if (!player.isCreative()) {
|
||||
handStack.decrement(1);
|
||||
if (handStack.isEmpty()) {
|
||||
player.setStackInHand(hand, Items.BUCKET.getDefaultStack());
|
||||
} else {
|
||||
player.giveItemStack(Items.BUCKET.getDefaultStack());
|
||||
}
|
||||
}
|
||||
|
||||
player.playSound(bucket.getEmptyingSound(), 1, 1);
|
||||
markDirty();
|
||||
return TypedActionResult.success(new EntityJarContents(tile, bucket.getEntityType()));
|
||||
}
|
||||
}
|
||||
|
||||
if (stacks.size() >= size()) {
|
||||
return TypedActionResult.fail(this);
|
||||
}
|
||||
stacks.add(player.isCreative() ? handStack.copyWithCount(1) : handStack.split(1));
|
||||
markDirty();
|
||||
return ActionResult.SUCCESS;
|
||||
|
||||
return TypedActionResult.success(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed() {
|
||||
stacks.forEach(stack -> {
|
||||
dropStack(tile.getWorld(), tile.getPos(), stack);
|
||||
});
|
||||
}
|
||||
|
||||
public List<ItemStack> getStacks() {
|
||||
|
@ -137,51 +327,42 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
@Override
|
||||
public ItemStack removeStack(int slot, int amount) {
|
||||
if (slot < 0 || slot >= stacks.size()) {
|
||||
try {
|
||||
ItemStack stack = stacks.get(slot);
|
||||
ItemStack removed = stack.split(1);
|
||||
if (stack.isEmpty()) {
|
||||
stacks.remove(slot);
|
||||
}
|
||||
return removed;
|
||||
} finally {
|
||||
markDirty();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
try {
|
||||
ItemStack stack = stacks.get(slot);
|
||||
ItemStack removed = stack.split(1);
|
||||
if (stack.isEmpty()) {
|
||||
stacks.remove(slot);
|
||||
}
|
||||
return removed;
|
||||
} finally {
|
||||
markDirty();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeStack(int slot) {
|
||||
if (slot < 0 || slot >= stacks.size()) {
|
||||
try {
|
||||
return stacks.remove(slot);
|
||||
} finally {
|
||||
markDirty();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
try {
|
||||
return stacks.remove(slot);
|
||||
} finally {
|
||||
markDirty();
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStack(int slot, ItemStack stack) {
|
||||
if (slot >= stacks.size()) {
|
||||
if (stacks.size() >= size()) {
|
||||
dropStack(getWorld(), getPos(), stack);
|
||||
} else {
|
||||
stacks.add(stack);
|
||||
}
|
||||
stacks.add(stack);
|
||||
} else {
|
||||
ItemStack existing = stacks.get(slot);
|
||||
if (!ItemStack.canCombine(existing, stack)) {
|
||||
dropStack(getWorld(), getPos(), stack);
|
||||
} else {
|
||||
existing.setCount(existing.getCount() + stack.split(Math.max(0, existing.getMaxCount() - existing.getCount())).getCount());
|
||||
if (!stack.isEmpty()) {
|
||||
dropStack(getWorld(), getPos(), stack);
|
||||
}
|
||||
}
|
||||
stacks.set(slot, stack);
|
||||
}
|
||||
markDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -202,15 +383,29 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
|||
|
||||
@Override
|
||||
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
|
||||
return (slot >= 0 && slot < size()) && (slot >= stacks.size() || (
|
||||
ItemStack.canCombine(stacks.get(slot), stack)
|
||||
&& (stacks.get(slot).getCount() + stack.getCount()) <= Math.min(stacks.get(slot).getMaxCount(), stack.getMaxCount())
|
||||
));
|
||||
return slot >= 0 && slot < size() && slot >= stacks.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
|
||||
return true;
|
||||
return slot >= 0 && slot < size() && slot < stacks.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
compound.put("items", NbtSerialisable.ITEM_STACK.writeAll(stacks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
stacks = NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE))
|
||||
.limit(size())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
tile.markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,17 @@ import net.minecraft.block.AbstractGlassBlock;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.Waterloggable;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.item.ItemPlacementContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.state.property.BooleanProperty;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
|
@ -22,17 +29,25 @@ import net.minecraft.util.shape.VoxelShape;
|
|||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
import net.minecraft.world.explosion.Explosion;
|
||||
|
||||
public class JarBlock extends AbstractGlassBlock {
|
||||
public class JarBlock extends AbstractGlassBlock implements Waterloggable {
|
||||
private static final VoxelShape SHAPE = VoxelShapes.union(
|
||||
Block.createCuboidShape(4, 0, 4, 12, 12, 12),
|
||||
Block.createCuboidShape(6, 12, 6, 10, 16, 10),
|
||||
Block.createCuboidShape(5, 13, 5, 11, 14, 11)
|
||||
);
|
||||
private static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
|
||||
|
||||
public JarBlock(Settings settings) {
|
||||
super(settings);
|
||||
setDefaultState(getDefaultState().with(WATERLOGGED, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(WATERLOGGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,9 +55,26 @@ public class JarBlock extends AbstractGlassBlock {
|
|||
return SHAPE;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public boolean isSideInvisible(BlockState state, BlockState stateFrom, Direction direction) {
|
||||
return super.isSideInvisible(state, stateFrom, direction);
|
||||
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
|
||||
if (state.get(WATERLOGGED)) {
|
||||
world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
|
||||
}
|
||||
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockState getPlacementState(ItemPlacementContext ctx) {
|
||||
return getDefaultState().with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public FluidState getFluidState(BlockState state) {
|
||||
return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,10 +5,16 @@ import org.joml.Vector3f;
|
|||
import org.joml.Vector4f;
|
||||
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.ColorHelper;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
public class RenderUtil {
|
||||
public static final Vector4f TEMP_VECTOR = new Vector4f();
|
||||
|
@ -25,6 +31,72 @@ public class RenderUtil {
|
|||
new Vertex(1, 0, 0, 1, 1),
|
||||
new Vertex(0, 0, 0, 0, 1)
|
||||
};
|
||||
private static final Vertex[][] CUBE_VERTICES = {
|
||||
new Vertex[] { // down
|
||||
new Vertex(0, 0, 0, 0, 0),
|
||||
new Vertex(1, 0, 0, 1, 0),
|
||||
new Vertex(1, 0, 1, 1, 1),
|
||||
new Vertex(0, 0, 1, 0, 1)
|
||||
},
|
||||
new Vertex[] { //up
|
||||
new Vertex(0, 1, 0, 0, 0),
|
||||
new Vertex(0, 1, 1, 0, 1),
|
||||
new Vertex(1, 1, 1, 1, 1),
|
||||
new Vertex(1, 1, 0, 1, 0)
|
||||
},
|
||||
new Vertex[] { //north
|
||||
new Vertex(0, 0, 0, 0, 0),
|
||||
new Vertex(0, 1, 0, 0, 1),
|
||||
new Vertex(1, 1, 0, 1, 1),
|
||||
new Vertex(1, 0, 0, 1, 0)
|
||||
},
|
||||
new Vertex[] { //south
|
||||
new Vertex(0, 0, 1, 0, 0),
|
||||
new Vertex(1, 0, 1, 1, 0),
|
||||
new Vertex(1, 1, 1, 1, 1),
|
||||
new Vertex(0, 1, 1, 0, 1)
|
||||
},
|
||||
new Vertex[] { //west
|
||||
new Vertex(0, 0, 0, 0, 0),
|
||||
new Vertex(0, 0, 1, 1, 0),
|
||||
new Vertex(0, 1, 1, 1, 1),
|
||||
new Vertex(0, 1, 0, 0, 1)
|
||||
},
|
||||
new Vertex[] { //east
|
||||
new Vertex(1, 0, 0, 0, 0),
|
||||
new Vertex(1, 1, 0, 1, 0),
|
||||
new Vertex(1, 1, 1, 1, 1),
|
||||
new Vertex(1, 0, 1, 0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
public static void renderSpriteCubeFaces(MatrixStack matrices, VertexConsumerProvider provider, Sprite sprite,
|
||||
float width, float height, float length,
|
||||
int color, int light, int overlay,
|
||||
Direction... directions) {
|
||||
float r = ColorHelper.Abgr.getRed(color),
|
||||
g = ColorHelper.Abgr.getGreen(color),
|
||||
b = ColorHelper.Abgr.getBlue(color),
|
||||
a = ColorHelper.Abgr.getAlpha(color);
|
||||
float u0 = sprite.getMinU(), uDelta = sprite.getMaxU() - u0;
|
||||
float v0 = sprite.getMinV(), vDelta = sprite.getMaxV() - v0;
|
||||
RenderLayer layer = RenderLayer.getEntitySolid(sprite.getAtlasId());
|
||||
VertexConsumer buffer = provider.getBuffer(layer);
|
||||
Matrix4f position = matrices.peek().getPositionMatrix();
|
||||
for (Direction direction : directions) {
|
||||
for (Vertex vertex : CUBE_VERTICES[direction.ordinal()]) {
|
||||
Vector4f pos = position.transform(TEMP_VECTOR.set(vertex.position(), 1).mul(width, height, length, 1));
|
||||
buffer.vertex(
|
||||
pos.x, pos.y, pos.z,
|
||||
r, g, b, a,
|
||||
u0 + vertex.texture().x * uDelta,
|
||||
v0 + vertex.texture().y * vDelta,
|
||||
overlay, light,
|
||||
direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
|
||||
renderFace(matrices, te, buffer, r, g, b, a, light, 1, 1);
|
||||
|
|
|
@ -1,29 +1,61 @@
|
|||
package com.minelittlepony.unicopia.client.render.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.minelittlepony.unicopia.block.ItemJarBlock;
|
||||
import com.minelittlepony.unicopia.block.ItemJarBlock.EntityJarContents;
|
||||
import com.minelittlepony.unicopia.block.ItemJarBlock.ItemsJarContents;
|
||||
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||
import com.minelittlepony.unicopia.util.PosHelper;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.color.world.BiomeColors;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.render.item.ItemRenderer;
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.command.argument.EntityAnchorArgumentType.EntityAnchor;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBlock.TileData> {
|
||||
|
||||
private final ItemRenderer itemRenderer;
|
||||
private final EntityRenderDispatcher dispatcher;
|
||||
|
||||
private final Sprite waterSprite;
|
||||
|
||||
public ItemJarBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
|
||||
itemRenderer = ctx.getItemRenderer();
|
||||
dispatcher = ctx.getEntityRenderDispatcher();
|
||||
waterSprite = MinecraftClient.getInstance().getBakedModelManager().getBlockModels().getModel(Blocks.WATER.getDefaultState()).getParticleSprite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(ItemJarBlock.TileData entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||
public void render(ItemJarBlock.TileData data, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||
|
||||
List<ItemStack> stacks = entity.getStacks();
|
||||
ItemsJarContents items = data.getItems();
|
||||
if (items != null) {
|
||||
renderItemStacks(data, items, tickDelta, matrices, vertices, light, overlay);
|
||||
}
|
||||
|
||||
EntityJarContents entity = data.getEntity();
|
||||
if (entity != null) {
|
||||
renderEntity(data, entity, tickDelta, matrices, vertices, light, overlay);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderItemStacks(ItemJarBlock.TileData data, ItemsJarContents items, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||
float itemScale = 0.35F;
|
||||
|
||||
matrices.push();
|
||||
|
@ -31,19 +63,66 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
|
|||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||
matrices.scale(itemScale, itemScale, itemScale);
|
||||
|
||||
Random rng = Random.create(entity.getPos().asLong());
|
||||
Random rng = Random.create(data.getPos().asLong());
|
||||
|
||||
float y = 0;
|
||||
for (ItemStack stack : stacks) {
|
||||
for (ItemStack stack : items.getStacks()) {
|
||||
matrices.push();
|
||||
|
||||
matrices.translate((rng.nextFloat() - 0.5F) * 0.5F, (rng.nextFloat() - 0.5F) * 0.8F, -0.05 + y);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees((rng.nextFloat() * 360) - 180));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees((rng.nextFloat() * 360) - 180));
|
||||
y -= 0.1F;
|
||||
MinecraftClient.getInstance().getItemRenderer().renderItem(stack, ModelTransformationMode.FIXED, light, overlay, matrices, vertices, entity.getWorld(), 0);
|
||||
itemRenderer.renderItem(stack, ModelTransformationMode.FIXED, light, overlay, matrices, vertices, data.getWorld(), 0);
|
||||
matrices.pop();
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
private void renderEntity(ItemJarBlock.TileData data, EntityJarContents entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||
Entity e = entity.getOrCreateEntity();
|
||||
if (e != null) {
|
||||
|
||||
|
||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
||||
int age = player == null ? 0 : player.age;
|
||||
|
||||
float fullTick = age + tickDelta;
|
||||
|
||||
float size = Math.max(e.getWidth(), e.getHeight());
|
||||
float desiredSize = 0.25F;
|
||||
float scale = desiredSize / size;
|
||||
float eyePos = (e.getEyeHeight(e.getPose())) * scale;
|
||||
|
||||
float yaw = 0;
|
||||
if (player != null) {
|
||||
Vec3d center = data.getPos().toCenterPos();
|
||||
Vec3d observerPos = MinecraftClient.getInstance().gameRenderer.getCamera().getPos();
|
||||
e.setPosition(center);
|
||||
e.lookAt(EntityAnchor.FEET, observerPos);
|
||||
}
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(0.5, 0.48 + MathHelper.sin(fullTick / 19F) * 0.02F - eyePos, 0.5);
|
||||
matrices.scale(scale, scale, scale);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(10 * MathHelper.sin(fullTick / 19F)));
|
||||
dispatcher.render(e, 0, 0, 0, yaw * MathHelper.RADIANS_PER_DEGREE, tickDelta, matrices, vertices, light);
|
||||
matrices.pop();
|
||||
}
|
||||
renderFluid(data.getWorld(), data.getPos(), tickDelta, matrices, vertices, light, overlay);
|
||||
}
|
||||
|
||||
private void renderFluid(World world, BlockPos pos, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||
matrices.push();
|
||||
matrices.translate(0.3F, 0, 0.3F);
|
||||
RenderUtil.renderSpriteCubeFaces(
|
||||
matrices,
|
||||
vertices,
|
||||
waterSprite,
|
||||
0.4F, 0.4F, 0.4F,
|
||||
BiomeColors.getWaterColor(world, pos),
|
||||
light, overlay, PosHelper.ALL
|
||||
);
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.minelittlepony.unicopia.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.item.EntityBucketItem;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
|
||||
@Mixin(EntityBucketItem.class)
|
||||
public interface MixinEntityBucketItem {
|
||||
@Accessor
|
||||
EntityType<?> getEntityType();
|
||||
@Accessor
|
||||
SoundEvent getEmptyingSound();
|
||||
}
|
|
@ -8,12 +8,14 @@ import java.util.stream.Stream;
|
|||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public interface NbtSerialisable {
|
||||
Serializer<BlockPos> BLOCK_POS = Serializer.of(NbtHelper::toBlockPos, NbtHelper::fromBlockPos);
|
||||
Serializer<ItemStack> ITEM_STACK = Serializer.of(ItemStack::fromNbt, stack -> stack.writeNbt(new NbtCompound()));
|
||||
|
||||
/**
|
||||
* Called to save this to nbt to persist state on file or to transmit over the network
|
||||
|
@ -44,6 +46,7 @@ public interface NbtSerialisable {
|
|||
}
|
||||
|
||||
static Vec3d readVector(NbtList list) {
|
||||
|
||||
return new Vec3d(list.getDouble(0), list.getDouble(1), list.getDouble(2));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import net.minecraft.world.BlockView;
|
|||
import net.minecraft.world.World;
|
||||
|
||||
public interface PosHelper {
|
||||
|
||||
Direction[] ALL = Direction.values();
|
||||
Direction[] HORIZONTAL = Arrays.stream(Direction.values()).filter(d -> d.getAxis().isHorizontal()).toArray(Direction[]::new);
|
||||
|
||||
static Vec3d offset(Vec3d a, Vec3i b) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
"MixinEnchantmentHelper",
|
||||
"MixinFallLocation",
|
||||
"MixinEntity",
|
||||
"MixinEntityBucketItem",
|
||||
"MixinEntityView",
|
||||
"MixinEntityShapeContext",
|
||||
"MixinFallingBlock",
|
||||
|
|
Loading…
Reference in a new issue