feat: add custom magical crafting screen handler
This commit is contained in:
1 parent
ce56bbe9da
commit
6e224e1fdf
9 files changed
+211
-7
No files matched your search
+2
-1
@@ -7,6 +7,7 @@ org.gradle.parallel=true
|
|||||||
minecraft_version=1.21.5
|
minecraft_version=1.21.5
|
||||||
yarn_mappings=1.21.5+build.1
|
yarn_mappings=1.21.5+build.1
|
||||||
loader_version=0.16.12
|
loader_version=0.16.12
|
||||||
|
loom_version=1.11-SNAPSHOT
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.0.0
|
mod_version=1.0.0
|
||||||
@@ -14,4 +15,4 @@ maven_group=com.uncreativebunch.magicmod
|
|||||||
archives_base_name=magic_mod
|
archives_base_name=magic_mod
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
fabric_version=0.119.9+1.21.5
|
fabric_version=0.128.2+1.21.5
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
package com.uncreativebunch.magicmod;
|
package com.uncreativebunch.magicmod;
|
||||||
|
|
||||||
|
import com.uncreativebunch.magicmod.screen.MagicalCraftingScreen;
|
||||||
|
import com.uncreativebunch.magicmod.screen.ModScreenHandlers;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreens;
|
||||||
|
|
||||||
public class MagicModClient implements ClientModInitializer {
|
public class MagicModClient implements ClientModInitializer {
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient() {
|
public void onInitializeClient() {
|
||||||
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
||||||
|
HandledScreens.register(ModScreenHandlers.MAGICAL_CRAFTING_SCREEN_HANDLER, MagicalCraftingScreen::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.uncreativebunch.magicmod.screen;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.DrawContext;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.render.RenderLayer;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class MagicalCraftingScreen extends HandledScreen<MagicalCraftingScreenHandler> {
|
||||||
|
private static final Identifier TEXTURE = Identifier.of("textures/gui/container/anvil.png");
|
||||||
|
|
||||||
|
public MagicalCraftingScreen(MagicalCraftingScreenHandler handler, PlayerInventory inventory, Text title) {
|
||||||
|
super(handler, inventory, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
|
||||||
|
context.drawTexture(RenderLayer::getGuiTextured, TEXTURE,
|
||||||
|
this.x, (this.height - this.backgroundHeight) / 2,
|
||||||
|
0.0F, 0.0F,
|
||||||
|
this.backgroundWidth, this.backgroundHeight,
|
||||||
|
256, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
renderBackground(context, mouseX, mouseY, delta);
|
||||||
|
super.render(context, mouseX, mouseY, delta);
|
||||||
|
drawMouseoverTooltip(context, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
// Centers the title
|
||||||
|
titleX = (backgroundWidth - textRenderer.getWidth(title)) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.uncreativebunch.magicmod;
|
|||||||
import com.uncreativebunch.magicmod.block.ModBlocks;
|
import com.uncreativebunch.magicmod.block.ModBlocks;
|
||||||
import com.uncreativebunch.magicmod.item.ModItemGroups;
|
import com.uncreativebunch.magicmod.item.ModItemGroups;
|
||||||
import com.uncreativebunch.magicmod.item.ModItems;
|
import com.uncreativebunch.magicmod.item.ModItems;
|
||||||
|
import com.uncreativebunch.magicmod.screen.ModScreenHandlers;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -29,6 +30,7 @@ public class MagicMod implements ModInitializer {
|
|||||||
ModBlocks.init();
|
ModBlocks.init();
|
||||||
ModItems.init();
|
ModItems.init();
|
||||||
ModItemGroups.init();
|
ModItemGroups.init();
|
||||||
|
ModScreenHandlers.init();
|
||||||
LOGGER.info("Finished Magic Mod initialization!");
|
LOGGER.info("Finished Magic Mod initialization!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,6 @@ import com.uncreativebunch.magicmod.MagicMod;
|
|||||||
import com.uncreativebunch.magicmod.block.crafting.MagicalCrafterBlock;
|
import com.uncreativebunch.magicmod.block.crafting.MagicalCrafterBlock;
|
||||||
import net.minecraft.block.AbstractBlock;
|
import net.minecraft.block.AbstractBlock;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.SlabBlock;
|
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
@@ -19,6 +18,7 @@ import java.util.function.Function;
|
|||||||
public class ModBlocks {
|
public class ModBlocks {
|
||||||
//region Block Definitions
|
//region Block Definitions
|
||||||
|
|
||||||
|
/** The magical crafting table block. */
|
||||||
public static final Block MAGICAL_CRAFTING_TABLE = register(
|
public static final Block MAGICAL_CRAFTING_TABLE = register(
|
||||||
"magical_crafting_table",
|
"magical_crafting_table",
|
||||||
MagicalCrafterBlock::new,
|
MagicalCrafterBlock::new,
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
package com.uncreativebunch.magicmod.block.crafting;
|
package com.uncreativebunch.magicmod.block.crafting;
|
||||||
|
|
||||||
import com.uncreativebunch.magicmod.MagicMod;
|
import com.uncreativebunch.magicmod.MagicMod;
|
||||||
|
import com.uncreativebunch.magicmod.screen.MagicalCraftingScreenHandler;
|
||||||
import net.minecraft.block.AbstractBlock;
|
import net.minecraft.block.AbstractBlock;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.SlabBlock;
|
import net.minecraft.block.CraftingTableBlock;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.LightningEntity;
|
import net.minecraft.entity.LightningEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
||||||
|
import net.minecraft.stat.Stats;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
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.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class MagicalCrafterBlock extends SlabBlock {
|
public class MagicalCrafterBlock extends CraftingTableBlock {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new MagicalCrafterBlock.
|
* Creates a new MagicalCrafterBlock.
|
||||||
@@ -21,7 +27,8 @@ public class MagicalCrafterBlock extends SlabBlock {
|
|||||||
public MagicalCrafterBlock(AbstractBlock.Settings settings) { super(settings); }
|
public MagicalCrafterBlock(AbstractBlock.Settings settings) { super(settings); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Occurs whenever this block is used. This is intended to open a crafting window in the future.
|
* Occurs whenever this block is used.
|
||||||
|
* It opens a crafting window and summons lightning on the interacting player.
|
||||||
* @param state The current {@link BlockState} of this block.
|
* @param state The current {@link BlockState} of this block.
|
||||||
* @param world The {@link World} that this block exists in.
|
* @param world The {@link World} that this block exists in.
|
||||||
* @param pos The {@link BlockPos} that this block is at.
|
* @param pos The {@link BlockPos} that this block is at.
|
||||||
@@ -31,8 +38,10 @@ public class MagicalCrafterBlock extends SlabBlock {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
|
||||||
if (world.isClient) return ActionResult.PASS;
|
// The server is the game's sole source of truth. Even though some things are displayed
|
||||||
|
// on the client, these actions usually, with very few exceptions, are routed and triggered
|
||||||
|
// through the server first.
|
||||||
|
if (!world.isClient) {
|
||||||
MagicMod.LOGGER.info("Block was used at location {}", pos.toShortString());
|
MagicMod.LOGGER.info("Block was used at location {}", pos.toShortString());
|
||||||
|
|
||||||
MagicMod.LOGGER.info("Electrocuting player...");
|
MagicMod.LOGGER.info("Electrocuting player...");
|
||||||
@@ -42,6 +51,24 @@ public class MagicalCrafterBlock extends SlabBlock {
|
|||||||
world.spawnEntity(lightningEntity);
|
world.spawnEntity(lightningEntity);
|
||||||
MagicMod.LOGGER.info("Player electrocuted.");
|
MagicMod.LOGGER.info("Player electrocuted.");
|
||||||
|
|
||||||
|
NamedScreenHandlerFactory screenFactory = state.createScreenHandlerFactory(world, pos);
|
||||||
|
if (screenFactory != null) {
|
||||||
|
player.openHandledScreen(screenFactory);
|
||||||
|
player.incrementStat(Stats.INTERACT_WITH_CRAFTING_TABLE);
|
||||||
|
} else {
|
||||||
|
MagicMod.LOGGER.info("NamedScreenHandlerFactory returned from the BlockState is null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) {
|
||||||
|
return new SimpleNamedScreenHandlerFactory(
|
||||||
|
((syncId, playerInventory, player) ->
|
||||||
|
new MagicalCraftingScreenHandler(syncId, playerInventory, ScreenHandlerContext.create(world, pos))),
|
||||||
|
Text.translatable("container.magical_crafting_table")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package com.uncreativebunch.magicmod.screen;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.inventory.CraftingInventory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
|
||||||
|
public class MagicalCraftingScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
|
private final ScreenHandlerContext context;
|
||||||
|
private final CraftingInventory inventory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client-side constructor.
|
||||||
|
* @param syncId The sync ID that's sent from the server.
|
||||||
|
* @param playerInventory The player's inventory.
|
||||||
|
*/
|
||||||
|
public MagicalCraftingScreenHandler(int syncId, PlayerInventory playerInventory) {
|
||||||
|
this(syncId, playerInventory, ScreenHandlerContext.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server-side constructor. The server knows the player's inventory and so can provide it to the client.
|
||||||
|
* It handles creating the inventory slots and syncs all information from the server to the client.
|
||||||
|
* @param syncId The sync ID that's sent from the server.
|
||||||
|
* @param playerInventory The player's inventory.
|
||||||
|
* @param screenHandlerContext The context of the screen handler. Not sure if this is needed anymore.
|
||||||
|
*/
|
||||||
|
public MagicalCraftingScreenHandler(int syncId, PlayerInventory playerInventory, ScreenHandlerContext screenHandlerContext) {
|
||||||
|
super(ModScreenHandlers.MAGICAL_CRAFTING_SCREEN_HANDLER, syncId);
|
||||||
|
this.context = screenHandlerContext;
|
||||||
|
this.inventory = new CraftingInventory(this, 3, 3);
|
||||||
|
|
||||||
|
// Ensure that the crafting inventory is the correct size.
|
||||||
|
checkSize(inventory, 9);
|
||||||
|
|
||||||
|
// Ensure that the inventory's custom logic runs (if any)
|
||||||
|
inventory.onOpen(playerInventory.player);
|
||||||
|
|
||||||
|
// Place all inventory slots within the screen. This piece doesn't actually render the background of the slots,
|
||||||
|
// as this is handled by the client-side application (the Screen), but it does tell the screen where to render.
|
||||||
|
int m, l;
|
||||||
|
for (m = 0; m < 3; m++) {
|
||||||
|
for (l = 0; l < 3; l++) {
|
||||||
|
// Create the crafting slots. This is good for a 3x3 grid of crafting slots. It registers them to a
|
||||||
|
// specific inventory and location on the client's screen, relative to the screen's size and origin.
|
||||||
|
this.addSlot(new Slot(inventory, l + m * 3, 62 + l * 18, 17 + m * 18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all player inventory slots. Start with the main inventory, then the hotbar.
|
||||||
|
for (m = 0; m < 3; m++) {
|
||||||
|
for (l = 0; l < 9; l++) {
|
||||||
|
this.addSlot(new Slot(playerInventory, l + m * 9 + 9, 8 + l * 18, 84 + m * 18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (m = 0; m < 9; m++) {
|
||||||
|
this.addSlot(new Slot(playerInventory, m, 8 + m * 18, 142));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified slot index is within the crafting inventory.
|
||||||
|
* @param slotIndex The slot index to check.
|
||||||
|
* @return True if the slot index is within the crafting inventory, false otherwise.
|
||||||
|
*/
|
||||||
|
protected boolean isCraftingInventorySlot(int slotIndex) {
|
||||||
|
return slotIndex < this.inventory.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack quickMove(PlayerEntity player, int slotIndex) {
|
||||||
|
// If the slot is in the crafting inventory, move it to the player's inventory.
|
||||||
|
// Otherwise, don't move it at all.
|
||||||
|
ItemStack newStack = ItemStack.EMPTY;
|
||||||
|
Slot slot = this.slots.get(slotIndex);
|
||||||
|
|
||||||
|
if (slot.hasStack()) {
|
||||||
|
ItemStack stack = slot.getStack();
|
||||||
|
newStack = stack.copy();
|
||||||
|
if (isCraftingInventorySlot(slotIndex)) {
|
||||||
|
// Attempt to move the stack into the player's inventory.
|
||||||
|
if (!this.insertItem(stack, this.inventory.size(), this.slots.size(), true)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Don't move the stack.
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the stack was moved. If moved entirely, empty the slot.
|
||||||
|
if (stack.isEmpty()) {
|
||||||
|
slot.setStack(ItemStack.EMPTY);
|
||||||
|
} else {
|
||||||
|
slot.markDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(PlayerEntity player) {
|
||||||
|
return inventory.canPlayerUse(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.uncreativebunch.magicmod.screen;
|
||||||
|
|
||||||
|
import com.uncreativebunch.magicmod.MagicMod;
|
||||||
|
import net.minecraft.registry.Registries;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.resource.featuretoggle.FeatureFlags;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
|
|
||||||
|
public class ModScreenHandlers {
|
||||||
|
public static final ScreenHandlerType<MagicalCraftingScreenHandler> MAGICAL_CRAFTING_SCREEN_HANDLER =
|
||||||
|
register("magical_crafting", MagicalCraftingScreenHandler::new);
|
||||||
|
|
||||||
|
private static <T extends ScreenHandler> ScreenHandlerType<T> register(String id, ScreenHandlerType.Factory<T> factory) {
|
||||||
|
return Registry.register(Registries.SCREEN_HANDLER, id, new ScreenHandlerType<>(factory, FeatureFlags.VANILLA_FEATURES));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
MagicMod.LOGGER.info("Screen handlers initialized.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"item.magic_mod.pale_oak_stick": "Pale Oak Stick",
|
"item.magic_mod.pale_oak_stick": "Pale Oak Stick",
|
||||||
"item.magic_mod.spruce_stick": "Spruce Stick",
|
"item.magic_mod.spruce_stick": "Spruce Stick",
|
||||||
"item.magic_mod.warped_stick": "Warped Stick",
|
"item.magic_mod.warped_stick": "Warped Stick",
|
||||||
|
"container.magical_crafting_table": "Magical Crafting",
|
||||||
"magic_mod.magic_group": "Testing Mod Items",
|
"magic_mod.magic_group": "Testing Mod Items",
|
||||||
"tag.item.magic_mod.sticks": "Sticks"
|
"tag.item.magic_mod.sticks": "Sticks"
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user