Topic category: User side tutorials
For the longest time, I wanted to figure out how to be able to store an entity so it can be despawned and then respawned later as an exact copy, and I've finally figured out how. While this is for MCreator 2024.2 & Forge 1.20.1, it is very likely to work on both newer MCreator/Forge versions, as well as NeoForge (though I can't guarantee).
You will need to know how return procedures work and will need to edit a code element directly, but otherwise most of this can be directly recreated from code blocks.
Step 1: Data Retriever Creation
The first step will be creating your procedure that actually gets the data of the entity that you want. Since we will need to directly code this part, I recommend making it a procedure that gives a return that you just call where wanted.
To start off, make a blank procedure, in this case I'll name mine 'GetEntityData'. Immediately save the empty procedure and open the code editor. Your procedure should look something like this:
package net.mcreator.[Your Mod Name].procedures;
public class GetEntityData {
public static void execute() {
}
}
From here, we need to import some extra information that the procedure needs, so we'll be sticking two new lines under the first line so that your code looks like this:
package net.mcreator.[Your Mod Name].procedures;
import net.minecraft.world.entity.Entity;
import net.minecraft.nbt.CompoundTag;
public class GetEntityData {
public static void execute() {
}
}
With all of the needed data imported, we can now replace the contents of the GetEntityData task. When replaced, it should look like:
public class GetEntityData {
public static String execute(Entity entity) {
if (entity == null) {
return "Null";
}
CompoundTag entityNbt = new CompoundTag();
entity.save(entityNbt);
return entityNbt.toString();
}
}
With all of that done, the entire code should look like:
package net.mcreator.[Your Mod Name].procedures;
import net.minecraft.world.entity.Entity;
import net.minecraft.nbt.CompoundTag;
public class GetEntityData {
public static String execute(Entity entity) {
if (entity == null) {
return "Null";
}
CompoundTag entityNbt = new CompoundTag();
entity.save(entityNbt);
return entityNbt.toString();
}
}
Step 2: Store the Data
With the data retriever made, you'll now want to make the system to actually store the entity data. For this tutorial, I'll be using the 'Player right clicks on entity' global procedure. Whether you store this data on the player directly or store it in an item, you'll need 2 String Variables. I'll be storing it on the player here, so I've created two Persistent global player String varibles: 'entity_data' and 'registry_name'.
One issue that comes with the data we've saved is that it includes the Positional data of the original mob, which we likely do not want. If we leave that data in, the mob copy we create will teleport to the exact spot the entity was copied from rather than spawn on the player like intended.
For this, we'll also want to make a local variable to edit before saving to the full variable. In the below example, I have used a local variable named 'tempTag'.
The first block here calls the GetEntityData procedure we just made, passing the target as the entity dependency and saves it to the local variable.
The second block is what removes the Positional data. It takes the returned string and finds all data from right before the 'Pos:[' (position tag), as well as calculates the length from the P in Pos to the ] that signifies the end of the positional data. We then remove the Pos variable by having the second half of the newly created string start from right after the length of the Pos statement.
The third code block finally saves the data left in the local variable (note that you can just save the results directly to the global variable in block 2 rather than re-saving to the global variable, I just have the extra step as I intend to have multiple potential slots of data it can be saved to.
Lastly, the fourth code block saves the registry name of the mob to a separate variable (this is important).
In most cases, you'll probably then want to add on a block below to despawn the original mob.
Step 3: Spawn the Copy
Now that we have our entity data saved, its time to summon our mob at will! For the best results, we'll want to use 3 code blocks that call on commands to get what we want. The commands should look like the following:
The first block will summon the mob using the registry name string we saved before, as well as give the target a tag named 'copy' so that we can ensure we target the right mob with the following steps. Below is an easy copy and paste for the third input (there is a space before the first ~, which is very important):
~ ~ ~ {Tags:["copy"]}
The second block merges the current data on the entity with the data we saved earlier (overriding everything but the position). NOTE that I split the top text box into two here as it wouldn't show its full length for the screenshot if I did, you'll just want to use a single text box and then the entity data string by copying the following (the space at the end it important):
data merge entity @e[limit=1,sort=nearest,tag=copy]
Lastly, we then remove the copy tag from our mob so that there's no chance it gets accidentally selected again!
tag @e[limit=1,sort=nearest,tag=copy] remove copy
With that, we can now create our exact copy of a mob! You'll need to decide what exactly will call the copy creation procedure. If you store the strings on an item and make a conditional right click that summons the mob, you'll want to replace the global player variables with the appropriate item string nbts, of course.