diff --git a/build.gradle b/build.gradle index b30cc36..822f7f9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'net.minecraftforge.gradle' version '5.1.+' + id 'org.parchmentmc.librarian.forgegradle' version '1.+' } @@ -26,6 +27,7 @@ minecraft { // Use non-default mappings at your own risk. They may not always work. // Simply re-run your setup task after changing the mappings to update your workspace. mappings channel: 'official', version: '1.18.2' + mappings channel: 'parchment', version: '2022.08.02-1.18.2' // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') diff --git a/settings.gradle b/settings.gradle index 2fb1a36..a95fa32 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,7 @@ pluginManagement { repositories { gradlePluginPortal() maven { url = 'https://maven.minecraftforge.net/' } + maven { url = 'https://maven.parchmentmc.org' } } } diff --git a/src/main/java/xyz/nuark/enchantrium/Enchantrium.java b/src/main/java/xyz/nuark/enchantrium/Enchantrium.java index d84b687..9db6eb2 100644 --- a/src/main/java/xyz/nuark/enchantrium/Enchantrium.java +++ b/src/main/java/xyz/nuark/enchantrium/Enchantrium.java @@ -1,29 +1,41 @@ package xyz.nuark.enchantrium; import com.mojang.logging.LogUtils; +import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; import org.slf4j.Logger; import xyz.nuark.enchantrium.block.ModBlocks; import xyz.nuark.enchantrium.block.entity.ModBlockEntities; import xyz.nuark.enchantrium.item.ModItems; +import xyz.nuark.enchantrium.network.Networking; +import xyz.nuark.enchantrium.screen.EnchanterScreen; import xyz.nuark.enchantrium.screen.ModMenuTypes; +import xyz.nuark.enchantrium.setup.ClientSetup; +import xyz.nuark.enchantrium.setup.ModSetup; +import xyz.nuark.enchantrium.setup.Registration; @Mod(Enchantrium.MOD_ID) public class Enchantrium { public static final String MOD_ID = "enchantrium"; public static final Logger LOGGER = LogUtils.getLogger(); + public Enchantrium() { IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); - ModItems.register(eventBus); - ModBlocks.register(eventBus); - ModBlockEntities.register(eventBus); - ModMenuTypes.register(eventBus); + ModSetup.setup(); + Registration.register(eventBus); - MinecraftForge.EVENT_BUS.register(this); + eventBus.addListener(ModSetup::init); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> eventBus.addListener(ClientSetup::init)); } } diff --git a/src/main/java/xyz/nuark/enchantrium/block/ModBlocks.java b/src/main/java/xyz/nuark/enchantrium/block/ModBlocks.java index d6841a6..b022d74 100644 --- a/src/main/java/xyz/nuark/enchantrium/block/ModBlocks.java +++ b/src/main/java/xyz/nuark/enchantrium/block/ModBlocks.java @@ -8,6 +8,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; @@ -15,7 +17,9 @@ import net.minecraftforge.registries.RegistryObject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.block.custom.EnchanterBlock; import xyz.nuark.enchantrium.item.ModItems; +import xyz.nuark.enchantrium.setup.ModSetup; import java.util.List; import java.util.function.Supplier; @@ -24,6 +28,10 @@ public class ModBlocks { public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, Enchantrium.MOD_ID); + public static final RegistryObject ENCHANTER = registerBlock("enchanter", + () -> new EnchanterBlock(BlockBehaviour.Properties.copy(Blocks.ENCHANTING_TABLE).noOcclusion()) + ); + private static RegistryObject registerBlockWithoutBlockItem(String name, Supplier block) { return BLOCKS.register(name, block); } @@ -36,7 +44,7 @@ public class ModBlocks { private static RegistryObject registerBlockItem(String name, RegistryObject block, String tooltipKey) { return ModItems.ITEMS.register(name, () -> new BlockItem(block.get(), - new Item.Properties().tab(ModItems.ITEM_GROUP)) { + new Item.Properties().tab(ModSetup.ITEM_GROUP)) { @Override public void appendHoverText(@NotNull ItemStack pStack, @Nullable Level pLevel, @NotNull List pTooltip, @NotNull TooltipFlag pFlag) { pTooltip.add(new TranslatableComponent(tooltipKey)); @@ -52,7 +60,7 @@ public class ModBlocks { private static RegistryObject registerBlockItem(String name, RegistryObject block) { return ModItems.ITEMS.register(name, () -> new BlockItem(block.get(), - new Item.Properties().tab(ModItems.ITEM_GROUP))); + new Item.Properties().tab(ModSetup.ITEM_GROUP))); } public static void register(IEventBus eventBus) { diff --git a/src/main/java/xyz/nuark/enchantrium/block/custom/EnchanterBlock.java b/src/main/java/xyz/nuark/enchantrium/block/custom/EnchanterBlock.java new file mode 100644 index 0000000..9954d71 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/block/custom/EnchanterBlock.java @@ -0,0 +1,62 @@ +package xyz.nuark.enchantrium.block.custom; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.nuark.enchantrium.block.entity.custom.EnchanterBlockEntity; + +public class EnchanterBlock extends BaseEntityBlock { + public EnchanterBlock(BlockBehaviour.Properties properties) { + super(properties); + } + + @Override + public RenderShape getRenderShape(BlockState pState) { + return RenderShape.MODEL; + } + + @Override + public void onRemove(BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (pState.getBlock() != pNewState.getBlock()) { + BlockEntity blockEntity = pLevel.getBlockEntity(pPos); + if (blockEntity instanceof EnchanterBlockEntity) { + ((EnchanterBlockEntity) blockEntity).drops(); + } + } + super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); + } + + @Override + public InteractionResult use(BlockState blockState, Level level, BlockPos blockPos, + Player player, InteractionHand interactionHand, BlockHitResult hitResult) { + if (!level.isClientSide()) { + BlockEntity entity = level.getBlockEntity(blockPos); + if(entity instanceof EnchanterBlockEntity) { + NetworkHooks.openGui(((ServerPlayer)player), (EnchanterBlockEntity)entity, blockPos); + } else { + throw new IllegalStateException("Our Container provider is missing!"); + } + } + + return InteractionResult.sidedSuccess(level.isClientSide()); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) { + return new EnchanterBlockEntity(blockPos, blockState); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/block/entity/ModBlockEntities.java b/src/main/java/xyz/nuark/enchantrium/block/entity/ModBlockEntities.java index acbc15e..4b963c3 100644 --- a/src/main/java/xyz/nuark/enchantrium/block/entity/ModBlockEntities.java +++ b/src/main/java/xyz/nuark/enchantrium/block/entity/ModBlockEntities.java @@ -4,12 +4,18 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.block.ModBlocks; +import xyz.nuark.enchantrium.block.entity.custom.EnchanterBlockEntity; public class ModBlockEntities { public static final DeferredRegister> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITIES, Enchantrium.MOD_ID); + public static final RegistryObject> ENCHANTER_BLOCK_ENTITY = + BLOCK_ENTITIES.register("enchanter_block_entity", () -> BlockEntityType.Builder.of(EnchanterBlockEntity::new, ModBlocks.ENCHANTER.get()).build(null)); + public static void register(IEventBus eventBus) { BLOCK_ENTITIES.register(eventBus); } diff --git a/src/main/java/xyz/nuark/enchantrium/block/entity/custom/EnchanterBlockEntity.java b/src/main/java/xyz/nuark/enchantrium/block/entity/custom/EnchanterBlockEntity.java new file mode 100644 index 0000000..4c5a829 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/block/entity/custom/EnchanterBlockEntity.java @@ -0,0 +1,122 @@ +package xyz.nuark.enchantrium.block.entity.custom; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.Containers; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +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.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.block.entity.ModBlockEntities; +import xyz.nuark.enchantrium.screen.EnchanterMenu; + +import java.util.List; + +public class EnchanterBlockEntity extends BlockEntity implements MenuProvider { + private final ItemStackHandler itemHandler = new ItemStackHandler(2) { + @Override + protected void onContentsChanged(int slot) { + setChanged(); + } + }; + + private LazyOptional lazyItemHandler = LazyOptional.empty(); + + public EnchanterBlockEntity(BlockPos pos, BlockState blockState) { + super(ModBlockEntities.ENCHANTER_BLOCK_ENTITY.get(), pos, blockState); + } + + @Override + public @NotNull Component getDisplayName() { + return new TextComponent("Enchanter"); + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player player) { + return new EnchanterMenu(containerID, inventory, this); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @javax.annotation.Nullable Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return lazyItemHandler.cast(); + } + + return super.getCapability(cap, side); + } + + @Override + public void onLoad() { + super.onLoad(); + lazyItemHandler = LazyOptional.of(() -> itemHandler); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + lazyItemHandler.invalidate(); + } + + @Override + protected void saveAdditional(@NotNull CompoundTag tag) { + tag.put("inventory", itemHandler.serializeNBT()); + super.saveAdditional(tag); + } + + @Override + public void load(@NotNull CompoundTag nbt) { + super.load(nbt); + itemHandler.deserializeNBT(nbt.getCompound("inventory")); + } + + public void drops() { + SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots()); + for (int i = 0; i < itemHandler.getSlots(); i++) { + inventory.setItem(i, itemHandler.getStackInSlot(i)); + } + + if (this.level != null) { + Containers.dropContents(this.level, this.worldPosition, inventory); + } else { + Enchantrium.LOGGER.error("EnchanterBlockEntity.drops() - level is null"); + } + } + + public ItemStack getInput() { + return itemHandler.getStackInSlot(0); + } + + public void enchant(List enchantments) { + if (itemHandler.extractItem(1, 1, true).is(Items.AIR)) { + return; + } + + ItemStack input = itemHandler.extractItem(0, 1, false); + itemHandler.extractItem(1, 1, false); + for (EnchantmentInstance enchantment : enchantments) { + input.enchant(enchantment.enchantment, enchantment.level); + } + + itemHandler.setStackInSlot(0, input); + itemHandler.insertItem(0, input, false); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/item/ModItems.java b/src/main/java/xyz/nuark/enchantrium/item/ModItems.java index 1a14610..f864941 100644 --- a/src/main/java/xyz/nuark/enchantrium/item/ModItems.java +++ b/src/main/java/xyz/nuark/enchantrium/item/ModItems.java @@ -1,26 +1,17 @@ package xyz.nuark.enchantrium.item; -import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; -import org.jetbrains.annotations.NotNull; import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.setup.ModSetup; public class ModItems { - public static final CreativeModeTab ITEM_GROUP = new CreativeModeTab(Enchantrium.MOD_ID) { - @Override - public @NotNull ItemStack makeIcon() { - return new ItemStack(TEST_ITEM.get()); - } - }; - public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Enchantrium.MOD_ID); - public static final RegistryObject TEST_ITEM = ITEMS.register("test_item", () -> new Item(new Item.Properties().tab(ITEM_GROUP))); + public static final RegistryObject TEST_ITEM = ITEMS.register("test_item", () -> new Item(new Item.Properties().tab(ModSetup.ITEM_GROUP))); public static void register(IEventBus eventBus) { ITEMS.register(eventBus); diff --git a/src/main/java/xyz/nuark/enchantrium/network/Networking.java b/src/main/java/xyz/nuark/enchantrium/network/Networking.java new file mode 100644 index 0000000..b3730c9 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/network/Networking.java @@ -0,0 +1,51 @@ +package xyz.nuark.enchantrium.network; + +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; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.network.message.PacketEnchantItem; +import xyz.nuark.enchantrium.network.message.PacketSyncEnchantedItemToClient; + +public class Networking { + public static final String PROTOCOL_VERSION = "1"; + public static SimpleChannel INSTANCE; + + private static int packetId = 0; + private static int nextPacketId() { + return packetId++; + } + + public static void register() { + INSTANCE = NetworkRegistry.ChannelBuilder + .named(new ResourceLocation(Enchantrium.MOD_ID, "main")) + .networkProtocolVersion(() -> PROTOCOL_VERSION) + .clientAcceptedVersions(PROTOCOL_VERSION::equals) + .serverAcceptedVersions(PROTOCOL_VERSION::equals) + .simpleChannel(); + + INSTANCE.messageBuilder(PacketEnchantItem.class, nextPacketId(), NetworkDirection.PLAY_TO_SERVER) + .encoder(PacketEnchantItem::encode) + .decoder(PacketEnchantItem::decode) + .consumer(PacketEnchantItem::handle) + .add(); + + INSTANCE.messageBuilder(PacketSyncEnchantedItemToClient.class, nextPacketId(), NetworkDirection.PLAY_TO_CLIENT) + .encoder(PacketSyncEnchantedItemToClient::encode) + .decoder(PacketSyncEnchantedItemToClient::decode) + .consumer(PacketSyncEnchantedItemToClient::handle) + .add(); + } + + + public static void sendToServer(MSG message) { + INSTANCE.sendToServer(message); + } + + public static void sendToPlayer(MSG message, ServerPlayer player) { + INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/network/message/PacketEnchantItem.java b/src/main/java/xyz/nuark/enchantrium/network/message/PacketEnchantItem.java new file mode 100644 index 0000000..f9b141c --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/network/message/PacketEnchantItem.java @@ -0,0 +1,55 @@ +package xyz.nuark.enchantrium.network.message; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.registries.ForgeRegistries; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.block.entity.custom.EnchanterBlockEntity; +import xyz.nuark.enchantrium.network.Networking; + +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; + +public class PacketEnchantItem { + private final BlockPos blockEntityPos; + private final List enchantments; + + public PacketEnchantItem(BlockPos blockEntityPos, List enchantments) { + this.blockEntityPos = blockEntityPos; + this.enchantments = enchantments; + } + + public boolean handle(Supplier supplier) { + NetworkEvent.Context ctx = supplier.get(); + ctx.enqueueWork(() -> { + EnchanterBlockEntity ebe = (EnchanterBlockEntity)ctx.getSender().level.getBlockEntity(blockEntityPos); + ebe.enchant(enchantments); + }); + return true; + } + + public void encode(FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeBlockPos(blockEntityPos); + friendlyByteBuf.writeCollection(enchantments, (buf, enchantment) -> { + buf.writeResourceLocation(ForgeRegistries.ENCHANTMENTS.getKey(enchantment.enchantment)); + buf.writeVarInt(enchantment.level); + }); + } + + public static PacketEnchantItem decode(FriendlyByteBuf friendlyByteBuf) { + return new PacketEnchantItem( + friendlyByteBuf.readBlockPos(), + friendlyByteBuf.readList((buf) -> new EnchantmentInstance( + ForgeRegistries.ENCHANTMENTS.getValue(buf.readResourceLocation()), + buf.readVarInt() + )) + ); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/screen/EnchanterMenu.java b/src/main/java/xyz/nuark/enchantrium/screen/EnchanterMenu.java new file mode 100644 index 0000000..d26f85f --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/screen/EnchanterMenu.java @@ -0,0 +1,183 @@ +package xyz.nuark.enchantrium.screen; + +import com.google.common.collect.Lists; +import net.minecraft.Util; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.common.Tags; +import net.minecraftforge.items.CapabilityItemHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.block.ModBlocks; +import xyz.nuark.enchantrium.block.entity.custom.EnchanterBlockEntity; +import xyz.nuark.enchantrium.network.Networking; +import xyz.nuark.enchantrium.network.message.PacketEnchantItem; +import xyz.nuark.enchantrium.screen.slot.FilteredSlot; +import xyz.nuark.enchantrium.util.EnchantmentUtil; + +import java.util.List; + +public class EnchanterMenu extends AbstractContainerMenu { + private final EnchanterBlockEntity blockEntity; + private final Level level; + + private ItemStack inputStack = new ItemStack(Items.AIR); + private List enchantments = Lists.newArrayList(); + private int currentEnchantmentIndex = -1; + private final Object lock = new Object(); + + public EnchanterMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) { + this(containerId, inv, inv.player.level.getBlockEntity(extraData.readBlockPos())); + } + + public EnchanterMenu(int containerId, Inventory inv, BlockEntity entity) { + super(ModMenuTypes.ENCHANTER_MENU.get(), containerId); + checkContainerSize(inv, 2); + blockEntity = ((EnchanterBlockEntity) entity); + this.level = inv.player.level; + + addPlayerInventory(inv); + addPlayerHotbar(inv); + + this.blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(handler -> { + this.addSlot(new FilteredSlot( + handler, 0, 8, 19, + stack -> EnchantmentUtil.canBeEnchanted(stack) && !stack.isEnchanted() && !stack.is(Items.BOOK) + )); + this.addSlot(new FilteredSlot( + handler, 1, 8, 43, + stack -> stack.is(Tags.Items.GEMS_EMERALD) || stack.is(Tags.Items.INGOTS_NETHERITE) + )); + }); + } + + @Nullable + public EnchantmentInstance getCurrentEnchantment() { + synchronized (lock) { + if (blockEntity.getInput().isEmpty() || blockEntity.getInput().isEnchanted()) { + currentEnchantmentIndex = -1; + return null; + } else if (currentEnchantmentIndex == -1) { + currentEnchantmentIndex = 0; + } + if (!this.inputStack.sameItem(blockEntity.getInput())) { + this.enchantments = EnchantmentUtil.getApplicableEnchantments(blockEntity.getInput()); + currentEnchantmentIndex = 0; + this.inputStack = blockEntity.getInput(); + } + return this.enchantments.size() > 0 ? this.enchantments.get(currentEnchantmentIndex) : null; + } + } + + @Override + public boolean clickMenuButton(Player player, int buttonId) { + if (buttonId < 0 || buttonId >= 5) { + Util.logAndPauseIfInIde(player.getName() + " pressed invalid button id: " + buttonId); + return false; + } + + Enchantrium.LOGGER.debug("{} clicked button {}", player.getName(), buttonId); + synchronized (lock) { + if (buttonId == 0) { + Networking.sendToServer(new PacketEnchantItem(blockEntity.getBlockPos(), this.enchantments.stream().filter(e -> e.level > 0).toList())); + } else if (buttonId == 1) { + currentEnchantmentIndex = (currentEnchantmentIndex + 1) % enchantments.size(); + } else if (buttonId == 2) { + currentEnchantmentIndex = (currentEnchantmentIndex - 1 + enchantments.size()) % enchantments.size(); + } else if (buttonId == 3) { + var enchantment = this.enchantments.get(currentEnchantmentIndex); + this.enchantments.set(currentEnchantmentIndex, new EnchantmentInstance( + enchantment.enchantment, + enchantment.level < enchantment.enchantment.getMaxLevel() ? (enchantment.level + 1) : enchantment.level + )); + } else { + var enchantment = this.enchantments.get(currentEnchantmentIndex); + this.enchantments.set(currentEnchantmentIndex, new EnchantmentInstance( + enchantment.enchantment, + enchantment.level > 0 ? (enchantment.level - 1) : 0 + )); + } + } + return true; + } + + @Override + public boolean stillValid(@NotNull Player player) { + return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()), player, ModBlocks.ENCHANTER.get()); + } + + private void addPlayerInventory(Inventory playerInventory) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 9; j++) { + addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 86 + i * 18)); + } + } + } + + private void addPlayerHotbar(Inventory playerInventory) { + for (int i = 0; i < 9; i++) { + addSlot(new Slot(playerInventory, i, 8 + i * 18, 144)); + } + } + + // CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons + // must assign a slot number to each of the slots used by the GUI. + // For this container, we can see both the tile inventory's slots and the player inventory slots and the hotbar. + // Each time we add a Slot to the container, it automatically increases the slotIndex, which means + // 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8) + // 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35) + // 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8) + private static final int HOTBAR_SLOT_COUNT = 9; + private static final int PLAYER_INVENTORY_ROW_COUNT = 3; + private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9; + private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT; + private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT; + private static final int VANILLA_FIRST_SLOT_INDEX = 0; + private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT; + + // THIS YOU HAVE TO DEFINE! + private static final int TE_INVENTORY_SLOT_COUNT = 2; // must be the number of slots you have! + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player playerIn, int index) { + Slot sourceSlot = slots.get(index); + if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM + ItemStack sourceStack = sourceSlot.getItem(); + ItemStack copyOfSourceStack = sourceStack.copy(); + + // Check if the slot clicked is one of the vanilla container slots + if (index < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) { + // This is a vanilla container slot so merge the stack into the tile inventory + if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX + + TE_INVENTORY_SLOT_COUNT, false)) { + return ItemStack.EMPTY; // EMPTY_ITEM + } + } else if (index < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) { + // This is a TE slot so merge the stack into the players inventory + if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) { + return ItemStack.EMPTY; + } + } else { + System.out.println("Invalid slotIndex:" + index); + return ItemStack.EMPTY; + } + // If stack size == 0 (the entire stack was moved) set slot contents to null + if (sourceStack.getCount() == 0) { + sourceSlot.set(ItemStack.EMPTY); + } else { + sourceSlot.setChanged(); + } + sourceSlot.onTake(playerIn, sourceStack); + return copyOfSourceStack; + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/screen/EnchanterScreen.java b/src/main/java/xyz/nuark/enchantrium/screen/EnchanterScreen.java new file mode 100644 index 0000000..83b8fb4 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/screen/EnchanterScreen.java @@ -0,0 +1,124 @@ +package xyz.nuark.enchantrium.screen; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.network.protocol.game.ServerboundContainerButtonClickPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.NotNull; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.network.Networking; +import xyz.nuark.enchantrium.network.message.PacketEnchantItem; +import xyz.nuark.enchantrium.screen.widget.Label; + +public class EnchanterScreen extends AbstractContainerScreen { + private static final ResourceLocation TEXTURE = + new ResourceLocation(Enchantrium.MOD_ID, "textures/gui/enchanter_gui.png"); + + private Label currentEnchantmentLabel; + private Button enchantBtn; + private Button nextBtn; + private Button prevBtn; + private Button increaseLevelBtn; + private Button decreaseLevelBtn; + + public EnchanterScreen(EnchanterMenu enchanterMenu, Inventory inventory, Component title) { + super(enchanterMenu, inventory, title); + } + + @Override + protected void init() { + super.init(); + + currentEnchantmentLabel = new Label( + new TextComponent(""), + width / 2, height / 2 + 80, 0xFFFFFF, true + ); + + enchantBtn = new Button( + width / 2 - 50, height / 2 + 100, 100, 20, + new TextComponent("Enchant"), + button -> clickButton(0) + ); + nextBtn = new Button( + width / 2 + 60, height / 2 + 100, 20, 20, + new TextComponent("\u2192"), + button -> clickButton(1) + ); + prevBtn = new Button( + width / 2 - 80, height / 2 + 100, 20, 20, + new TextComponent("\u2190"), + button -> clickButton(2) + ); + + increaseLevelBtn = new Button( + width / 2 + 90, height / 2 + 100, 20, 10, + new TextComponent("\u2191"), + button -> clickButton(3) + ); + decreaseLevelBtn = new Button( + width / 2 + 90, height / 2 + 110, 20, 10, + new TextComponent("\u2193"), + button -> clickButton(4) + ); + + addRenderableWidget(enchantBtn); + addRenderableWidget(nextBtn); + addRenderableWidget(prevBtn); + addRenderableWidget(increaseLevelBtn); + addRenderableWidget(decreaseLevelBtn); + addRenderableOnly(currentEnchantmentLabel); + } + + private void clickButton(int buttonId) { + assert Minecraft.getInstance().player != null; + menu.clickMenuButton(Minecraft.getInstance().player, buttonId); + } + + @Override + protected void renderBg(@NotNull PoseStack pPoseStack, float pPartialTick, int pMouseX, int pMouseY) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, TEXTURE); + int x = (width - imageWidth) / 2; + int y = (height - imageHeight) / 2; + + this.blit(pPoseStack, x, y, 0, 0, imageWidth, imageHeight); + } + + @Override + public void render(@NotNull PoseStack pPoseStack, int mouseX, int mouseY, float delta) { + renderBackground(pPoseStack); + super.render(pPoseStack, mouseX, mouseY, delta); + renderTooltip(pPoseStack, mouseX, mouseY); + + var enchantmentInstance = menu.getCurrentEnchantment(); + if (enchantmentInstance != null) { + var enchantment = enchantmentInstance.enchantment; + var level = enchantmentInstance.level; + Component description; + if (level == 0) { + description = new TranslatableComponent(enchantment.getDescriptionId()); + } else { + description = enchantment.getFullname(level); + } + currentEnchantmentLabel.setText(description); + } else { + currentEnchantmentLabel.setText(new TextComponent("No enchantment selected")); + } + + enchantBtn.active = enchantmentInstance != null; + nextBtn.active = enchantmentInstance != null; + prevBtn.active = enchantmentInstance != null; + increaseLevelBtn.active = enchantmentInstance != null; + decreaseLevelBtn.active = enchantmentInstance != null; + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/screen/ModMenuTypes.java b/src/main/java/xyz/nuark/enchantrium/screen/ModMenuTypes.java index 8f752c4..b585370 100644 --- a/src/main/java/xyz/nuark/enchantrium/screen/ModMenuTypes.java +++ b/src/main/java/xyz/nuark/enchantrium/screen/ModMenuTypes.java @@ -14,6 +14,10 @@ public class ModMenuTypes { public static final DeferredRegister> MENUS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Enchantrium.MOD_ID); + public static final RegistryObject> ENCHANTER_MENU = registerMenuType( + EnchanterMenu::new, "enchanter_menu" + ); + private static RegistryObject> registerMenuType(IContainerFactory factory, String name) { return MENUS.register(name, () -> IForgeMenuType.create(factory)); } diff --git a/src/main/java/xyz/nuark/enchantrium/screen/slot/FilteredSlot.java b/src/main/java/xyz/nuark/enchantrium/screen/slot/FilteredSlot.java new file mode 100644 index 0000000..9bd9628 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/screen/slot/FilteredSlot.java @@ -0,0 +1,22 @@ +package xyz.nuark.enchantrium.screen.slot; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +public class FilteredSlot extends SlotItemHandler { + Predicate filter; + + public FilteredSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition, Predicate filter) { + super(itemHandler, index, xPosition, yPosition); + this.filter = filter; + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return filter.test(stack); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/screen/widget/Label.java b/src/main/java/xyz/nuark/enchantrium/screen/widget/Label.java new file mode 100644 index 0000000..ab4b264 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/screen/widget/Label.java @@ -0,0 +1,44 @@ +package xyz.nuark.enchantrium.screen.widget; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.gui.components.Widget; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; + +@OnlyIn(Dist.CLIENT) +public class Label implements Widget { + private Component text; + private final int x; + private final int y; + private final int color; + private final boolean centered; + + public Label(Component p_120736_, int p_120737_, int p_120738_, int p_120739_, boolean centered) { + this.text = p_120736_.copy(); + this.x = p_120737_; + this.y = p_120738_; + this.color = p_120739_; + this.centered = centered; + } + + public void render(@NotNull PoseStack p_175036_, int p_175037_, int p_175038_, float p_175039_) { + if (centered) { + GuiComponent.drawCenteredString(p_175036_, Minecraft.getInstance().font, this.text, this.x, this.y, this.color); + } else { + GuiComponent.drawString(p_175036_, Minecraft.getInstance().font, this.text, this.x, this.y, this.color); + } + } + + public void setText(Component p_175041_) { + this.text = p_175041_; + } + + public Component getText() { + return this.text; + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/setup/ClientSetup.java b/src/main/java/xyz/nuark/enchantrium/setup/ClientSetup.java new file mode 100644 index 0000000..490c01d --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/setup/ClientSetup.java @@ -0,0 +1,15 @@ +package xyz.nuark.enchantrium.setup; + +import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import xyz.nuark.enchantrium.screen.EnchanterScreen; +import xyz.nuark.enchantrium.screen.ModMenuTypes; + +public class ClientSetup { + public static void init(final FMLClientSetupEvent event) { + event.enqueueWork(() -> { + MenuScreens.register(ModMenuTypes.ENCHANTER_MENU.get(), EnchanterScreen::new); + }); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/setup/ModSetup.java b/src/main/java/xyz/nuark/enchantrium/setup/ModSetup.java new file mode 100644 index 0000000..2f32705 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/setup/ModSetup.java @@ -0,0 +1,30 @@ +package xyz.nuark.enchantrium.setup; + +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import org.jetbrains.annotations.NotNull; +import xyz.nuark.enchantrium.Enchantrium; +import xyz.nuark.enchantrium.item.ModItems; +import xyz.nuark.enchantrium.network.Networking; + +@Mod.EventBusSubscriber(modid = Enchantrium.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class ModSetup { + public static final CreativeModeTab ITEM_GROUP = new CreativeModeTab(Enchantrium.MOD_ID) { + @Override + public @NotNull ItemStack makeIcon() { + return new ItemStack(ModItems.TEST_ITEM.get()); + } + }; + + public static void setup() { + IEventBus bus = MinecraftForge.EVENT_BUS; + } + + public static void init(FMLCommonSetupEvent event) { + Networking.register(); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/setup/Registration.java b/src/main/java/xyz/nuark/enchantrium/setup/Registration.java new file mode 100644 index 0000000..3b26df3 --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/setup/Registration.java @@ -0,0 +1,16 @@ +package xyz.nuark.enchantrium.setup; + +import net.minecraftforge.eventbus.api.IEventBus; +import xyz.nuark.enchantrium.block.ModBlocks; +import xyz.nuark.enchantrium.block.entity.ModBlockEntities; +import xyz.nuark.enchantrium.item.ModItems; +import xyz.nuark.enchantrium.screen.ModMenuTypes; + +public class Registration { + public static void register(IEventBus eventBus) { + ModItems.register(eventBus); + ModBlocks.register(eventBus); + ModBlockEntities.register(eventBus); + ModMenuTypes.register(eventBus); + } +} diff --git a/src/main/java/xyz/nuark/enchantrium/util/EnchantmentUtil.java b/src/main/java/xyz/nuark/enchantrium/util/EnchantmentUtil.java new file mode 100644 index 0000000..6a10a0f --- /dev/null +++ b/src/main/java/xyz/nuark/enchantrium/util/EnchantmentUtil.java @@ -0,0 +1,27 @@ +package xyz.nuark.enchantrium.util; + +import com.google.common.collect.Lists; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentInstance; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.List; + +public class EnchantmentUtil { + public static boolean canBeEnchanted(ItemStack stack) { + return stack.getItem().isEnchantable(stack); + } + + public static List getApplicableEnchantments(ItemStack itemStack) { + List list = Lists.newArrayList(); + + for (Enchantment enchantment : ForgeRegistries.ENCHANTMENTS) { + if (enchantment.canEnchant(itemStack) && !enchantment.isCurse()) { + list.add(new EnchantmentInstance(enchantment, 0)); + } + } + + return list; + } +} diff --git a/src/main/resources/assets/enchantrium/textures/gui/enchanter_gui.png b/src/main/resources/assets/enchantrium/textures/gui/enchanter_gui.png new file mode 100644 index 0000000..e490f5f Binary files /dev/null and b/src/main/resources/assets/enchantrium/textures/gui/enchanter_gui.png differ