feat: build crafting type and block entity, pc change
This commit is contained in:
1 parent
6e224e1fdf
commit
ce1bd9052f
11 files changed
+384
-6
No files matched your search
@@ -8,7 +8,7 @@ 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");
|
||||
private static final Identifier TEXTURE = Identifier.of("textures/gui/container/dispenser.png");
|
||||
|
||||
public MagicalCraftingScreen(MagicalCraftingScreenHandler handler, PlayerInventory inventory, Text title) {
|
||||
super(handler, inventory, title);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.uncreativebunch.magicmod;
|
||||
|
||||
import com.uncreativebunch.magicmod.block.ModBlocks;
|
||||
import com.uncreativebunch.magicmod.block.entity.ModBlockEntityTypes;
|
||||
import com.uncreativebunch.magicmod.item.ModItemGroups;
|
||||
import com.uncreativebunch.magicmod.item.ModItems;
|
||||
import com.uncreativebunch.magicmod.recipe.ModRecipeTypes;
|
||||
import com.uncreativebunch.magicmod.screen.ModScreenHandlers;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
@@ -31,6 +33,8 @@ public class MagicMod implements ModInitializer {
|
||||
ModItems.init();
|
||||
ModItemGroups.init();
|
||||
ModScreenHandlers.init();
|
||||
ModRecipeTypes.init();
|
||||
ModBlockEntityTypes.init();
|
||||
LOGGER.info("Finished Magic Mod initialization!");
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package com.uncreativebunch.magicmod.block.crafting;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.uncreativebunch.magicmod.MagicMod;
|
||||
import com.uncreativebunch.magicmod.block.entity.MagicalCrafterBlockEntity;
|
||||
import com.uncreativebunch.magicmod.screen.MagicalCraftingScreenHandler;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.CraftingTableBlock;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.enums.SlabType;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.LightningEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@@ -12,19 +14,34 @@ import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandlerContext;
|
||||
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
||||
import net.minecraft.stat.Stats;
|
||||
import net.minecraft.state.StateManager;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class MagicalCrafterBlock extends CraftingTableBlock {
|
||||
public class MagicalCrafterBlock extends BlockWithEntity {
|
||||
|
||||
private static final MapCodec<MagicalCrafterBlock> CODEC = null;
|
||||
|
||||
/**
|
||||
* Creates a new MagicalCrafterBlock.
|
||||
* @param settings The settings of the block.
|
||||
*/
|
||||
public MagicalCrafterBlock(AbstractBlock.Settings settings) { super(settings); }
|
||||
public MagicalCrafterBlock(AbstractBlock.Settings settings) {
|
||||
super(settings);
|
||||
this.setDefaultState(
|
||||
this.stateManager.getDefaultState()
|
||||
.with(SlabBlock.TYPE, SlabType.BOTTOM)
|
||||
.with(SlabBlock.WATERLOGGED, false)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BlockWithEntity> getCodec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever this block is used.
|
||||
@@ -71,4 +88,18 @@ public class MagicalCrafterBlock extends CraftingTableBlock {
|
||||
Text.translatable("container.magical_crafting_table")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new MagicalCrafterBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds properties to the block state. This crafting table is a slab, so it has a type and waterlogged property.
|
||||
* @param builder The {@link StateManager.Builder} to add properties to.
|
||||
*/
|
||||
@Override
|
||||
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
|
||||
builder.add(SlabBlock.TYPE, SlabBlock.WATERLOGGED);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.uncreativebunch.magicmod.block.entity;
|
||||
|
||||
import com.uncreativebunch.magicmod.util.ImplementedInventory;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class MagicalCrafterBlockEntity extends BlockEntity implements ImplementedInventory {
|
||||
protected DefaultedList<ItemStack> items = DefaultedList.ofSize(3, ItemStack.EMPTY);
|
||||
|
||||
@Override
|
||||
public DefaultedList<ItemStack> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public MagicalCrafterBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntityTypes.MAGICAL_CRAFTING_TABLE, pos, state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.uncreativebunch.magicmod.block.entity;
|
||||
|
||||
import com.uncreativebunch.magicmod.block.ModBlocks;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
|
||||
public class ModBlockEntityTypes {
|
||||
|
||||
public static final BlockEntityType<MagicalCrafterBlockEntity> MAGICAL_CRAFTING_TABLE = register(
|
||||
"magical_crafting_table",
|
||||
FabricBlockEntityTypeBuilder.create(MagicalCrafterBlockEntity::new, ModBlocks.MAGICAL_CRAFTING_TABLE).build()
|
||||
);
|
||||
|
||||
public static <T extends BlockEntity> BlockEntityType<T> register(String id, BlockEntityType<T> type) {
|
||||
return Registry.register(Registries.BLOCK_ENTITY_TYPE, id, type);
|
||||
}
|
||||
|
||||
public static void init() {}
|
||||
}
|
||||
@@ -21,6 +21,16 @@ public class StickTagRecipeProvider extends FabricRecipeProvider {
|
||||
public void generate() {
|
||||
MagicMod.LOGGER.info("Hello from the recipe provider!");
|
||||
MagicMod.LOGGER.info("This cannot scan recipes - apparently they don't exist in this context.");
|
||||
|
||||
// Create a builder for our custom recipe types. This will allow for type-safe creation of recipes.
|
||||
// This builder should likely be defined as a static class or function within the main Recipe class.
|
||||
// RecipeBuilder.create(
|
||||
// Ingredient.fromTag(ItemTags.MAGIC_MATERIALS),
|
||||
// Ingredient.fromTag(ItemTags.MAGIC_CORES),
|
||||
// Ingredient.fromTag(ItemTags.MAGIC_GRIPS),
|
||||
// ModItems.BASIC_WAND.getDefaultStack(),
|
||||
// new Identifier("magic_mod", "basic_wand_crafting")
|
||||
// );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.uncreativebunch.magicmod.recipe;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.recipe.input.RecipeInput;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record MagicShapedInput(List<ItemStack> stacks) implements RecipeInput {
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int slot) {
|
||||
return stacks.get(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return stacks.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return RecipeInput.super.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.uncreativebunch.magicmod.recipe;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.recipe.*;
|
||||
import net.minecraft.recipe.book.RecipeBookCategory;
|
||||
import net.minecraft.recipe.display.RecipeDisplay;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MagicShapedRecipe implements Recipe<MagicShapedInput> {
|
||||
private final Ingredient inputA;
|
||||
private final Ingredient inputB;
|
||||
private final ItemStack output;
|
||||
private final Identifier id;
|
||||
|
||||
public MagicShapedRecipe(Ingredient inputA, Ingredient inputB, ItemStack output, Identifier id) {
|
||||
this.inputA = inputA;
|
||||
this.inputB = inputB;
|
||||
this.output = output;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Ingredient getInputA() {
|
||||
return this.inputA;
|
||||
}
|
||||
|
||||
public Ingredient getInputB() {
|
||||
return inputB;
|
||||
}
|
||||
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public boolean fits(int width, int height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(MagicShapedInput input, World world) {
|
||||
if (input.stacks().size() < 2) return false;
|
||||
return inputA.test(input.stacks().getFirst()) && inputB.test(input.stacks().get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack craft(MagicShapedInput input, RegistryWrapper.WrapperLookup registries) {
|
||||
return this.output.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoredInRecipeBook() {
|
||||
return Recipe.super.isIgnoredInRecipeBook();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showNotification() {
|
||||
return Recipe.super.showNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return Recipe.super.getGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeSerializer<? extends Recipe<MagicShapedInput>> getSerializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Implement the recipe's type.
|
||||
public static class Type implements RecipeType<MagicShapedRecipe> {
|
||||
private Type() { }
|
||||
public static final Type INSTANCE = new Type();
|
||||
public static final String ID = "magic_crafting";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the type of this recipe}
|
||||
*
|
||||
* <p>The {@code type} in the recipe JSON format is the {@linkplain
|
||||
* #getSerializer() serializer} instead.
|
||||
*/
|
||||
@Override
|
||||
public RecipeType<? extends Recipe<MagicShapedInput>> getType() {
|
||||
return ModRecipeTypes.MAGIC_SHAPED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngredientPlacement getIngredientPlacement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecipeDisplay> getDisplays() {
|
||||
return Recipe.super.getDisplays();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeBookCategory getRecipeBookCategory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Serializer definition
|
||||
public static class Serializer implements RecipeSerializer<MagicShapedRecipe> {
|
||||
public static final Serializer INSTANCE = new Serializer();
|
||||
|
||||
private static final MapCodec<MagicShapedRecipe> CODEC = RecordCodecBuilder.mapCodec(
|
||||
// This function essentially creates a way to deserialize from a JSON using the constructor's
|
||||
// parameters, as defined above.
|
||||
instance -> instance.group(
|
||||
Ingredient.CODEC.fieldOf("inputA").forGetter(MagicShapedRecipe::getInputA),
|
||||
Ingredient.CODEC.fieldOf("inputB").forGetter(MagicShapedRecipe::getInputB),
|
||||
ItemStack.CODEC.fieldOf("output").forGetter(MagicShapedRecipe::getOutput),
|
||||
Identifier.CODEC.fieldOf("id").forGetter(MagicShapedRecipe::getId)
|
||||
).apply(instance, MagicShapedRecipe::new)
|
||||
);
|
||||
|
||||
private static final PacketCodec<RegistryByteBuf, MagicShapedRecipe> PACKET_CODEC = PacketCodec.tuple(
|
||||
Ingredient.PACKET_CODEC, MagicShapedRecipe::getInputA,
|
||||
Ingredient.PACKET_CODEC, MagicShapedRecipe::getInputB,
|
||||
ItemStack.PACKET_CODEC, MagicShapedRecipe::getOutput,
|
||||
Identifier.PACKET_CODEC, MagicShapedRecipe::getId,
|
||||
MagicShapedRecipe::new
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the codec for this serializer. This determines how the recipe is parsed from JSON.
|
||||
* @return The codec for this serializer.
|
||||
*/
|
||||
@Override
|
||||
public MapCodec<MagicShapedRecipe> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet codec for this serializer. This determines how the recipe is parsed from packets.
|
||||
* @return The packet codec for this serializer.
|
||||
*/
|
||||
@Override
|
||||
public PacketCodec<RegistryByteBuf, MagicShapedRecipe> packetCodec() {
|
||||
return PACKET_CODEC;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.uncreativebunch.magicmod.recipe;
|
||||
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeSerializer;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
|
||||
public class ModRecipeSerializers {
|
||||
public static RecipeSerializer<MagicShapedRecipe> MAGIC_SHAPED = new MagicShapedRecipe.Serializer();
|
||||
|
||||
public static <T extends Recipe<?>> RecipeSerializer<T> register(String id, RecipeSerializer<T> type) {
|
||||
return Registry.register(Registries.RECIPE_SERIALIZER, id, type);
|
||||
}
|
||||
|
||||
public static void init() {}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.uncreativebunch.magicmod.recipe;
|
||||
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.recipe.RecipeType;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
|
||||
public class ModRecipeTypes {
|
||||
public static final RecipeType<MagicShapedRecipe> MAGIC_SHAPED = register("magic_shaped", MagicShapedRecipe.Type.INSTANCE);
|
||||
|
||||
public static <T extends Recipe<?>> RecipeType<T> register(String id, RecipeType<T> type) {
|
||||
return Registry.register(Registries.RECIPE_TYPE, id, type);
|
||||
}
|
||||
|
||||
public static void init() {}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.uncreativebunch.magicmod.util;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventories;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
public interface ImplementedInventory extends Inventory {
|
||||
DefaultedList<ItemStack> getItems();
|
||||
|
||||
static ImplementedInventory of(DefaultedList<ItemStack> items) {
|
||||
return () -> items;
|
||||
}
|
||||
|
||||
static ImplementedInventory ofSize(int size) {
|
||||
return of(DefaultedList.ofSize(size, ItemStack.EMPTY));
|
||||
}
|
||||
|
||||
@Override
|
||||
default int size() {
|
||||
return getItems().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean isEmpty() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
ItemStack stack = getStack(i);
|
||||
if (!stack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default ItemStack getStack(int slot) {
|
||||
return getItems().get(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ItemStack removeStack(int slot, int count) {
|
||||
ItemStack result = Inventories.splitStack(getItems(), slot, count);
|
||||
if (!result.isEmpty()) {
|
||||
markDirty();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
default ItemStack removeStack(int slot) {
|
||||
return Inventories.removeStack(getItems(), slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setStack(int slot, ItemStack stack) {
|
||||
getItems().set(slot, stack);
|
||||
if (stack.getCount() > stack.getMaxCount()) {
|
||||
stack.setCount(stack.getMaxCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clear() {
|
||||
getItems().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void markDirty() {
|
||||
// Doesn't need to be overridden in this case.
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean canPlayerUse(PlayerEntity player) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user