Jump to content

Recommended Posts

Posted (edited)

Hello!

I'm writing a Minecraft based on tech and machines, and I'm making a furnace-esque machine for processing ores. However, I can't seem to get the recipes to work. Whenever I put the ore into the slot, nothing happens. I added the inventory property to the watchlist and it showed that it was detecting the block in the right slot, but for some reason its not triggering crafting. I'm at a loss right now. Please note that I am new to modding, and I followed a tutorial for this code, so I don't really know code conventions yet. 

Also, there's no crashes at all. No errors thrown. It just doesn't do anything.

Below is some of the associated code:

1) The .json files for the recipes

{
  "type": "darkcollective:ore_refining",
  "ingredients": [
    {
      "item": "darkcollective:aernium_ore"
    }
  ],
  "output": {
    "count": 2,
    "item": "darkcollective:aernium_ingot"
  }
}

2) The code in the OreRefineryEntityClass that looks for the recipe and, if found, starts the crafting

private boolean hasRecipe() {
        Optional<OreRefineryRecipe> recipe = getCurrentRecipe();

        System.out.println(recipe);

        if(recipe.isEmpty()) {
            return false;
        }
        ItemStack result = recipe.get().getResultItem(getLevel().registryAccess());

        return canInsertAmountIntoOutputSlot(result.getCount()) && canInsertItemIntoOutputSlot(result.getItem());
    }

    private Optional<OreRefineryRecipe> getCurrentRecipe() {
        SimpleContainer inventory = new SimpleContainer(this.itemHandler.getSlots());
        for(int i = 0; i < itemHandler.getSlots(); i++) {
            inventory.setItem(i, this.itemHandler.getStackInSlot(i));
        }

        return this.level.getRecipeManager().getRecipeFor(OreRefineryRecipe.Type.INSTANCE, inventory, level);
    }

3) The code for the RecipeSerializer.

    public static class Serializer implements RecipeSerializer<OreRefineryRecipe>{

        public static final Serializer INSTANCE = new Serializer();
        public static final ResourceLocation ID = new ResourceLocation(DarkCollective.ModID, "ore_refining");

        @Override
        public OreRefineryRecipe fromJson(ResourceLocation recipeId, JsonObject serializedRecipe) {
            ItemStack output = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result"));

            JsonArray ingredients = GsonHelper.getAsJsonArray(serializedRecipe, "ingredients");
            NonNullList<Ingredient> inputs = NonNullList.withSize(1, Ingredient.EMPTY);

            for(int i = 0; i < inputs.size(); i++) {
                inputs.set(i, Ingredient.fromJson(ingredients.get(i)));
            }

            return new OreRefineryRecipe(inputs, output, recipeId);
        }

        @Override
        public @Nullable OreRefineryRecipe fromNetwork(ResourceLocation recipeID, FriendlyByteBuf buffer) {
            NonNullList<Ingredient> inputs = NonNullList.withSize(buffer.readInt(), Ingredient.EMPTY);

            for(int i = 0; i < inputs.size(); i++) {
                inputs.set(i, Ingredient.fromNetwork(buffer));
            }

            ItemStack output = buffer.readItem();
            return new OreRefineryRecipe(inputs, output, recipeID);
        }

        @Override
        public void toNetwork(FriendlyByteBuf buffer, OreRefineryRecipe recipe) {
            buffer.writeInt(recipe.inputItems.size());

            for (Ingredient ingredient : recipe.getIngredients()) {
                ingredient.toNetwork(buffer);
            }

            buffer.writeItemStack(recipe.getResultItem(null), false);

        }
    }

If there's anything I missed, just tell me and I'd be happy to send.

Also, I'm on version 1.20.

Thank you!

Edited by BlueFFlame
Clarification
Posted (edited)

Show more of your code, ideally a Git repo.

BTW, wrong Forum, your questions has nothing to do with ForgeGradle.
But please do not create a new thread, but remember it for the next time.

Edited by Luis_ST
Posted
On 11/4/2023 at 6:33 AM, BlueFFlame said:

Ah, ok. What forum should I post in for next time?

Direktly in Modder Support

Have you used debugger to check your code?
At first look the code should work, is a recipe found in the tick method?

Posted

Yeah, I’ve looked at it in the debugger. There’s no recipe found, as the getRecipeMethod is returning null. I’m not sure why though, as the inventory isn’t null: it’s detecting the correct item in the correct slot. 

Posted
46 minutes ago, Luis_ST said:

Direktly in Modder Support

Have you used debugger to check your code?
At first look the code should work, is a recipe found in the tick method?

Quoting this becuase I realized I wasn’t quoting before.

Posted
5 hours ago, BlueFFlame said:

Yeah, I’ve looked at it in the debugger. There’s no recipe found, as the getRecipeMethod is returning null. I’m not sure why though, as the inventory isn’t null: it’s detecting the correct item in the correct slot. 

RecipeManager#getRecipeFor uses OreRefineryRecipe#matches to enure the items in the container are valid for the given SimpleContainer are you sure the implemention is correct since you have a NonNullList as input but you only use the first item of the list?

Posted
2 hours ago, Luis_ST said:

RecipeManager#getRecipeFor uses OreRefineryRecipe#matches to enure the items in the container are valid for the given SimpleContainer are you sure the implemention is correct since you have a NonNullList as input but you only use the first item of the list?

Hmm, not sure. I can check with the tutorial. Again, I'm not 100% sure as to how the whole process functions, as the tutorial didn't really explain well. From what I understand, the recipes are gathered from the Json files and stored in the NonNullList.

Posted
12 hours ago, Luis_ST said:

RecipeManager#getRecipeFor uses OreRefineryRecipe#matches to enure the items in the container are valid for the given SimpleContainer are you sure the implemention is correct since you have a NonNullList as input but you only use the first item of the list?

Just checked with the tutorial, they’re doing the same thing. From what I understand, the non-null list is just storing the item that is in the input slot (in this case, the SimpleContainer slot 0). I can send the link to the tutorial GitHub: https://github.com/Tutorials-By-Kaupenjoe/Forge-Tutorial-1.20.X/tree/31-recipeTypes

Posted

I cloned your git repo to debug your mod locally on my PC, but it seems to be broken.
The project is missing some important gradle files because you are using a java .gitignore file, you should use the file which comes with the mdk.

Posted
27 minutes ago, Luis_ST said:

I cloned your git repo to debug your mod locally on my PC, but it seems to be broken.
The project is missing some important gradle files because you are using a java .gitignore file, you should use the file which comes with the mdk.

Ok, I just changed the .gitignore. Not sure if that also added the gradle files you needed, but it added something. If it doesn't, I can just send you the files that you need manually.

Posted

I am still not able to import your project into my IDE, I would recommend you to remove all files from github that can be found in the .gitignore file. Iedally you create a new branch.

Posted
On 11/8/2023 at 4:24 PM, Luis_ST said:

I am still not able to import your project into my IDE, I would recommend you to remove all files from github that can be found in the .gitignore file. Iedally you create a new branch.

Ah, I realized my response didn't send. Would you be able to just copy and paste the necessary files into a new project? I didn't change much in my gradle files, basically just specifying the mod id (which can be seen in the main class) and the version of forge (40.0.14). If you're unable to do that, that's fine, but I may need some help with creating a new branch and working with Git since my Git expertise really only go up to branch merging.

Posted
5 hours ago, BlueFFlame said:

Ah, I realized my response didn't send. Would you be able to just copy and paste the necessary files into a new project?

That would work, but note the correct .gitignore must be part of the first commit.

I would recommend you to learn the basics of Git, it is very helpful for a programmer.

Posted
8 minutes ago, Luis_ST said:

That would work, but note the correct .gitignore must be part of the first commit.

I would recommend you to learn the basics of Git, it is very helpful for a programmer.

Yeah, it's been on my list of things to learn. As of now, I haven't really had a need to create branches or do anything more than commiting, pushing and pulling. I'll probably create a new branch for the .gitignore; I could just look at how to do it.

Posted
On 11/10/2023 at 10:47 PM, Luis_ST said:

That would work, but note the correct .gitignore must be part of the first commit.

I would recommend you to learn the basics of Git, it is very helpful for a programmer.

How's debugging going? Have you figured a root cause? I had an idea of what it was (recipe returning null), but I couldn't figure out why it was doing that. If you haven't had time to work on it don't worry, I'm not really in a time rush.

Posted

Sorry, I completely forgot about it.

First of all, there is a problem in your recipes. You load a property "result" from your recipes in the Serialiser, but in the recipe you specify "ouput". (Read your logs!)

Secondly, you have two ItemStackHandlers in your BlockEntity, you should use the one from the Capability.
Remove the ItemStackHandler named 'itemHandler' and the problem should be fixed.

It worked for me.

Posted
On 11/17/2023 at 10:35 PM, Luis_ST said:

Sorry, I completely forgot about it.

First of all, there is a problem in your recipes. You load a property "result" from your recipes in the Serialiser, but in the recipe you specify "ouput". (Read your logs!)

Secondly, you have two ItemStackHandlers in your BlockEntity, you should use the one from the Capability.
Remove the ItemStackHandler named 'itemHandler' and the problem should be fixed.

It worked for me.

Oh my god, thank you so much! It works perfectly now. Of course it was a typo. Was there anything else I should change in my code, to keep up with conventions and make the game run better? Again, I'm new to modding, so I don't know a lot about conventions so I'd like to learn.

Posted

The only thing I noticed when debugging is that you use System.out for logging.
I would recommend you to use the logger from the mdk because you get information like time, thread or the file directly to the output.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.