Jump to content

[1.7.10] Issues with EntityPotion custom potion effects [Solved]


Recommended Posts

Posted

I am attempting to create a mod, which so far is working well. In this mod I've created a class that extends Entity witch, and I am using events to intercept when a potion is being thrown by this new witch.

 

I tested it out in single player, in Minecraft, the entity for a potion is ThrownPotion, while in the code ThrownPotion doesn't exist and is instead EntityPotion (from what I can tell).

 

In game with command blocks I can execute this command and it works perfectly:

/summon ThrownPotion ~ ~2 ~ {Potion:{Count:1,id:373,Damage:16428,tag:{CustomPotionEffects:[{Id:20,Amplifier:0,Duration:200}]}}}

It was my belief that the same NBT structure should work for EntityPotion as well. Since I'm adding a wither potion effect I can't just set the damage, as id=20 is above the 15 allowed in the first 4 bits of the id, which define the potion effect, so I have to use custom potion effects. The problem is the nbt format isn't working. The following is the code:

@SubscribeEvent
public void onEntitySpawn(EntityJoinWorldEvent event)
{
	Entity e = event.entity;

	if(e instanceof EntityPotion)
	{
		EntityPotion ep = (EntityPotion)e;
		if(ep.getThrower() instanceof ChargedWitch)
		{
			if(ep.getPotionDamage() != 32660) return;// Only alter the poison potion thrown by the witch
			ep.setPotionDamage(16461); // If this line is here, potion becomes instant damage, is commented potion is still poison
                                                           // (proving nbt didn't work)
			NBTTagCompound nbt = ep.getEntityData();

			NBTTagCompound potion = nbt.getCompoundTag("Potion");
			NBTTagCompound tag = new NBTTagCompound();

			potion.setShort("id", (short) 373);
			potion.setShort("Damage", (short) 16461);
			potion.setByte("Count", (byte) 1);

			tag.setTag("CustomPotionEffects", makePotion());

			potion.setTag("tag", tag);

			nbt.setTag("Potion", potion);
		}
	}
}
public NBTTagList makePotion() { 
	NBTTagList list = new NBTTagList();
	NBTTagCompound potionType = new NBTTagCompound();
	potionType.setByte("Id", (byte) Potion.wither.getId());
	potionType.setByte("Amplifier", (byte) 0);
	potionType.setInteger("Duration", 200);
	potionType.setByte("Ambient", (byte) 0); //Not ambient
	list.appendTag(potionType);
	return list;
}

 

I'm unsure why this isn't working. I guess my main question is why is it ThrownPotion in game, but no sign of any "ThrownPotion" class in the project.

 

If it's not possible I can easily make my own potion entity, I know enough to do so, I've just never experienced this issue before with inconsistent NBT structures.

 

!EDIT: Changed topic title to fit the format most posts are using.

 

!!EDIT: Thanks for the help, for anyone else looking to add custom effects to Potion Entities but don't know how:

 

 

 

NBTPotionHelper.java

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.potion.Potion;

public class NBTPotionHelper
{
public static NBTTagList makePotion(Potion effect, int amplifier, int duration, boolean ambient)
{ 
	NBTTagList list = new NBTTagList();
	return addPotion(effect, amplifier, duration, ambient, list);
}
public static NBTTagList addPotion(Potion effect, int amplifier, int duration, boolean ambient, NBTTagList list)
{
	NBTTagCompound potionType = new NBTTagCompound();
	potionType.setByte("Id", (byte) effect.getId());
	potionType.setByte("Amplifier", (byte) amplifier);
	potionType.setInteger("Duration", duration);
	potionType.setByte("Ambient", (byte) (ambient ? 1 : 0)); //Not ambient
	list.appendTag(potionType);
	return list;
}
}

 

To create a custom EntityPotion:

 

ItemStack stack = new ItemStack(new ItemPotion());

NBTTagCompound nbt = stack.getTagCompound();
if(nbt == null) nbt = new NBTTagCompound();
// Replace Potion.wither with the potion effect you want to use.
nbt.setTag("CustomPotionEffects", NBTPotionHelper.makePotion(Potion.wither, 1, 250, false));
            	
stack.setTagCompound(nbt);
            	
entitypotion = new EntityPotion(this.worldObj, this, stack);

 

To add multiple potion effects to an entity:

 

ItemStack stack = new ItemStack(new ItemPotion());

NBTTagCompound nbt = stack.getTagCompound();
if(nbt == null) nbt = new NBTTagCompound();

// Replace Potion.wither with the potion effect you want to use.
nbt.setTag("CustomPotionEffects", NBTPotionHelper.makePotion(Potion.wither, 1, 250, false));

nbt.setTag("CustomPotionEffects", NBTPotionHelper.addPotion(Potion.poison, 0, 300, false, nbt.getTagList("CustomPotionEffects", 10));
//10 is "Compound" in the List Types.

stack.setTagCompound(nbt);
            	
entitypotion = new EntityPotion(this.worldObj, this, stack);

 

 

Posted

With the changed to how forge decompiles in 1.7 (I don't know which version it changed) you're building against a placeholder jar. There is absolutely no source code that I can access besides the obfuscated code for the actual game. Because of this I can't just copy and paste the witch code over because I can't get it. The last time I used forge you built your mod with a full decompiled minecraft code, able to see the actual game code from within Eclipse.

 

Even if I did summon the potion myself, I'd still have the same issue. I've done 2 days of research and can't find any links on the internet about how to set the CustomPotionEffects of an EntityPotion. Since I'm trying to use Wither, which is not obtainable via metadata this is the only way that's possible to do it short of making your own custom potion entity.

 

EntityWitch handles the potion behavior in onLivingUpdate. Override it and change the code to your liking.

Overwriting can only do so much. I want it to have completely the same behavior as a normal witch except throwing wither potions and summoning lightning bolts (which I already have working). Unless I can get the deobfuscated code for EntityWitch, I don't get how I'm supposed to simply overwrite the method, I still would need to set the potion data of the EntityPotion.

Posted

Ok, thank you, that's very useful. I wonder why that's not noted in any tutorials I've ever found, all of say to use Dev. The question still remains how to make the potion give wither, since I know it's possible in game it's obviously possible with code, but I guess I can look at EntityPotion and figure that out.

Posted

I am familiar with the custom potion effect format, I've studied that page and the Chunk_format page as well, the problem is even after applying the NBT to the potion it doesn't seem to have any effect. Is potionEntity.getEntitydata() not the right NBT to modify? From what I see it's the only method that returns NBT other than the readFromNBT and WriteToNBT which are only used when loading from the save file.

 

The problem with just overwriting the attackEntityWithRangedattack (which I use already to do the lightning strikes) is that no where there can I change the potion types. The only way is to copy all of the code, so I'll end up doing that, I just am having a hard time getting the NBT to apply. I've checked that it's being structured the right way, I built a class that prints out the NBT of an entity in JSON and it prints out the correct NBT, but when the potion hits me it doesn't have the effect, while the one I summon in-game with commands using ThrownPotion works fine.

 

I think I can figure the rest out from here now that I've been told how to get the decomp workspace, so thanks for that. I'll report back if I have other questions related to this.

Posted
If you run gradlew setupDecompWorkspace (as opposed to setupDevWorkspace) you will get sourcecode.

 

Ok, so I have a script I made in batch to create new workspaces for projects, and in that file I use

 

gradlew setupDecompWorkspace --refresh-dependencies
gradlew eclipse

 

It ends up i was already using decomp workspace, not dev, and it did not set up a workspace that had the source code. The resulting eclipse workspace contains a src folder with only a simple example mod that prints out the unlocalized name of dirt, and none of the code. To compile against it contains a referenced library called forgeSrc which is a jar containing only empty methods to allow the IDE to compile. Where would I find the source code? Did you mean setupDevWorkspace would generate the source code instead, did you say them backwards?

 

EDIT! apparently the source code is obtainable in "\build\tmp\recompSrc\", bit of a strange place to be, and not the most obvious place to find it, but it works at least.

 

Indeed it is not. getEntityData is for custom, additional data that you want stored in an entity that is not yours (e.g. store a player's team or something). This is an old outdated mechanic and pretty much replaced by IExtendedEntityProperties.

 

As I said, the NBT goes on an ItemStack (with Items.potionitem). Then you pass that ItemStack to EntityPotion. Yes, you have to pretty much copy the code in attackEntityWithRangedAttack.

 

I find that very strange, considering you're supposed to be able to modify the NBT data of any entity, if that NBT data really can't be modified after creation it's a bit hard to work with. That's a bit convoluted. Considering the fact that I can with in-game commands assign NBT data to an entity that I summon, and can also be done with /entitydata, I find it really strange that I'm being told this is not possible to do within the code.

Posted

Why are you looking directly for the source code? setupDecompWorkspace attaches a source jar to the forge bin jar, so eclipse should automatically display the source if you open a Minecraft or Forge class.

Ok, that makes more sense. I've never actually worked with a project that set that up, every time I usually click on those it goes to "No linked source could be found for this file", so I never gave it a thought to try it here.

 

Entities don't have NBT data. Entities are saved to NBT. The getEntityData is abusing the NBT system.
I see, thanks for that explanation then. That makes me curious how the entitydata command works, perhaps it calls the readfromNBT function again.

 

It is, but not using getEntityData. Using NBT for this stuff is a hack. Just set the properties directly for an entity.

And again, this is not the entity's NBT. Look at EntityPotion, it only wraps a poition ItemStack, so you need to store the potion there, in the ItemStack.

Ok. this actually also means theoretically I could use reflection to change the ItemStack info (although I won't do that, I'll just set it at creation of the potion).
Posted

Entities don't have NBT data. Entities are saved to NBT. The getEntityData is abusing the NBT system.
I see, thanks for that explanation then. That makes me curious how the entitydata command works, perhaps it calls the readfromNBT function again.

 

If you look at its implementation in 1.8, you'll see that it tells the

Entity

to write itself to NBT, merges that with the NBT specified in the command and then tells the

Entity

to read from the merged NBT.

 

To address your initial confusion of

ThrownPotion

vs.

EntityPotion

: every

Entity

class is registered with a unique name.

ThrownPotion

is the name that the

EntityPotion

class is registered with.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted

If you look at its implementation in 1.8, you'll see that it tells the

Entity

to write itself to NBT, merges that with the NBT specified in the command and then tells the

Entity

to read from the merged NBT.

 

To address your initial confusion of

ThrownPotion

vs.

EntityPotion

: every

Entity

class is registered with a unique name.

ThrownPotion

is the name that the

EntityPotion

class is registered with.

Thank you for that explanation. I figured the ThrownPotion was just the registered name, just wasn't sure. As for the command then you for the explanation. I guess that makes sense, I was wondering how it managed to insert only some NBT with omitting other data and not change anything else of the entity, and that is the most obvious way of doing so (not that I'll be using that to achieve my goal)

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.