Jump to content

Recommended Posts

Posted

Ok, a bit of a bug report on this. For one it will only craft one instance of recipe, and then after that it will just delete the ingredients with each attempt, until the current save is reloaded. Another issue is that if a recipe contains similar ingredients to another it seems to spawn the other result.. I.e 1 stack of diamonds become diamond axes.

 

So basically it doesn't craft as many as it can, so that if you drop 90 diamonds, you expect 10 diamond blocks, but instead you get either diamond axes or absolutely nothing. It just doesn't seem to check if other ingredients also match, and such... I have an idea what could be causing it, but not sure.

 

Member of Aerotech Networks, a Multi-Gaming server.

Also Currently porting the "Rise of the Automatons" minecraft mod

Posted

Ok, so I have made good progress in getting the bugs worked out with this. In that it now crafts all it can, and give back proper results, and remainders... Still have one problem, it seems to be something to do with the findMatching method. In the sense that it has problems with recipes with multiple ingredients, doesn't seem to correctly check if the other ingredients are present to craft.

May just be a simple solution xD

Here is the findMatching method, followed by the fully updated code:

 

/**
 * Returns the matching {@link InWorldRecipe} that has the given items as
 * ingredients.
 * 
 * @param items
 *            A {@link List} of {@link ItemStack}s with items to test.
 * @return Either the mathing {@link InWorldRecipe} where the given items
 *         are ingredients or <code>null</code> if no recipe was found
 */
public InWorldRecipe findMatching(List<ItemStack> items) {
	for (InWorldRecipe recipe : recipes) {
		if (recipe.getRecipeSize() != items.size()) {
			continue; // the sizes do not match: next recipe please!
		}
		int nbMatchingItems = 0;
		for (ItemStack is : items) {
			if (recipe.containsIngredient(is)) {
				// okay, is is part of the recipe
				nbMatchingItems++;
			}
		}
		if (nbMatchingItems == recipe.getRecipeSize()) {
			// yeah found recipe (but did not check correct amount!)
			return recipe;
		} else {
			// not enough matching items
			return null;
		}
	}
	return null;
}

 

 

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import cpw.mods.fml.common.event.FMLInitializationEvent;

/**
* A crafting manager that is capable of managing and crafting
* {@link InWorldRecipe}s.
* 
* It is recommended to add recipes during the {@link FMLInitializationEvent}.
* 
* This crafting manager can (currently only) add recipes of type
* {@link InWorldRecipe}. It is also able to find matching recipes for a given
* list of ingredients and processes the complete 'crafting process' for a given
* world and bounding box.
* 
* <p>
* <b>Warning</b> This class was written quickly and did not went through JUnit
* tests. Its also not very completed, since NBTTags do matter and this class
* just ignores them. The original idea comes from the minecraft forge forums:
* http://www.minecraftforge.net/forum/index.php/topic,24744.0.html
* </p>
* 
* @author pickaxe_engineer
* @Edited By Electrobob99
* @version 1.3
*/
public class InWorldCraftingManager {

private Vector<InWorldRecipe> recipes;

/**
 * The instance of this {@link InWorldCraftingManager}. Its thought to exist
 * only once per server?(not sure actually)
 */
public static InWorldCraftingManager object = new InWorldCraftingManager();

/**
 * Creates a new {@link InWorldCraftingManager}. This is private since it
 * should only exist one craftingmanager per server?
 */
private InWorldCraftingManager() {
	recipes = new Vector<InWorldRecipe>(10);// avarage of such recipes
}

/**
 * Adds the given recipe to the list of recipes this manager knows. Like
 * registering a recipe to the GameRegistry.
 * 
 * @param recipe
 *            The recipe to add
 */
public void addRecipe(InWorldRecipe recipe) {
	recipes.add(recipe);
	Collections.sort(recipes);
}

/**
 * Crafts whatever is possible within the given bounds. This method does a
 * lot at once. It firstly searches for {@link EntityItem}s within the given
 * {@link AxisAlignedBB}. Then it looks if a recipe matches (with
 * {@link InWorldCraftingManager#findMatching(List)}) and if found one - it
 * crafts as many times result as possible and consumes the used
 * ingredients.
 * 
 * @param world
 *            The world where the crafting should happen. This method tests
 *            if its executed on the server and if not, it returns
 *            immediatley.
 * @param bounds
 *            The bounds in where to look for items ( {@link EntityItem}s ).
 * @param x
 *            The x-coordinate on which the result-spawning-calculation will
 *            start
 * @param y
 *            The y-coordinate on which the result-spawning-calculation will
 *            start
 * @param z
 *            The z-coordinate on which the result-spawning-calculation will
 *            start
 */
public void craftIfPossible(World world, AxisAlignedBB bounds, int x,
		int y, int z) {
	if (world.isRemote) {
		return;// don't craft on client
	}
	List<EntityItem> entities = world.getEntitiesWithinAABB(
			EntityItem.class, bounds);
	if (entities == null || entities.size() == 0) {
		return;// no items found or the list has no entries (not sure if
				// possible).
	}
	List<ItemStack> items = extractItemStacks(entities);
	InWorldRecipe recipe = findMatching(items);
	Vector<Integer> nbConsumed = craftRecipe(recipe, items, world, x, y, z);
	if (nbConsumed == null) {
		// nothing crafted
		System.out.println("Did not craft");
		return;
	} else {
		// crafted items spawned already in world!
	}
	for (int i = 0; i < nbConsumed.size(); i++) {
		// going through nbConsumed:
		// if actual nbConsumed > 0 -> entities[i].getEntityItem().stackSize
		// -= nbConsumed
		// if entities[i].getEntityItem().stackSize <= 0:
		// entities[i].setDead
		if (nbConsumed.get(i) > 0) {
			entities.get(i).getEntityItem().stackSize -= nbConsumed.get(i);
			if (entities.get(i).getEntityItem().stackSize <= 0) {
				entities.get(i).setDead();
				world.removeEntity(entities.get(i));
			}
		}
	}
}

/**
 * Crafts a recipe and returns the amount of used items. The returning
 * list's entries do correspond to the argument {@link List} of
 * {@link ItemStack}s. Thus in the returning {@link Vector} at position i is
 * stored how much items of the ItemStack at position i are used.
 * <b>Warning: this method should only be invoked on server side, but does
 * not test it!</b>
 * 
 * @param recipe
 *            The recipe to craft
 * @param items
 *            The ingredients
 * @param world
 *            The world in where the crafting happens
 * @param x
 *            The x-coordinate on which the result-spawning-calculation will
 *            start
 * @param y
 *            The y-coordinate on which the result-spawning-calculation will
 *            start
 * @param z
 *            The z-coordinate on which the result-spawning-calculation will
 *            start
 * @return A {@link Vector} of {@link Integer}s which correspond to the
 *         amount of items used during the crafting process. If no crafting
 *         happend it returns NULL!
 */
private Vector<Integer> craftRecipe(InWorldRecipe recipe,
		List<ItemStack> items, World world, int x, int y, int z) {
	if (recipe != null && items != null && items.size() > 0) {
		Vector<Integer> nbConsumed = new Vector<Integer>(items.size());

		//int nbResults = 0;
		for (ItemStack is : items) {
			if(is.stackSize == recipe.demandedAmount(is)){
				//can craft once the result, craft the item, spawn it, and set new stack size
				ItemStack itemStack = recipe.getResult();
				world.spawnEntityInWorld(new EntityItem(world, x, y+1, z, itemStack));
				is.stackSize -= recipe.demandedAmount(is);
				//return true;
			}
			if(is.stackSize > recipe.demandedAmount(is)){
				int toCraft = is.stackSize / recipe.demandedAmount(is);
				int rest = is.stackSize - (toCraft*recipe.demandedAmount(is));
				ItemStack itemStack = new ItemStack(recipe.getResult().getItem(),toCraft,0);
				world.spawnEntityInWorld(new EntityItem(world, x, y+1, z, itemStack));
				is.stackSize = rest;

			}
			if(is.stackSize < recipe.demandedAmount(is)){
				System.out.println("Did not craft!");
			}	
		}
	}
	// null recipe or empty list
	return null;
}

/**
 * Extracts the {@link ItemStack}s out of a list of {@link EntityItem}s
 * 
 * @param list
 *            The {@link EntityItem} {@link List} from where to extract
 * @return A {@link List} of {@link ItemStack}s which correspond to the
 *         {@link EntityItem} list. Or NULL if the list was null or empty.
 */
private List<ItemStack> extractItemStacks(List<EntityItem> list) {
	if (list == null || list.size() == 0) {
		return null; // emtpy list
	}
	List<ItemStack> out = new Vector<ItemStack>(list.size());
	for (EntityItem ei : list) {
		out.add(ei.getEntityItem());
	}
	return out;
}

/**
 * Returns the matching {@link InWorldRecipe} that has the given items as
 * ingredients.
 * 
 * @param items
 *            A {@link List} of {@link ItemStack}s with items to test.
 * @return Either the mathing {@link InWorldRecipe} where the given items
 *         are ingredients or <code>null</code> if no recipe was found
 */
public InWorldRecipe findMatching(List<ItemStack> items) {
	for (InWorldRecipe recipe : recipes) {
		if (recipe.getRecipeSize() != items.size()) {
			continue; // the sizes do not match: next recipe please!
		}
		int nbMatchingItems = 0;
		for (ItemStack is : items) {
			if (recipe.containsIngredient(is)) {
				// okay, is is part of the recipe
				nbMatchingItems++;
			}
		}
		if (nbMatchingItems == recipe.getRecipeSize()) {
			// yeah found recipe (but did not check correct amount!)
			return recipe;
		} else {
			// not enough matching items
			return null;
		}
	}
	return null;
}
@Deprecated
/**
 * Spawns a given amount of {@link EntityItem}s in the given world, near the
 * given position. This method respects the stacksize limits and thus spawns
 * several entities if the stacksize would overflow.
 * 
 * @param world
 *            The world in where to spawn the items. If this world is
 *            remote, the method does nothing
 * @param x
 *            The x-coordinate on which the result-spawning-calculation will
 *            start
 * @param y
 *            The y-coordinate on which the result-spawning-calculation will
 *            start
 * @param z
 *            The z-coordinate on which the result-spawning-calculation will
 *            start
 * @param item
 *            The item to spawn. If this is null, nothing happens
 * @param nbResults
 *            The amount of times the item should spawn. Example: the item
 *            is 9 redstone pieces and nbResults is 4, a stack of 36
 *            redstone pieces would spawn.
 */
private void spawnItems(World world, int x, int y, int z, ItemStack item,
		int nbResults) {
	if (item != null && nbResults > 0 && !world.isRemote) {
		int total = item.stackSize * nbResults;
		if (total <= item.getMaxStackSize()) {
			item.stackSize = total;
			EntityItem ei = new EntityItem(world, x + 0.5, y + 1.5,
					z + 0.5, item);
			world.spawnEntityInWorld(ei);
		} else {
			int nbStacks = total / item.getMaxStackSize();
			int remaining = total % item.getMaxStackSize();
			for (int i = 0; i < nbStacks; i++) {
				ItemStack is = new ItemStack(item.getItem(),
						item.getMaxStackSize(), item.getItemDamage());
				EntityItem ei = new EntityItem(world, x + 0.5, y + 1.5,
						z + 0.5, is);
				world.spawnEntityInWorld(ei);
			}
			if (remaining > 0) {
				ItemStack is = new ItemStack(item.getItem(), remaining,
						item.getItemDamage());
				EntityItem ei = new EntityItem(world, x + 0.5, y + 1.5,
						z + 0.5, is);
				world.spawnEntityInWorld(ei);
			}
		}
	}
}

}

 

 

I also wouldn't mind making some of the recipes only work with certain items aswell.

Member of Aerotech Networks, a Multi-Gaming server.

Also Currently porting the "Rise of the Automatons" minecraft mod

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

    • Reach Out To Rapid Digital: What sapp Info: +1 41 4 80 7 14 85 Email INFO: rap iddi gita lrecov ery @ exe cs. com Hello, my name is Jayson, and I’m 35 years old from the United Kingdom. My family and I recently endured an incredibly challenging experience that I wouldn’t wish on anyone. We became victims of a cryptocurrency investment fraud scheme that saw us lose a staggering $807,000 in USDT and Bitcoins. The fraudsters had created a convincing facade, and we were lured into investing, only to discover later that the platform was a complete scam. We were left devastated, not just financially, but emotionally, as we had trusted these people and believed in the legitimacy of the investment. After the initial shock wore off, we desperately searched for ways to recover the lost funds. It seemed like an impossible task, and we felt as though there was no hope. That’s when, by sheer luck, we stumbled across a post about Rapid Digital Recovery, a cryptocurrency and funds recovery organization with a proven track record in cybersecurity and fraud recovery. We decided to reach out to them, and from the first interaction, we were impressed with their professionalism and transparency. They explained the recovery process in detail and reassured us that they had the skills and expertise to track down the perpetrators and recover our funds. This gave us a renewed sense of hope, something we hadn’t felt in months. What truly stood out during our experience with Rapid Digital Recovery was their dedication to the recovery process. The team went above and beyond, using sophisticated tracking tools and cyber forensics to gather critical information. Within a matter of weeks, they had successfully located the funds and traced the scam back to the fraudsters responsible. They worked with the authorities to ensure the criminals were held accountable for their actions. To our relief, the team at Rapid Digital Recovery was able to recover every single penny we had lost. The funds were returned in full, and the sense of closure we felt was invaluable. We couldn’t have imagined such a positive outcome in the early stages of our recovery journey, and we are deeply grateful for the work they did. If you ever find yourself in a similar situation, I highly recommend contacting Rapid Digital Recovery. Their expertise, transparency, and dedication to their clients make them the go-to choice for anyone seeking to recover lost cryptocurrency or funds. They truly gave us back our financial future.  
    • This is my first time modding anything, so maybe just skill issue. I'm using Forge 54.0.12 and Temurin 21.0.5+11-LTS I wanted to create a custom keybind and to check whether it works I'd like to send a chat message. I tried using Minecraft.getInstance().player.sendSystemMessage(Component.literal("test")); but IntelliJ couldnt resolve sendSystemMessage(...). Since I saw people using it in earlier versions, I tried the same thing with 1.20.6(- 50.1.0), where it works fine, now I can't figure out if this is intentional and whether there are other options for sending chat messages. On that note, is there more documentation than https://docs.minecraftforge.net/en/1.21.x/? It seems very incomplete compared to something like the Oracle Java docs
    • Hi, i'm having this error and I wanna fix it. we try: -Reload drivers -Eliminate .minecraft -Eliminate Java -Restart launcher -Verify if minecraft is using gpu -Mods  in .minecraft is empty -Install the latest and recomended version of forge idk what i have to do, help me pls. the lastest log is: https://mclo.gs/WAMao8x  
    • Read the FAQ, Rule #2. (https://forums.minecraftforge.net/topic/125488-rules-and-frequently-asked-questions-faq/)  
  • Topics

×
×
  • Create New...

Important Information

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