Add the insolator #17

Merged
BlakeRain merged 19 commits from BlakeRain/utamacraft:main into main 2023-12-01 18:20:57 +00:00
9 changed files with 422 additions and 13 deletions
Showing only changes of commit 4c420c6041 - Show all commits

View File

@ -2,9 +2,15 @@ package net.banutama.utamacraft.block.entity;
import com.mojang.logging.LogUtils;
import net.banutama.utamacraft.block.custom.InsolatorBlock;
import net.banutama.utamacraft.networking.ModMessages;
import net.banutama.utamacraft.networking.packet.EnergySyncPacket;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.banutama.utamacraft.networking.packet.ItemStackSyncPacket;
import net.banutama.utamacraft.screen.InsolatorMenu;
import net.banutama.utamacraft.util.ModEnergyStorage;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Containers;
@ -20,25 +26,85 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class InsolatorBlockEntity extends BlockEntity implements MenuProvider {
public class InsolatorBlockEntity extends BlockEntity implements MenuProvider, EnergySyncPacket.EnergySyncReceiver, FluidSyncPacket.FluidSyncReceiver, ItemStackSyncPacket.ItemStackSyncReceiver {
private static final Logger LOGGER = LogUtils.getLogger();
private final ItemStackHandler itemHandler = new ItemStackHandler(3) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if (level != null && !level.isClientSide()) {
ModMessages.sendToClients(new ItemStackSyncPacket(this, worldPosition));
}
}
@Override
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
return switch (slot) {
case 0 -> stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).isPresent();
case 1 -> true;
case 2 -> false;
default -> super.isItemValid(slot, stack);
};
}
};
@Override
public void receiveItemStack(NonNullList<ItemStack> stacks) {
for (int slot = 0; slot < stacks.size(); ++slot) {
itemHandler.setStackInSlot(slot, stacks.get(slot));
}
}
private static final int ENERGY_REQUIRED = 32;
private final ModEnergyStorage energyStorage = new ModEnergyStorage(60000, 256) {
@Override
public void onEnergyChanged() {
setChanged();
ModMessages.sendToClients(new EnergySyncPacket(energy, getBlockPos()));
}
};
@Override
public void receiveEnergySync(int energy) {
energyStorage.setEnergy(energy);
}
private final FluidTank fluidTank = new FluidTank(64000) {
@Override
protected void onContentsChanged() {
setChanged();
if (level != null && !level.isClientSide()) {
ModMessages.sendToClients(new FluidSyncPacket(fluid, worldPosition));
}
}
};
public FluidStack getFluidStack() {
return fluidTank.getFluid();
}
@Override
public void receiveFluidSync(FluidStack fluid) {
fluidTank.setFluid(fluid);
}
private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty();
private LazyOptional<IEnergyStorage> lazyEnergyStorage = LazyOptional.empty();
private LazyOptional<IFluidHandler> lazyFluidHandler = LazyOptional.empty();
protected final ContainerData data;
private int progress = 0;
private int maxProgress = 60;
@ -81,15 +147,25 @@ public class InsolatorBlockEntity extends BlockEntity implements MenuProvider {
@Nullable
@Override
public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pPlayerInventory, @NotNull Player pPlayer) {
ModMessages.sendToClients(new EnergySyncPacket(this.energyStorage.getEnergyStored(), getBlockPos()));
ModMessages.sendToClients(new FluidSyncPacket(this.fluidTank.getFluid(), getBlockPos()));
return new InsolatorMenu(pContainerId, pPlayerInventory, this, this.data);
}
@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
if (cap == ForgeCapabilities.ENERGY) {
return lazyEnergyStorage.cast();
}
if (cap == ForgeCapabilities.ITEM_HANDLER) {
return lazyItemHandler.cast();
}
if (cap == ForgeCapabilities.FLUID_HANDLER) {
return lazyFluidHandler.cast();
}
return super.getCapability(cap, side);
}
@ -97,18 +173,24 @@ public class InsolatorBlockEntity extends BlockEntity implements MenuProvider {
public void onLoad() {
super.onLoad();
lazyItemHandler = LazyOptional.of(() -> itemHandler);
lazyEnergyStorage = LazyOptional.of(() -> energyStorage);
lazyFluidHandler = LazyOptional.of(() -> fluidTank);
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
lazyItemHandler.invalidate();
lazyEnergyStorage.invalidate();
lazyFluidHandler.invalidate();
}
@Override
protected void saveAdditional(CompoundTag nbt) {
nbt.put("inventory", itemHandler.serializeNBT());
nbt.putInt("insolator.progress", progress);
nbt.putInt("insolator.energy", energyStorage.getEnergyStored());
fluidTank.writeToNBT(nbt);
super.saveAdditional(nbt);
}
@ -117,6 +199,8 @@ public class InsolatorBlockEntity extends BlockEntity implements MenuProvider {
super.load(nbt);
itemHandler.deserializeNBT(nbt.getCompound("inventory"));
progress = nbt.getInt("insolator.progress");
energyStorage.setEnergy(nbt.getInt("insolator.energy"));
fluidTank.readFromNBT(nbt);
}
public void drops() {

View File

@ -0,0 +1,55 @@
package net.banutama.utamacraft.networking;
import net.banutama.utamacraft.Utamacraft;
import net.banutama.utamacraft.networking.packet.EnergySyncPacket;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.banutama.utamacraft.networking.packet.ItemStackSyncPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;
public class ModMessages {
public static SimpleChannel INSTANCE;
public static void register() {
INSTANCE = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(Utamacraft.MOD_ID, "messages"))
.networkProtocolVersion(() -> "1.0")
.clientAcceptedVersions(s -> true)
.serverAcceptedVersions(s -> true)
.simpleChannel();
INSTANCE.messageBuilder(EnergySyncPacket.class, 0x0001, NetworkDirection.PLAY_TO_CLIENT)
.encoder(EnergySyncPacket::toBytes)
.decoder(EnergySyncPacket::new)
.consumerMainThread(EnergySyncPacket::handle)
.add();
INSTANCE.messageBuilder(FluidSyncPacket.class, 0x0002, NetworkDirection.PLAY_TO_CLIENT)
.encoder(FluidSyncPacket::toBytes)
.decoder(FluidSyncPacket::new)
.consumerMainThread(FluidSyncPacket::handle)
.add();
INSTANCE.messageBuilder(ItemStackSyncPacket.class, 0x0003, NetworkDirection.PLAY_TO_CLIENT)
.encoder(ItemStackSyncPacket::toBytes)
.decoder(ItemStackSyncPacket::new)
.consumerMainThread(ItemStackSyncPacket::handle)
.add();
}
public static <T> void sendToServer(T message) {
INSTANCE.sendToServer(message);
}
public static <T> void sendToPlayer(T message, ServerPlayer player) {
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
}
public static <T> void sendToClients(T message) {
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
}
}

View File

@ -0,0 +1,11 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public abstract class BasePacket {
public abstract void toBytes(FriendlyByteBuf buf);
public abstract boolean handle(Supplier<NetworkEvent.Context> supplier);
}

View File

@ -0,0 +1,69 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class EnergySyncPacket extends BasePacket {
private final int energy;
private final BlockPos pos;
public EnergySyncPacket(int energy, BlockPos pos) {
this.energy = energy;
this.pos = pos;
}
public EnergySyncPacket(@NotNull FriendlyByteBuf buf) {
this.energy = buf.readInt();
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(@NotNull FriendlyByteBuf buf) {
buf.writeInt(energy);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof EnergySyncReceiver energyReceiver) {
energyReceiver.receiveEnergySync(energy);
Player player = Minecraft.getInstance().player;
if (player == null) {
return;
}
if (player.containerMenu instanceof EnergySyncReceiverMenu menu &&
menu.getBlockEntity().getBlockPos().equals(pos)) {
menu.receiveEnergySync(energy);
}
}
});
return true;
}
public interface EnergySyncReceiver {
void receiveEnergySync(int energy);
}
public interface EnergySyncReceiverMenu extends EnergySyncReceiver {
BlockEntity getBlockEntity();
}
}

View File

@ -0,0 +1,70 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class FluidSyncPacket extends BasePacket {
private final FluidStack fluid;
private final BlockPos pos;
public FluidSyncPacket(FluidStack fluid, BlockPos pos) {
this.fluid = fluid;
this.pos = pos;
}
public FluidSyncPacket(@NotNull FriendlyByteBuf buf) {
this.fluid = buf.readFluidStack();
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(@NotNull FriendlyByteBuf buf) {
buf.writeFluidStack(fluid);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof FluidSyncReceiver fluidSyncReceiver) {
fluidSyncReceiver.receiveFluidSync(fluid.copy());
Player player = Minecraft.getInstance().player;
if (player == null) {
return;
}
if (player.containerMenu instanceof FluidSyncReceiverMenu menu &&
menu.getBlockEntity().getBlockPos().equals(pos)) {
menu.receiveFluidSync(fluid);
}
}
});
return true;
}
public interface FluidSyncReceiver {
void receiveFluidSync(FluidStack fluid);
}
public interface FluidSyncReceiverMenu extends FluidSyncReceiver {
BlockEntity getBlockEntity();
}
}

View File

@ -0,0 +1,70 @@
package net.banutama.utamacraft.networking.packet;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
public class ItemStackSyncPacket extends BasePacket {
private final NonNullList<ItemStack> stacks;
private final BlockPos pos;
public ItemStackSyncPacket(NonNullList<ItemStack> stacks, BlockPos pos) {
this.stacks = stacks;
this.pos = pos;
}
public ItemStackSyncPacket(IItemHandler handler, BlockPos pos) {
this.stacks = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY);
for (int slot = 0; slot < handler.getSlots(); ++slot) {
this.stacks.add(handler.getStackInSlot(slot));
}
this.pos = pos;
}
public ItemStackSyncPacket(@NotNull FriendlyByteBuf buf) {
this.stacks = buf.readCollection((int size) -> NonNullList.withSize(size, ItemStack.EMPTY), FriendlyByteBuf::readItem);
this.pos = buf.readBlockPos();
}
@Override
public void toBytes(FriendlyByteBuf buf) {
buf.writeCollection(this.stacks, FriendlyByteBuf::writeItem);
buf.writeBlockPos(pos);
}
@Override
public boolean handle(@NotNull Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
Level level = Minecraft.getInstance().level;
if (level == null) {
return;
}
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof ItemStackSyncReceiver receiver) {
receiver.receiveItemStack(stacks);
}
});
return true;
}
public interface ItemStackSyncReceiver {
void receiveItemStack(NonNullList<ItemStack> handler);
}
}

View File

@ -3,7 +3,7 @@ package net.banutama.utamacraft.screen;
import com.mojang.logging.LogUtils;
import net.banutama.utamacraft.block.custom.ModBlocks;
import net.banutama.utamacraft.block.entity.InsolatorBlockEntity;
import net.minecraft.core.NonNullList;
import net.banutama.utamacraft.networking.packet.FluidSyncPacket;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
@ -11,16 +11,18 @@ import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.SlotItemHandler;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
public class InsolatorMenu extends AbstractContainerMenu {
public class InsolatorMenu extends AbstractContainerMenu implements FluidSyncPacket.FluidSyncReceiverMenu {
private static final Logger LOGGER = LogUtils.getLogger();
public final InsolatorBlockEntity blockEntity;
private final Level level;
private final ContainerData data;
private FluidStack fluid;
public InsolatorMenu(int id, Inventory inventory, FriendlyByteBuf extraData) {
this(id, inventory, inventory.player.level.getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(3));
@ -34,11 +36,12 @@ public class InsolatorMenu extends AbstractContainerMenu {
this.level = inventory.player.level;
this.data = data;
this.blockEntity = insolator;
this.fluid = insolator.getFluidStack();
addPlayerInventory(inventory);
addPlayerHotbar(inventory);
this.blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(handler -> {
this.blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER).ifPresent(handler -> {
this.addSlot(new SlotItemHandler(handler, 0, 12, 15));
this.addSlot(new SlotItemHandler(handler, 1, 86, 15));
this.addSlot(new SlotItemHandler(handler, 2, 86, 60));
@ -50,6 +53,16 @@ public class InsolatorMenu extends AbstractContainerMenu {
}
}
@Override
public void receiveFluidSync(FluidStack fluid) {
this.fluid = fluid;
}
@Override
public BlockEntity getBlockEntity() {
return blockEntity;
}
public boolean isCrafting() {
return data.get(0) > 0;
}
@ -62,7 +75,7 @@ public class InsolatorMenu extends AbstractContainerMenu {
}
@Override
public boolean stillValid(Player player) {
public boolean stillValid(@NotNull Player player) {
return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()), player, ModBlocks.INSOLATOR.get());
}
@ -77,9 +90,9 @@ public class InsolatorMenu extends AbstractContainerMenu {
private static final int TILE_ENTITY_SLOT_COUNT = 3;
@Override
public ItemStack quickMoveStack(Player player, int index) {
public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) {
Slot source = slots.get(index);
if (source == null || !source.hasItem()) {
if (!source.hasItem()) {
return ItemStack.EMPTY;
}

View File

@ -8,6 +8,7 @@ import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import org.jetbrains.annotations.NotNull;
public class InsolatorScreen extends AbstractContainerScreen<InsolatorMenu> {
private static final ResourceLocation TEXTURE =
@ -18,7 +19,7 @@ public class InsolatorScreen extends AbstractContainerScreen<InsolatorMenu> {
}
@Override
protected void renderBg(PoseStack stack, float partialTick, int mouseX, int mouseY) {
protected void renderBg(@NotNull PoseStack stack, float partialTick, int mouseX, int mouseY) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, TEXTURE);
@ -36,7 +37,7 @@ public class InsolatorScreen extends AbstractContainerScreen<InsolatorMenu> {
}
@Override
public void render(PoseStack stack, int mouseX, int mouseY, float delta) {
public void render(@NotNull PoseStack stack, int mouseX, int mouseY, float delta) {
renderBackground(stack);
super.render(stack, mouseX, mouseY, delta);
renderTooltip(stack, mouseX, mouseY);

View File

@ -0,0 +1,36 @@
package net.banutama.utamacraft.util;
import net.minecraftforge.energy.EnergyStorage;
public abstract class ModEnergyStorage extends EnergyStorage {
public ModEnergyStorage(int capacity, int maxTransfer) {
super(capacity, maxTransfer);
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
int extracted = super.extractEnergy(maxExtract, simulate);
if (extracted != 0) {
onEnergyChanged();
}
return extracted;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
int received = super.receiveEnergy(maxReceive, simulate);
if (received != 0) {
onEnergyChanged();
}
return received;
}
public int setEnergy(int energy) {
this.energy = energy;
return energy;
}
public abstract void onEnergyChanged();
}