Fix bugs and allow for storing bucketed entities in jars

This commit is contained in:
Sollace 2024-03-30 21:22:36 +00:00
parent f0b2a8a550
commit 2784627adc
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
8 changed files with 474 additions and 76 deletions

View file

@ -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();
}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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();
}

View file

@ -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));
}

View file

@ -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) {

View file

@ -19,6 +19,7 @@
"MixinEnchantmentHelper",
"MixinFallLocation",
"MixinEntity",
"MixinEntityBucketItem",
"MixinEntityView",
"MixinEntityShapeContext",
"MixinFallingBlock",