Jump to content

Recommended Posts

Posted

So I had this idea for a mod that adds randomly generated crafting recepies that are specific to one world/seed.

I have already tested some stuff and it turns out that you can add new recepies at runtime, but these recepies of course then also persist over saves and could cause problems with multiplayer servers.

I am just wondering? Is something like this possible? Can you point me in a direction?

Posted

Possible, yes.
Exists already, and is ready for use, no.

You'll need to create your own implementation of IRecipe, that can handle a world (or IBlockAccess as it boils down to) as a variable for the recipe.
To go along with that, you will very likely need to create your own Crafting table etc, or substitute the normal Crafting Table's container for your new one, that can do these world-specific recipes, and all the normal ones as well.

Also previously known as eAndPi.

"Pi, is there a station coming up where we can board your train of thought?" -Kronnn

Published Mods: Underworld

Handy links: Vic_'s Forge events Own WIP Tutorials.

Posted (edited)
5 minutes ago, Matryoshika said:

Possible, yes.
Exists already, and is ready for use, no.

You'll need to create your own implementation of IRecipe, that can handle a world (or IBlockAccess as it boils down to) as a variable for the recipe.
To go along with that, you will very likely need to create your own Crafting table etc, or substitute the normal Crafting Table's container for your new one, that can do these world-specific recipes, and all the normal ones as well.

I have some experience with IRecipes so that can be done. I was hoping to not have to make a new Crafting table tough, darn. I'll look into it, thanks.

Edited by Tschipp
Posted
6 minutes ago, diesieben07 said:

You don't need a new crafting table. IRecipe::matches has a World parameter.

Ah yes, very good. So for example, I could create an item that when right clicked registers the crafting recipe for the given world. But how would I make it so that other worlds don't have access to that recipe?

 

Posted (edited)

Alright, some progress has been made:

The mod generates a recipe that creates gold blocks. It takes one ingredient. That ingredient is defined by the world's seed. So what I'm doing, is when checking if the recipes match, I get the world seed, get the log from that number, and then get a item/block corresponding to that id. The problem is, that the matches() method gets executed twice. Once of the client side and once on the server side. The client side gets executed first, then the server side. The client side passes an instance of WorldClient as world, which makes it impossible to get the seed from that. The server side passes a WorldServer, everything there works fine. The crafting recipe actually works, the problem is that the output item isn't displayed, because the client version of the matches() method returns false. I hope I was clear enough, but just in case, here is my code:

private static long seed;
	private static int seedLog;
	private static Item worldItem;
	
	public boolean matches(InventoryCrafting inv, World world)
	{
		seed = world.getSeed();
		seedLog = (int) Math.log(Math.abs(seed) / 10);
		worldItem = Item.getItemById(seedLog);
		
		ItemStack stack = ItemStack.EMPTY;

		for (int i = 0; i < inv.getSizeInventory(); ++i)
		{
			ItemStack currentstack = inv.getStackInSlot(i);

			if (!currentstack.isEmpty())
			{
				Item current = currentstack.getItem();
				if(worldItem != null && current == worldItem)
				{
					return true;
				}
	
			}
		}

		return false;
	}

 

Also, here is a gif demonstrating what is happening:

GIF

 

Edited by Tschipp
Posted
30 minutes ago, diesieben07 said:

First, that's a terrible way to select an Item based on the seed. Create a new Random with the set seed and then use it to select an Item from ForgeRegistries.ITEMS.getValues.

The visual issue you are experiencing is because the client does not actually know the world seed. You will have to send a packet containing the selected item (don't send the seed) to the client whenever they connect (PlayerLoggedInEvent), respawn (PlayerRespawnEvent) or switch dimensions (PlayerChangedDimensionEvent).

Thanks, this is exactly what I needed. I didn't know you could create randoms with a seed. Also, can you elaborate on why I should send the packet at these specific events? They do not have anything to do with crafting right? Also how would the PacketHandler look like?

Posted (edited)
12 minutes ago, diesieben07 said:

I chose those specific events, because they are the only times a player's World changes. In fact, now that I think about it, you probably only need to do it on login, since the seed will not change if you change dimensions.

Yes, it does not have anything to do with crafting, but there is no way to predict on the server when the client will need to know the result of a crafting recipe beforehand (think JEI, etc.), so you have to tell them up front.

In the packet-handler you'd just store the item somewhere. Then in the recipe check if the world is client side (using isRemote) and if it is, access that stored item, otherwise compute it from the seed.

 

A cleaner way would be to store the item attached to the world on both sides (using WorldSavedData) and compute it once when the world is loaded (WorldEvent.Load) on the server.

Ah ok. Now that you mention it: Will JEI be able to see my recepies by default? Because that kinda ruins the purpose of secret crafting recipes.

EDIT: Also, I should maybe add, that I plan on adding multiple different recipes, with all having different items, so I'm not sure storing the items is a good idea.

Edited by Tschipp
Posted
41 minutes ago, diesieben07 said:

I don't know how JEI handles displaying crafting recipes, but I remember that in the NEI days you had to register a handler for special IRecipe implementations.

 

Well, you must store them somewhere at least on the client.

I made an implementation of WorldSavedData., but the values don't get shared with client and server, and I'm not sure how to connect them. I also ended up saving the seed instead of all the item ids, makes it a bit easier.

 

This is the event:

@SubscribeEvent
	public void onWorldLoad(WorldEvent.Load event)
	{
		World world = event.getWorld();
		long seed = Math.abs(world.getSeed());
		WorldSeedSavedData.getInstance(world).setSeed(seed);
		WorldSeedSavedData.getInstance(world).markDirty();


	}

 

And this is my WorldSavedData:

package tschipp.buildingblocks.util;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.WorldSavedData;
import net.minecraft.world.storage.MapStorage;
import tschipp.buildingblocks.BBMod;

public class WorldSeedSavedData extends WorldSavedData {
	
	private static final String DATA_NAME = BBMod.MODID + "_SEED";
	private long seed;
	
	public WorldSeedSavedData() {
		super(DATA_NAME);
	}

	@Override
	public void readFromNBT(NBTTagCompound tag) {
		this.seed = tag.getLong("seed");
	}

	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound tag) {
		tag.setLong("seed", this.seed);
		return tag;
	}
	
	public void setSeed(long seed)
	{
		this.seed = seed;
	}
	
	public long getSeed()
	{
		return this.seed;
	}
	
	
	public static WorldSeedSavedData getInstance(World world) {

		MapStorage storage = world.getPerWorldStorage();
		WorldSeedSavedData instance = (WorldSeedSavedData) storage.getOrLoadData(WorldSeedSavedData.class, DATA_NAME);

		  if (instance == null) {
		    instance = new WorldSeedSavedData();
		    storage.setData(DATA_NAME, instance);
		  }
		  return instance;
		}

}

 

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



×
×
  • Create New...

Important Information

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