mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Jars can now hold fluids
This commit is contained in:
parent
a81336ef88
commit
7d63797d4d
11 changed files with 772 additions and 346 deletions
|
@ -1,42 +1,34 @@
|
||||||
package com.minelittlepony.unicopia.block;
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
|
import com.minelittlepony.unicopia.block.jar.EntityJarContents;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.block.jar.FluidOnlyJarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.jar.ItemsJarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.jar.FakeFluidJarContents;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
import net.minecraft.block.BlockEntityProvider;
|
import net.minecraft.block.BlockEntityProvider;
|
||||||
import net.minecraft.block.BlockRenderType;
|
import net.minecraft.block.BlockRenderType;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
|
||||||
import net.minecraft.block.InventoryProvider;
|
import net.minecraft.block.InventoryProvider;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
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.entity.player.PlayerEntity;
|
||||||
import net.minecraft.inventory.SidedInventory;
|
import net.minecraft.inventory.SidedInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.ItemUsage;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.NbtElement;
|
import net.minecraft.nbt.NbtElement;
|
||||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||||
import net.minecraft.network.packet.Packet;
|
import net.minecraft.network.packet.Packet;
|
||||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
|
||||||
import net.minecraft.registry.Registries;
|
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.TypedActionResult;
|
import net.minecraft.util.TypedActionResult;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
|
|
||||||
|
@ -79,7 +71,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
||||||
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
|
||||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR)
|
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR)
|
||||||
.map(TileData::getItems)
|
.map(TileData::getItems)
|
||||||
.map(data -> Math.min(16, data.getStacks().size()))
|
.map(data -> Math.min(16, data.stacks().size()))
|
||||||
.orElse(0);
|
.orElse(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +88,7 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
||||||
return new TileData(pos, state);
|
return new TileData(pos, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public SidedInventory getInventory(BlockState state, WorldAccess world, BlockPos pos) {
|
public SidedInventory getInventory(BlockState state, WorldAccess world, BlockPos pos) {
|
||||||
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(TileData::getItems).orElse(null);
|
return world.getBlockEntity(pos, UBlockEntities.ITEM_JAR).map(TileData::getItems).orElse(null);
|
||||||
|
@ -130,6 +122,16 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
||||||
return getContents() instanceof EntityJarContents c ? c : null;
|
return getContents() instanceof EntityJarContents c ? c : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public FluidJarContents getFluid() {
|
||||||
|
return getContents() instanceof FluidJarContents c ? c : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public FakeFluidJarContents getFakeFluid() {
|
||||||
|
return getContents() instanceof FakeFluidJarContents c ? c : null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Packet<ClientPlayPacketListener> toUpdatePacket() {
|
public Packet<ClientPlayPacketListener> toUpdatePacket() {
|
||||||
return BlockEntityUpdateS2CPacket.create(this);
|
return BlockEntityUpdateS2CPacket.create(this);
|
||||||
|
@ -151,11 +153,13 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
||||||
@Override
|
@Override
|
||||||
public void readNbt(NbtCompound nbt) {
|
public void readNbt(NbtCompound nbt) {
|
||||||
if (nbt.contains("items", NbtElement.COMPOUND_TYPE)) {
|
if (nbt.contains("items", NbtElement.COMPOUND_TYPE)) {
|
||||||
contents = new ItemsJarContents(this);
|
contents = new ItemsJarContents(this, nbt.getCompound("items"));
|
||||||
contents.fromNBT(nbt.getCompound("items"));
|
|
||||||
} else if (nbt.contains("entity", NbtElement.COMPOUND_TYPE)) {
|
} else if (nbt.contains("entity", NbtElement.COMPOUND_TYPE)) {
|
||||||
contents = new EntityJarContents(this);
|
contents = new EntityJarContents(this, nbt.getCompound("entity"));
|
||||||
contents.fromNBT(nbt.getCompound("entity"));
|
} else if (nbt.contains("fluid", NbtElement.COMPOUND_TYPE)) {
|
||||||
|
contents = new FluidOnlyJarContents(this, nbt.getCompound("fluid"));
|
||||||
|
} else if (nbt.contains("fakeFluid", NbtElement.COMPOUND_TYPE)) {
|
||||||
|
contents = new FakeFluidJarContents(this, nbt.getCompound("fakeFluid"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,249 +167,34 @@ public class ItemJarBlock extends JarBlock implements BlockEntityProvider, Inven
|
||||||
protected void writeNbt(NbtCompound nbt) {
|
protected void writeNbt(NbtCompound nbt) {
|
||||||
var items = getItems();
|
var items = getItems();
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
nbt.put("items", items.toNBT());
|
nbt.put("items", items.toNBT(new NbtCompound()));
|
||||||
} else if (getEntity() != null) {
|
} else if (getEntity() != null) {
|
||||||
nbt.put("entity", getEntity().toNBT());
|
nbt.put("entity", getEntity().toNBT(new NbtCompound()));
|
||||||
|
} else if (getFluid() != null) {
|
||||||
|
nbt.put("fluid", getFluid().toNBT(new NbtCompound()));
|
||||||
|
} else if (getFakeFluid() != null) {
|
||||||
|
nbt.put("fakeFluid", getFakeFluid().toNBT(new NbtCompound()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface JarContents {
|
||||||
public interface JarContents extends NbtSerialisable {
|
|
||||||
TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand);
|
TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand);
|
||||||
|
|
||||||
void onDestroyed();
|
void onDestroyed();
|
||||||
|
|
||||||
|
NbtCompound toNBT(NbtCompound compound);
|
||||||
|
|
||||||
|
default void consumeAndSwap(PlayerEntity player, Hand hand, ItemStack output) {
|
||||||
|
player.setStackInHand(hand, ItemUsage.exchangeStack(player.getStackInHand(hand), player, output.copy()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EntityJarContents implements JarContents {
|
public interface FluidJarContents extends JarContents {
|
||||||
@Nullable
|
FluidVariant fluid();
|
||||||
private EntityType<?> entityType;
|
|
||||||
@Nullable
|
|
||||||
private Entity renderEntity;
|
|
||||||
|
|
||||||
private final TileData tile;
|
default long amount() {
|
||||||
|
return FluidConstants.BUCKET;
|
||||||
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 TypedActionResult.success(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyed() {
|
|
||||||
stacks.forEach(stack -> {
|
|
||||||
dropStack(tile.getWorld(), tile.getPos(), stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ItemStack> getStacks() {
|
|
||||||
return stacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return stacks.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getStack(int slot) {
|
|
||||||
return slot < 0 || slot >= stacks.size() ? ItemStack.EMPTY : stacks.get(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack removeStack(int slot, int amount) {
|
|
||||||
if (slot < 0 || slot >= stacks.size()) {
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
ItemStack stack = stacks.get(slot);
|
|
||||||
ItemStack removed = stack.split(1);
|
|
||||||
if (stack.isEmpty()) {
|
|
||||||
stacks.remove(slot);
|
|
||||||
}
|
|
||||||
return removed;
|
|
||||||
} finally {
|
|
||||||
markDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack removeStack(int slot) {
|
|
||||||
if (slot < 0 || slot >= stacks.size()) {
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return stacks.remove(slot);
|
|
||||||
} finally {
|
|
||||||
markDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStack(int slot, ItemStack stack) {
|
|
||||||
if (slot >= stacks.size()) {
|
|
||||||
stacks.add(stack);
|
|
||||||
} else {
|
|
||||||
stacks.set(slot, stack);
|
|
||||||
}
|
|
||||||
markDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayerUse(PlayerEntity player) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
stacks.clear();
|
|
||||||
markDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getAvailableSlots(Direction side) {
|
|
||||||
return SLOTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
|
|
||||||
return slot >= 0 && slot < size() && slot >= stacks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.minelittlepony.unicopia.block.jar;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.Bucketable;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.Fluids;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
|
||||||
|
public record EntityJarContents (
|
||||||
|
TileData tile,
|
||||||
|
@Nullable EntityType<?> entityType,
|
||||||
|
Supplier<@Nullable Entity> entity
|
||||||
|
) implements FluidJarContents {
|
||||||
|
public EntityJarContents(TileData tile, NbtCompound compound) {
|
||||||
|
this(tile, Registries.ENTITY_TYPE.getOrEmpty(Identifier.tryParse(compound.getString("entity"))).orElse(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityJarContents(TileData tile) {
|
||||||
|
this(tile, (EntityType<?>)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityJarContents(TileData tile, EntityType<?> entityType) {
|
||||||
|
this(tile, entityType, Suppliers.memoize(() -> {
|
||||||
|
return entityType == null ? null : entityType.create(tile.getWorld());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||||
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
if (stack.isOf(Items.BUCKET)) {
|
||||||
|
if (entity().get() instanceof Bucketable bucketable) {
|
||||||
|
consumeAndSwap(player, hand, 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 = entity().get();
|
||||||
|
if (entity != null) {
|
||||||
|
entity.refreshPositionAfterTeleport(tile.getPos().toCenterPos());
|
||||||
|
tile.getWorld().spawnEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtCompound toNBT(NbtCompound compound) {
|
||||||
|
compound.putString("entity", EntityType.getId(entityType).toString());
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidVariant fluid() {
|
||||||
|
return FluidVariant.of(Fluids.WATER);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.minelittlepony.unicopia.block.jar;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
|
||||||
|
import com.minelittlepony.unicopia.util.FluidHelper;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.Fluid;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
|
||||||
|
public record FakeFluidJarContents (
|
||||||
|
TileData tile,
|
||||||
|
String fluid,
|
||||||
|
int color,
|
||||||
|
Item empty,
|
||||||
|
Item filled
|
||||||
|
) implements JarContents {
|
||||||
|
public FakeFluidJarContents(TileData tile, NbtCompound compound) {
|
||||||
|
this(tile, compound.getString("fluid"), compound.getInt("color"),
|
||||||
|
Registries.ITEM.get(new Identifier(compound.getString("empty"))),
|
||||||
|
Registries.ITEM.get(new Identifier(compound.getString("filled"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||||
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
|
||||||
|
tile.markDirty();
|
||||||
|
return getRealFluid().map(FluidVariant::of).<TypedActionResult<JarContents>>map(fluid -> {
|
||||||
|
long remainder = FluidHelper.deposit(stack, player, hand, fluid, FluidConstants.BUCKET);
|
||||||
|
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
|
||||||
|
if (remainder > 0) {
|
||||||
|
return TypedActionResult.success(new FluidOnlyJarContents(tile, remainder, fluid));
|
||||||
|
}
|
||||||
|
return TypedActionResult.success(new ItemsJarContents(tile));
|
||||||
|
}).orElseGet(() -> {
|
||||||
|
if (!stack.isOf(empty)) {
|
||||||
|
return TypedActionResult.pass(this);
|
||||||
|
}
|
||||||
|
consumeAndSwap(player, hand, filled.getDefaultStack());
|
||||||
|
player.playSound("powder_snow".equalsIgnoreCase(fluid) ? USounds.Vanilla.ITEM_BUCKET_FILL_POWDER_SNOW : USounds.Vanilla.ITEM_BUCKET_FILL, 1, 1);
|
||||||
|
return TypedActionResult.success(new ItemsJarContents(tile));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyed() {
|
||||||
|
getRealFluid().ifPresent(fluid -> {
|
||||||
|
tile.getWorld().setBlockState(tile.getPos(), FluidHelper.getFullFluidState(FluidVariant.of(fluid)).getBlockState());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtCompound toNBT(NbtCompound compound) {
|
||||||
|
compound.putString("fluid", fluid);
|
||||||
|
compound.putInt("color", color);
|
||||||
|
compound.putString("empty", Registries.ITEM.getId(empty).toString());
|
||||||
|
compound.putString("filled", Registries.ITEM.getId(filled).toString());
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Fluid> getRealFluid() {
|
||||||
|
return Registries.FLUID.getIds().stream()
|
||||||
|
.filter(id -> id.getPath().equalsIgnoreCase(fluid))
|
||||||
|
.findFirst()
|
||||||
|
.map(Registries.FLUID::get);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.minelittlepony.unicopia.block.jar;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
|
||||||
|
import com.minelittlepony.unicopia.util.FluidHelper;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
|
||||||
|
public record FluidOnlyJarContents (
|
||||||
|
TileData tile,
|
||||||
|
long amount,
|
||||||
|
FluidVariant fluid
|
||||||
|
) implements FluidJarContents {
|
||||||
|
|
||||||
|
public FluidOnlyJarContents(TileData tile, NbtCompound compound) {
|
||||||
|
this(tile, compound.getLong("amount"), FluidVariant.fromNbt(compound.getCompound("fluid")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||||
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
if (stack.isOf(Items.BUCKET)) {
|
||||||
|
long remainder = FluidHelper.deposit(stack, player, hand, fluid, amount);
|
||||||
|
tile.markDirty();
|
||||||
|
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
|
||||||
|
if (remainder > 0) {
|
||||||
|
return TypedActionResult.success(new FluidOnlyJarContents(tile, remainder, fluid));
|
||||||
|
}
|
||||||
|
return TypedActionResult.success(new ItemsJarContents(tile));
|
||||||
|
}
|
||||||
|
return TypedActionResult.pass(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyed() {
|
||||||
|
if (amount >= FluidConstants.BUCKET) {
|
||||||
|
tile.getWorld().setBlockState(tile.getPos(), FluidHelper.getFullFluidState(fluid).getBlockState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtCompound toNBT(NbtCompound compound) {
|
||||||
|
compound.put("fluid", fluid.toNbt());
|
||||||
|
compound.putLong("amount", amount);
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,208 @@
|
||||||
|
package com.minelittlepony.unicopia.block.jar;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.ItemJarBlock.TileData;
|
||||||
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
|
import com.minelittlepony.unicopia.mixin.MixinEntityBucketItem;
|
||||||
|
import com.minelittlepony.unicopia.util.FluidHelper;
|
||||||
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
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.util.Hand;
|
||||||
|
import net.minecraft.util.Pair;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
|
|
||||||
|
public record ItemsJarContents (
|
||||||
|
TileData tile,
|
||||||
|
List<ItemStack> stacks
|
||||||
|
) implements JarContents, SidedInventory {
|
||||||
|
private static final int[] SLOTS = IntStream.range(0, 16).toArray();
|
||||||
|
|
||||||
|
public ItemsJarContents(TileData tile) {
|
||||||
|
this(tile, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemsJarContents(TileData tile, NbtCompound compound) {
|
||||||
|
this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE))
|
||||||
|
.limit(15)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||||
|
ItemStack handStack = player.getStackInHand(hand);
|
||||||
|
|
||||||
|
if (handStack.isEmpty()) {
|
||||||
|
if (stacks.isEmpty()) {
|
||||||
|
return TypedActionResult.fail(this);
|
||||||
|
}
|
||||||
|
Block.dropStack(tile.getWorld(), tile.getPos(), stacks.remove(0));
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stacks.isEmpty()) {
|
||||||
|
if (handStack.getItem() instanceof MixinEntityBucketItem bucket) {
|
||||||
|
consumeAndSwap(player, hand, Items.BUCKET.getDefaultStack());
|
||||||
|
player.playSound(bucket.getEmptyingSound(), 1, 1);
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new EntityJarContents(tile, bucket.getEntityType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Long, FluidVariant> fluid = FluidHelper.extract(handStack, player, hand).orElse(null);
|
||||||
|
if (fluid != null) {
|
||||||
|
fluid.getRight().getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new FluidOnlyJarContents(tile, fluid.getLeft(), fluid.getRight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handStack.isOf(Items.MILK_BUCKET)) {
|
||||||
|
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
|
||||||
|
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new FakeFluidJarContents(tile, "milk", 0xFFFFFFFF, Items.BUCKET, Items.MILK_BUCKET));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handStack.isOf(Items.POWDER_SNOW_BUCKET)) {
|
||||||
|
consumeAndSwap(player, hand, Items.BUCKET.getDefaultStack());
|
||||||
|
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY_POWDER_SNOW, 1, 1);
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new FakeFluidJarContents(tile, "powder_snow", 0xFFFFFFFF, Items.BUCKET, Items.POWDER_SNOW_BUCKET));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handStack.isOf(UItems.LOVE_BUCKET)) {
|
||||||
|
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
|
||||||
|
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new FakeFluidJarContents(tile, "love", 0xFF3030, Items.BUCKET, UItems.LOVE_BUCKET));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handStack.isOf(UItems.JUICE)) {
|
||||||
|
consumeAndSwap(player, hand, handStack.getRecipeRemainder());
|
||||||
|
player.playSound(USounds.Vanilla.ITEM_BUCKET_EMPTY, 1, 1);
|
||||||
|
markDirty();
|
||||||
|
return TypedActionResult.success(new FakeFluidJarContents(tile, "apple_juice", 0x30FF30, Items.GLASS_BOTTLE, UItems.JUICE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stacks.size() >= size()) {
|
||||||
|
return TypedActionResult.fail(this);
|
||||||
|
}
|
||||||
|
stacks.add(player.isCreative() ? handStack.copyWithCount(1) : handStack.split(1));
|
||||||
|
markDirty();
|
||||||
|
|
||||||
|
return TypedActionResult.success(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyed() {
|
||||||
|
stacks.forEach(stack -> Block.dropStack(tile.getWorld(), tile.getPos(), stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return stacks.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getStack(int slot) {
|
||||||
|
return slot < 0 || slot >= stacks.size() ? ItemStack.EMPTY : stacks.get(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack removeStack(int slot, int amount) {
|
||||||
|
if (slot < 0 || slot >= stacks.size()) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ItemStack stack = stacks.get(slot);
|
||||||
|
ItemStack removed = stack.split(1);
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
stacks.remove(slot);
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
} finally {
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack removeStack(int slot) {
|
||||||
|
if (slot < 0 || slot >= stacks.size()) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return stacks.remove(slot);
|
||||||
|
} finally {
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStack(int slot, ItemStack stack) {
|
||||||
|
if (slot >= stacks.size()) {
|
||||||
|
stacks.add(stack);
|
||||||
|
} else {
|
||||||
|
stacks.set(slot, stack);
|
||||||
|
}
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayerUse(PlayerEntity player) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
stacks.clear();
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getAvailableSlots(Direction side) {
|
||||||
|
return SLOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canInsert(int slot, ItemStack stack, Direction dir) {
|
||||||
|
return slot >= 0 && slot < size() && slot >= stacks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
|
||||||
|
return slot >= 0 && slot < size() && slot < stacks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtCompound toNBT(NbtCompound compound) {
|
||||||
|
compound.put("items", NbtSerialisable.ITEM_STACK.writeAll(stacks));
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void markDirty() {
|
||||||
|
tile.markDirty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,20 +5,15 @@ import org.joml.Vector3f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
import net.minecraft.client.render.BufferBuilder;
|
import net.minecraft.client.render.BufferBuilder;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
|
||||||
import net.minecraft.client.render.Tessellator;
|
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.VertexFormat;
|
||||||
import net.minecraft.client.render.VertexFormats;
|
import net.minecraft.client.render.VertexFormats;
|
||||||
import net.minecraft.client.texture.Sprite;
|
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.util.math.ColorHelper;
|
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
|
|
||||||
public class RenderUtil {
|
public class RenderUtil {
|
||||||
public static final Vector4f TEMP_VECTOR = new Vector4f();
|
public static final Vector4f TEMP_VECTOR = new Vector4f();
|
||||||
private static final Vector4f TEMP_UV_VECTOR = new Vector4f();
|
public static final Vector4f TEMP_UV_VECTOR = new Vector4f();
|
||||||
|
public static final Vector3f TEMP_NORMAL_VECTOR = new Vector3f();
|
||||||
public static final Vertex[] UNIT_FACE = new Vertex[] {
|
public static final Vertex[] UNIT_FACE = new Vertex[] {
|
||||||
new Vertex(0, 0, 0, 1, 1),
|
new Vertex(0, 0, 0, 1, 1),
|
||||||
new Vertex(0, 1, 0, 1, 0),
|
new Vertex(0, 1, 0, 1, 0),
|
||||||
|
@ -31,72 +26,9 @@ public class RenderUtil {
|
||||||
new Vertex(1, 0, 0, 1, 1),
|
new Vertex(1, 0, 0, 1, 1),
|
||||||
new Vertex(0, 0, 0, 0, 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) {
|
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);
|
renderFace(matrices, te, buffer, r, g, b, a, light, 1, 1);
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
package com.minelittlepony.unicopia.client.render.entity;
|
package com.minelittlepony.unicopia.client.render.entity;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.common.util.Color;
|
||||||
import com.minelittlepony.unicopia.block.ItemJarBlock;
|
import com.minelittlepony.unicopia.block.ItemJarBlock;
|
||||||
import com.minelittlepony.unicopia.block.ItemJarBlock.EntityJarContents;
|
import com.minelittlepony.unicopia.block.ItemJarBlock.FluidJarContents;
|
||||||
import com.minelittlepony.unicopia.block.ItemJarBlock.ItemsJarContents;
|
import com.minelittlepony.unicopia.block.jar.ItemsJarContents;
|
||||||
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
import com.minelittlepony.unicopia.block.jar.FakeFluidJarContents;
|
||||||
|
import com.minelittlepony.unicopia.block.jar.EntityJarContents;
|
||||||
|
import com.minelittlepony.unicopia.client.render.model.CubeModel;
|
||||||
|
import com.minelittlepony.unicopia.util.FluidHelper;
|
||||||
import com.minelittlepony.unicopia.util.PosHelper;
|
import com.minelittlepony.unicopia.util.PosHelper;
|
||||||
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
|
||||||
|
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.color.world.BiomeColors;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
||||||
|
@ -20,8 +30,12 @@ import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.command.argument.EntityAnchorArgumentType.EntityAnchor;
|
import net.minecraft.command.argument.EntityAnchorArgumentType.EntityAnchor;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.Fluid;
|
||||||
|
import net.minecraft.fluid.FluidState;
|
||||||
|
import net.minecraft.fluid.Fluids;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
import net.minecraft.util.math.RotationAxis;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -29,16 +43,13 @@ import net.minecraft.util.math.random.Random;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBlock.TileData> {
|
public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBlock.TileData> {
|
||||||
|
private static final Direction[] GLASS_SIDES = Arrays.stream(PosHelper.ALL).filter(i -> i != Direction.UP).toArray(Direction[]::new);
|
||||||
private final ItemRenderer itemRenderer;
|
private final ItemRenderer itemRenderer;
|
||||||
private final EntityRenderDispatcher dispatcher;
|
private final EntityRenderDispatcher dispatcher;
|
||||||
|
|
||||||
private final Sprite waterSprite;
|
|
||||||
|
|
||||||
public ItemJarBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
|
public ItemJarBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
|
||||||
itemRenderer = ctx.getItemRenderer();
|
itemRenderer = ctx.getItemRenderer();
|
||||||
dispatcher = ctx.getEntityRenderDispatcher();
|
dispatcher = ctx.getEntityRenderDispatcher();
|
||||||
waterSprite = MinecraftClient.getInstance().getBakedModelManager().getBlockModels().getModel(Blocks.WATER.getDefaultState()).getParticleSprite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,6 +64,16 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
renderEntity(data, entity, tickDelta, matrices, vertices, light, overlay);
|
renderEntity(data, entity, tickDelta, matrices, vertices, light, overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FluidJarContents fluid = data.getFluid();
|
||||||
|
if (fluid != null) {
|
||||||
|
renderFluid(data, fluid, tickDelta, matrices, vertices, light, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
FakeFluidJarContents milk = data.getFakeFluid();
|
||||||
|
if (milk != null) {
|
||||||
|
renderFluid(data, Fluids.WATER.getDefaultState(), milk.color(), FluidConstants.BUCKET, tickDelta, matrices, vertices, light, overlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderItemStacks(ItemJarBlock.TileData data, ItemsJarContents items, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
private void renderItemStacks(ItemJarBlock.TileData data, ItemsJarContents items, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||||
|
@ -66,7 +87,7 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
|
||||||
Random rng = Random.create(data.getPos().asLong());
|
Random rng = Random.create(data.getPos().asLong());
|
||||||
|
|
||||||
float y = 0;
|
float y = 0;
|
||||||
for (ItemStack stack : items.getStacks()) {
|
for (ItemStack stack : items.stacks()) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
|
|
||||||
matrices.translate((rng.nextFloat() - 0.5F) * 0.5F, (rng.nextFloat() - 0.5F) * 0.8F, -0.05 + y);
|
matrices.translate((rng.nextFloat() - 0.5F) * 0.5F, (rng.nextFloat() - 0.5F) * 0.8F, -0.05 + y);
|
||||||
|
@ -80,10 +101,9 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderEntity(ItemJarBlock.TileData data, EntityJarContents entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
private void renderEntity(ItemJarBlock.TileData data, EntityJarContents entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||||
Entity e = entity.getOrCreateEntity();
|
Entity e = entity.entity().get();
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
|
|
||||||
|
|
||||||
PlayerEntity player = MinecraftClient.getInstance().player;
|
PlayerEntity player = MinecraftClient.getInstance().player;
|
||||||
int age = player == null ? 0 : player.age;
|
int age = player == null ? 0 : player.age;
|
||||||
|
|
||||||
|
@ -109,20 +129,57 @@ public class ItemJarBlockEntityRenderer implements BlockEntityRenderer<ItemJarBl
|
||||||
dispatcher.render(e, 0, 0, 0, yaw * MathHelper.RADIANS_PER_DEGREE, tickDelta, matrices, vertices, light);
|
dispatcher.render(e, 0, 0, 0, yaw * MathHelper.RADIANS_PER_DEGREE, tickDelta, matrices, vertices, light);
|
||||||
matrices.pop();
|
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) {
|
private void renderFluid(ItemJarBlock.TileData data, FluidJarContents fluid, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||||
|
FluidState state = FluidHelper.getFullFluidState(fluid.fluid());
|
||||||
|
int color = getFluidColor(data.getWorld(), data.getPos(), state);
|
||||||
|
renderFluid(data, state, color, fluid.amount(), tickDelta, matrices, vertices, light, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderFluid(ItemJarBlock.TileData data, FluidState state, int color, long amount, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light, int overlay) {
|
||||||
|
Sprite[] sprite = getFluidSprite(data.getWorld(), data.getPos(), state);
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0.3F, 0, 0.3F);
|
Sprite topSprite = sprite[0];
|
||||||
RenderUtil.renderSpriteCubeFaces(
|
float height = 0.6F * (amount / (float)FluidConstants.BUCKET);
|
||||||
|
boolean opaque = Color.a(color) >= 1;
|
||||||
|
CubeModel.render(
|
||||||
matrices,
|
matrices,
|
||||||
vertices,
|
vertices.getBuffer(opaque ? RenderLayer.getEntitySolid(topSprite.getAtlasId()) : RenderLayer.getEntityTranslucent(topSprite.getAtlasId())),
|
||||||
waterSprite,
|
topSprite.getMinU(), topSprite.getMinV(),
|
||||||
0.4F, 0.4F, 0.4F,
|
topSprite.getMaxU(), topSprite.getMaxV(),
|
||||||
BiomeColors.getWaterColor(world, pos),
|
0.28F, 0.01F, 0.28F,
|
||||||
light, overlay, PosHelper.ALL
|
0.73F, 0.01F + height, 0.73F,
|
||||||
|
color,
|
||||||
|
light, overlay, Direction.UP
|
||||||
|
);
|
||||||
|
Sprite sideSprite = sprite[sprite.length - 1];
|
||||||
|
CubeModel.render(
|
||||||
|
matrices,
|
||||||
|
vertices.getBuffer(opaque ? RenderLayer.getEntitySolid(sideSprite.getAtlasId()) : RenderLayer.getEntityTranslucent(sideSprite.getAtlasId())),
|
||||||
|
sideSprite.getMinU(), sideSprite.getMinV(),
|
||||||
|
sideSprite.getMaxU(), sideSprite.getMaxV(),
|
||||||
|
0.28F, 0.01F, 0.28F,
|
||||||
|
0.73F, 0.01F + height, 0.73F,
|
||||||
|
color,
|
||||||
|
light, overlay, GLASS_SIDES
|
||||||
);
|
);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getFluidColor(World world, BlockPos pos, FluidState state) {
|
||||||
|
return getFluidHandler(state.getFluid()).getFluidColor(world, pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sprite[] getFluidSprite(@Nullable World world, BlockPos pos, FluidState state) {
|
||||||
|
return getFluidHandler(state.getFluid()).getFluidSprites(world, pos, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FluidRenderHandler getFluidHandler(Fluid fluid) {
|
||||||
|
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
|
||||||
|
if (handler == null) {
|
||||||
|
return FluidRenderHandlerRegistry.INSTANCE.get(Fluids.WATER);
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.minelittlepony.unicopia.client.render.model;
|
||||||
|
|
||||||
|
import org.joml.Matrix3f;
|
||||||
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector2f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
|
import com.minelittlepony.common.util.Color;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||||
|
import com.minelittlepony.unicopia.client.render.RenderUtil.Vertex;
|
||||||
|
|
||||||
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
|
|
||||||
|
public class CubeModel {
|
||||||
|
private static final Vector2f TEMP_UV_VECTOR = new Vector2f();
|
||||||
|
private static final Vertex[][] CUBE_VERTICES = {
|
||||||
|
new Vertex[] {
|
||||||
|
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[] {
|
||||||
|
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[] {
|
||||||
|
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[] {
|
||||||
|
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[] {
|
||||||
|
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[] {
|
||||||
|
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 render(MatrixStack matrices, VertexConsumer buffer,
|
||||||
|
float u0, float v0, float u1, float v1,
|
||||||
|
float x0, float y0, float z0, float x1, float y1, float z1,
|
||||||
|
int color, int light, int overlay,
|
||||||
|
Direction... directions) {
|
||||||
|
float r = Color.r(color), g = Color.g(color), b = Color.b(color);
|
||||||
|
float du = u1 - u0, dv = v1 - v0;
|
||||||
|
float dx = x1 - x0, dy = y1 - y0, dz = z1 - z0;
|
||||||
|
Matrix4f position = matrices.peek().getPositionMatrix();
|
||||||
|
Matrix3f normal = matrices.peek().getNormalMatrix();
|
||||||
|
for (Direction direction : directions) {
|
||||||
|
for (Vertex vertex : CUBE_VERTICES[direction.ordinal()]) {
|
||||||
|
Vector4f pos = position.transform(RenderUtil.TEMP_VECTOR.set(vertex.position(), 1).mul(dx, dy, dz, 1).add(x0, y0, z0, 0));
|
||||||
|
Vector2f tex = TEMP_UV_VECTOR.set(vertex.texture().x, vertex.texture().y).mul(du, dv).add(u0, v0);
|
||||||
|
Vector3f norm = normal.transform(RenderUtil.TEMP_NORMAL_VECTOR.set(direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ()));
|
||||||
|
buffer.vertex(pos.x, pos.y, pos.z, r, g, b, 1, tex.x, tex.y, overlay, light, norm.x, norm.y, norm.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package com.minelittlepony.unicopia.datagen.providers.loot;
|
package com.minelittlepony.unicopia.datagen.providers.loot;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.block.PieBlock;
|
||||||
import com.minelittlepony.unicopia.block.UBlocks;
|
import com.minelittlepony.unicopia.block.UBlocks;
|
||||||
import com.minelittlepony.unicopia.datagen.providers.UModelProvider;
|
import com.minelittlepony.unicopia.datagen.providers.UModelProvider;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
|
@ -14,14 +16,21 @@ import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.enums.BedPart;
|
import net.minecraft.block.enums.BedPart;
|
||||||
import net.minecraft.enchantment.Enchantments;
|
import net.minecraft.enchantment.Enchantments;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.loot.LootPool;
|
import net.minecraft.loot.LootPool;
|
||||||
import net.minecraft.loot.LootTable;
|
import net.minecraft.loot.LootTable;
|
||||||
|
import net.minecraft.loot.condition.BlockStatePropertyLootCondition;
|
||||||
|
import net.minecraft.loot.condition.LootConditionConsumingBuilder;
|
||||||
import net.minecraft.loot.condition.TableBonusLootCondition;
|
import net.minecraft.loot.condition.TableBonusLootCondition;
|
||||||
import net.minecraft.loot.entry.ItemEntry;
|
import net.minecraft.loot.entry.ItemEntry;
|
||||||
import net.minecraft.loot.function.SetCountLootFunction;
|
import net.minecraft.loot.function.SetCountLootFunction;
|
||||||
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
|
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
|
||||||
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
|
import net.minecraft.loot.provider.number.UniformLootNumberProvider;
|
||||||
|
import net.minecraft.predicate.StatePredicate;
|
||||||
|
import net.minecraft.state.property.BooleanProperty;
|
||||||
|
import net.minecraft.state.property.Property;
|
||||||
|
import net.minecraft.util.StringIdentifiable;
|
||||||
|
|
||||||
public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
|
public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
|
||||||
|
|
||||||
|
@ -116,6 +125,7 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
|
||||||
addDrop(UBlocks.CLOUD_PILLAR, drops(UBlocks.CLOUD_PILLAR, UBlocks.CLOUD, ConstantLootNumberProvider.create(2)));
|
addDrop(UBlocks.CLOUD_PILLAR, drops(UBlocks.CLOUD_PILLAR, UBlocks.CLOUD, ConstantLootNumberProvider.create(2)));
|
||||||
|
|
||||||
addDrop(UBlocks.FROSTED_OBSIDIAN, Blocks.OBSIDIAN);
|
addDrop(UBlocks.FROSTED_OBSIDIAN, Blocks.OBSIDIAN);
|
||||||
|
addDrop(UBlocks.APPLE_PIE, pieDrops(UBlocks.APPLE_PIE, UItems.APPLE_PIE, UItems.APPLE_PIE_HOOF));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LootTable.Builder fruitLeavesDrops(Block leaves) {
|
private LootTable.Builder fruitLeavesDrops(Block leaves) {
|
||||||
|
@ -136,4 +146,23 @@ public class UBlockLootTableProvider extends FabricBlockLootTableProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LootTable.Builder pieDrops(Block block, Item drop, Item stomped) {
|
||||||
|
return LootTable.builder().pool(LootPool.builder()
|
||||||
|
.rolls(ConstantLootNumberProvider.create(1)).conditionally(WITH_SILK_TOUCH)
|
||||||
|
.with(addStateCondition(block, PieBlock.STOMPED, false, applyExplosionDecay(block, ItemEntry.builder(drop))))
|
||||||
|
.with(addStateCondition(block, PieBlock.STOMPED, true, applyExplosionDecay(block, ItemEntry.builder(stomped))))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends LootConditionConsumingBuilder<T>, P extends Comparable<P> & StringIdentifiable> T addStateCondition(Block block,
|
||||||
|
Property<P> property, P value,
|
||||||
|
LootConditionConsumingBuilder<T> builder) {
|
||||||
|
return builder.conditionally(BlockStatePropertyLootCondition.builder(block).properties(StatePredicate.Builder.create().exactMatch(property, value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends LootConditionConsumingBuilder<T>> T addStateCondition(Block block,
|
||||||
|
BooleanProperty property, boolean value,
|
||||||
|
LootConditionConsumingBuilder<T> builder) {
|
||||||
|
return builder.conditionally(BlockStatePropertyLootCondition.builder(block).properties(StatePredicate.Builder.create().exactMatch(property, value)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.minelittlepony.unicopia.util;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.FluidState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.Pair;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here be dragons
|
||||||
|
*/
|
||||||
|
public interface FluidHelper {
|
||||||
|
static FluidState getFullFluidState(FluidVariant variant) {
|
||||||
|
return PsyFluidHelper.getFullFluidState(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Optional<Pair<Long, FluidVariant>> extract(ItemStack stack, PlayerEntity player, Hand hand) {
|
||||||
|
return getAsContainer(stack, ContainerItemContext.forPlayerInteraction(player, hand))
|
||||||
|
.filter(c -> !c.isResourceBlank())
|
||||||
|
.map(container -> applyTransaction(t -> {
|
||||||
|
FluidVariant type = container.getResource();
|
||||||
|
long amountExtracted = container.extract(type, FluidConstants.BUCKET, t);
|
||||||
|
if (amountExtracted > 0) {
|
||||||
|
return new Pair<>(amountExtracted, type);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
static long deposit(ItemStack stack, PlayerEntity player, Hand hand, FluidVariant variant, long amount) {
|
||||||
|
return amount - getAsStorage(stack, ContainerItemContext.forPlayerInteraction(player, hand))
|
||||||
|
.map(storage -> applyTransaction(t -> storage.insert(variant, amount, t)))
|
||||||
|
.orElse(0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Optional<Storage<FluidVariant>> getAsStorage(ItemStack stack, ContainerItemContext context) {
|
||||||
|
return Optional.ofNullable(FluidStorage.ITEM.find(stack, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Optional<StorageView<FluidVariant>> getAsContainer(ItemStack stack, ContainerItemContext context) {
|
||||||
|
return getAsStorage(stack, context).map(storage -> {
|
||||||
|
Iterator<StorageView<FluidVariant>> iter = storage.iterator();
|
||||||
|
return iter.hasNext() ? iter.next() : null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T applyTransaction(Function<Transaction, T> action) {
|
||||||
|
try (@SuppressWarnings("deprecation") var transaction = Transaction.isOpen()
|
||||||
|
? Transaction.getCurrentUnsafe().openNested()
|
||||||
|
: Transaction.openOuter()) {
|
||||||
|
try {
|
||||||
|
return action.apply(transaction);
|
||||||
|
} finally {
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.minelittlepony.unicopia.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
|
import net.minecraft.fluid.FluidState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
|
||||||
|
final class PsyFluidHelper {
|
||||||
|
private static final Supplier<Optional<Class<?>>> SIMPLE_FLUID_CLASS = Suppliers.memoize(() -> {
|
||||||
|
try {
|
||||||
|
return Optional.ofNullable(Class.forName("ivorius.psychedelicraft.fluid.SimpleFluid"));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
private static final Function<FluidVariant, FluidState> FALLBACK_METHOD = fluid -> fluid.getFluid().getDefaultState();
|
||||||
|
private static final Supplier<Function<FluidVariant, FluidState>> GET_FULL_FLUID_STATE = Suppliers.memoize(() -> SIMPLE_FLUID_CLASS.get().<Function<FluidVariant, FluidState>>map(type -> {
|
||||||
|
try {
|
||||||
|
final Method method = type.getDeclaredMethod("getFluidState", ItemStack.class);
|
||||||
|
if (method != null) {
|
||||||
|
return fluid -> {
|
||||||
|
try {
|
||||||
|
ItemStack stack = Items.STONE.getDefaultStack();
|
||||||
|
NbtCompound fluidTag = stack.getOrCreateSubNbt("fluid");
|
||||||
|
fluidTag.putString("id", Registries.FLUID.getId(fluid.getFluid()).toString());
|
||||||
|
fluidTag.put("attributes", fluid.getNbt());
|
||||||
|
return FluidState.class.cast(method.invoke(type.cast(fluid), stack));
|
||||||
|
} catch (Throwable tt) {}
|
||||||
|
return FALLBACK_METHOD.apply(fluid);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {}
|
||||||
|
return FALLBACK_METHOD;
|
||||||
|
}).orElse(FALLBACK_METHOD));
|
||||||
|
|
||||||
|
static FluidState getFullFluidState(FluidVariant variant) {
|
||||||
|
return SIMPLE_FLUID_CLASS.get()
|
||||||
|
.filter(type -> type.isAssignableFrom(variant.getFluid().getClass()))
|
||||||
|
.map(type -> GET_FULL_FLUID_STATE.get().apply(variant))
|
||||||
|
.orElseGet(() -> variant.getFluid().getDefaultState());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue