Jump to content

[1.7.10] Spawn Particles Around Armor When Hit


Izzy Axel

Recommended Posts

I can't find anything in the source or the forum search about spawning particle effects from armor. :S  The armor class is implementing ISpecialArmor, if that helps.  This is what I've been trying to make work:

 

public class ItemMithrilLeggings extends ItemArmor implements ISpecialArmor
{
public ItemMithrilLeggings(ArmorMaterial armorMat, CreativeTabs tab, int renderIndex, int slot)
{
	super(armorMat, renderIndex, slot);
	setUnlocalizedName("mithrilLeggings");
	setTextureName(Reference.MODID + ":" + getUnlocalizedName().substring(5));
	setCreativeTab(tab);
	setMaxDamage(2456);
	maxStackSize = 1;
}

@Override
public ArmorProperties getProperties(EntityLivingBase player, ItemStack armor, DamageSource source, double damage, int slot)
{
	ArmorProperties mithLeg = new ArmorProperties(3, 1, 167);
	WorldServer overworldInst = MinecraftServer.getServer().worldServers[0];
	Random rand = new Random();
	if(overworldInst != null)
		if(overworldInst.isDaytime())
			mithLeg.AbsorbMax = 167;
		else
			mithLeg.AbsorbMax = 217;
			for (int i = 0; i < 10; i++)
				overworldInst.spawnParticle("suspend", player.posX + (rand.nextDouble() + 0.8D) * 0.5D, player.posY + (rand.nextDouble() * 0.5D), player.posZ + (rand.nextDouble() + 0.8D) * 0.5D, 200.0D, 200.0D, 200.0D);
	return mithLeg;
}

@Override
public int getArmorDisplay(EntityPlayer player, ItemStack armor, int slot){return 0;}

@Override
public void damageArmor(EntityLivingBase entity, ItemStack stack, DamageSource source, int damage, int slot)
{
	this.setDamage(stack, stack.getItemDamage() - damage);
}
}

Link to comment
Share on other sites

Ok this is the first time using Forge event subscriptions, how am I supposed to do this, am I doing this completely wrong?

 

(this is in the main class)

 

@SubscribeEvent
public void LivingHurtEvent(EntityLivingBase entity, DamageSource source, float amount)
{

}

Link to comment
Share on other sites

You need to create a class to handle the event, and in it you need a method like this:

@SubscribeEvent
public void anyMethodName(EventTypeYouWant event)
{

}

 

Then you find out which EventBus the event is posted on, in this case, it's the MinecraftForge event bus - so you register to it like this:

 

MinecraftForge.EVENT_BUS.register(INSTANCE_OF_YOUR_HANDLER_CLASS);

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

Why are you using the MinecraftServer? :o This is certain to crash on a client!

Also why are you checking if it's an instance of EntityLivingBase - it has to be, you're given one!

 

You want something like this:

@SubscribeEvent
public void onHurt(LivingHurtEvent event)
{
    if(event.entityLiving.worldObj.isRemote) //Client only!
    {
        for(int i = 1; i<=4; i++)
        {
            ItemStack stack = event.entityLiving.getEquipmentInSlot(i);
            Item item = stack != null ? stack.getItem() : null;
            if(item instanceof HELMET || item instanceof BODY || item instanceof LEGGINGS || item instanceof BOOTS)
            {
                event.entityLiving.worldObj.spawnParticle(...);
            }
        }
    }
}

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

SSP has been running on an internal server for a while now for starters, and I solved this in another thread, if I try to do Minecraft.getMinecraft().theWorld, nothing I do using it works, such as isDaytime always evaluates to true.  So no, doing it this way is not crashing the client, and doing it the old way isn't working, so...yeah.

 

Also yeah I just figured out that you can access entityLiving through event.  Oops.  :P

Link to comment
Share on other sites

If you use MinecraftServer.getServer().worldServers[0] then it'll always be the overworld, regardless of what dimension you're in.

 

So if you took damage in the Nether, it would try spawn the particles on the overworld - this would cause unexpected behaviour and most likely crashes.

 

In this case, Minecraft.getMinecraft().theWorld is perfectly viable, because particles are only on the client - but every entity has a World object associated with it (Entity#worldObj) - so you don't even need to use Minecraft#theWorld, you can just use LivingHurtEvent#entityLiving.worldObj

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

Just to be sure I tried it the other way, neither way is working with any damage type.  The particles nor the console message.  Also the armor is only supposed to give off particles if its in the Overworld, and it's night.  Additionally, I'm doing 4 if statements because I want to make the individual pieces give off particles, and doing it as 1 conditional wouldn't tell me which one evaluated true.

 

public class MythrilArmorParticles
{
@SubscribeEvent
public void spawnArmorParticles(LivingHurtEvent event)
{
	//WorldServer overworldInst = MinecraftServer.getServer().worldServers[0];
	EntityLivingBase entity = event.entityLiving;

	if(event.entityLiving.worldObj.isRemote && !event.entityLiving.worldObj.isDaytime())
		for (int i = 1; i < 4; i++)
		{
			Item entArmor = entity.getEquipmentInSlot(i).getItem();
			if(entArmor instanceof ItemMithrilHelmet)
				for (int j = 0; j < 4; ++j)
				{
					event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY, entity.posZ, 1.0D, 1.0D, 1.0D);
					System.out.println("particle");
				}

			if(entArmor instanceof ItemMithrilChestplate)
				for (int j = 0; j < 4; ++j)
					event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.6D, entity.posZ, 1.0D, 1.0D, 1.0D);

			if(entArmor instanceof ItemMithrilLeggings)
				for (int j = 0; j < 4; ++j)
					event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.4D, entity.posZ, 1.0D, 1.0D, 1.0D);

			if(entArmor instanceof ItemMithrilBoots)
				for (int j = 0; j < 4; ++j)
					event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.2D, entity.posZ, 1.0D, 1.0D, 1.0D);
		}
}
}

Link to comment
Share on other sites

You should not invert or remove the world.isRemote check - the whole point of it is that you MUST be on the CLIENT side when spawning particles. Not only that, but LivingHurtEvent is typically if not always posted only on the server side.

 

If you want to spawn particles from there, your best bet would be to send a packet to all nearby clients with the data you need to spawn the particles you want.

Link to comment
Share on other sites

If you want to spawn particles from there, your best bet would be to send a packet to all nearby clients with the data you need to spawn the particles you want.

 

I have no idea how to do that.  I'm using LivingHurtEvent because it's what shieldbug1 suggested.  What event should I be subscribing to if LivingHurtEvent is server sided?

Link to comment
Share on other sites

If the LivingHurtEvent is server only, like coolAlias says, then do your checks as usual (on the server), then if you meet the conditions you want, you will have to send packets. Then on the Client, when the packet is received, create your particles.

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

Alright, am I doing this right?  Now, I'm not sure how to spawn the particles inside the conditionals inside the packets receiver, or if that's not where I do it, then where?  Additionally, when I try to specify the entity to send the packets to, I can't seem to find anything that returns EntityLivingBase in event?

 

MithrilArmorParticles

public class MithrilArmorParticles
{
@SubscribeEvent
public void spawnArmorParticles(LivingHurtEvent event)
{
	EntityLivingBase entity = event.entityLiving;
	if(event.entityLiving.worldObj.isRemote && !event.entityLiving.worldObj.isDaytime())
	{
		for (int i = 1; i < 4; i++)
		{
			Item entArmor = entity.getEquipmentInSlot(i).getItem();
			if(entArmor instanceof ItemMithrilHelmet)
				Artifice.networkWrapper.sendTo("helmet", event.entityLiving); //this is EntityPlayerMP, takes EntityLivingBase, how do?

			if(entArmor instanceof ItemMithrilChestplate)
				Artifice.networkWrapper.sendTo("chestplate", event.entityLiving); //this is EntityPlayerMP, takes EntityLivingBase, how do?

			if(entArmor instanceof ItemMithrilLeggings)
				Artifice.networkWrapper.sendTo("leggings", event.entityLiving); //this is EntityPlayerMP, takes EntityLivingBase, how do?

			if(entArmor instanceof ItemMithrilBoots)
				Artifice.networkWrapper.sendTo("boots", event.entityLiving); //this is EntityPlayerMP, takes EntityLivingBase, how do?
		}
	}
}
}

 

SendMParticles

public class SendMParticles implements IMessage
{
private String text;

public SendMParticles()
{

}

public SendMParticles(String text)
{
	this.text = text;
}

@Override
public void fromBytes(ByteBuf buf)
{
	text = ByteBufUtils.readUTF8String(buf);
}

@Override
public void toBytes(ByteBuf buf)
{
	ByteBufUtils.writeUTF8String(buf, text);
}

public static class Handler implements IMessageHandler<SendMParticles, IMessage>
{
	@Override
	public IMessage onMessage(SendMParticles message, MessageContext ctx)
	{
		System.out.println(String.format("Received %s from %s", message.text, ctx.getServerHandler().playerEntity.getDisplayName()));
		if (message.equals("helmet"))
		{
			event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY, entity.posZ, 0.0D, 0.0D, 0.0D); //how do now?
		}
		if (message.equals("chestplate"))
		{
			event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.6D, entity.posZ, 1.0D, 1.0D, 1.0D); //how do now?
		}
		if(message.equals("leggings"))
		{
			event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.4D, entity.posZ, 1.0D, 1.0D, 1.0D); //how do now?
		}
		if(message.equals("boots"))
		{
			event.entityLiving.worldObj.spawnParticle("suspend", entity.posX, entity.posY + 0.2D, entity.posZ, 1.0D, 1.0D, 1.0D); //how do now?
		}
		return null;
	}
}
}

 

main class

 

@Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
public class Artifice
{
public static SimpleNetworkWrapper networkWrapper;

@EventHandler
public void preinit(FMLPreInitializationEvent event)
{
	networkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel("SendMParticles");
	networkWrapper.registerMessage(SendMParticles.Handler.class, SendMParticles.class, 0, Side.CLIENT);

	MithrilArmorParticles MiArPa = new MithrilArmorParticles();
	MinecraftForge.EVENT_BUS.register(MiArPa);
}
}

Link to comment
Share on other sites

What you want to do is:

 

1. Check your conditions on the server in the event.

2. If conditions are right, create a packet containing the entityLiving's entity id, and send it to any clients tracking it. There is a method for that in WorldServer, but I can't remember what it's called of the top of my head.

3. Through your proxy, handle the packet on the client proxy, by getting the entity through World#getEntityById(), and spawn the particles using the entity's posX, posY, and posZ values.

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

I'm kind of lost right now, how can I handle the packet in the proxy if its not implementing IMessage, and doesn't have all the rest of the packet handling class inside it?  I haven't had to use proxies yet either so I don't know if I'm missing things in it that I'd need.  And, I couldn't find anything suitable in WorldServer. :S

Link to comment
Share on other sites

1. Create two classes, a ClientProxy and a CommonProxy. ClientProxy must extend CommonProxy. You can additionaly create a ServerProxy to also extend CommonProxy.

2. In your main mod file:

@SidedProxy(cilentSide = "com.somepackage.ClientProxyClassName", serverSide = "com.somepackage.ServerProxyClassName"); //Fully qualified name of your proxies.
public static CommonProxy proxy;

3. Create a method in your CommonProxy that does nothing and takes in your IMessage implementation as a parameter and does nothing.

 

4. In your IMessageHandlerClass in the onMessage method:

MainClass.proxy.yourMethodHere(message);

 

5. In your client proxy:

@Override
public void someMethod(YourPacket packet)
{
Entity entity = FMLClientHandler.instance().getWorldClient().getEntityById(packet.entityID);
//Spawn particles here using entity.worldObj and entity.posX, posY and posZ.
}

 

 

 

 

Now as for sending the packet, rather than using the actual SimpleNetworkWrapper, what you do is this, in your event handler method

if(!event.entityLiving.worldObj.isRemote) //Server!
{
    YourPacket packet = new YourPacket(event.entityLiving.getEntityId());
    ((WorldServer)event.entityLiving.worldObj).getEntityTracker().func_151247_a(event.entityLiving, packet);
}

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Link to comment
Share on other sites

Ok, so then I'd need to change the constructor to SendParticles(int message) instead of SendParticles(String message), then how should I alter the fromBytes and toBytes methods to work with these changes, readVarInt?  If so, what would the maxSize be?

 

public class SendParticles implements IMessage
{
private int index;

public SendParticles(int index)
{
	this.index = index;
}

@Override
public void fromBytes(ByteBuf buf)
{
	index = ByteBufUtils.readUTF8String(buf);
}

@Override
public void toBytes(ByteBuf buf)
{
	ByteBufUtils.writeUTF8String(buf, index);
}

public static class Handler implements IMessageHandler<SendParticles, IMessage>
{
	@Override
	public IMessage onMessage(SendParticles message, MessageContext ctx)
	{
		Artifice.comProxy.doParticles(message);

		/*WorldClient clientInst = Minecraft.getMinecraft().theWorld;
		Entity ent = clientInst.getEntityByID(Integer.parseInt(message.toString()));
		if (message.equals("helmet"))
		{
			clientInst.spawnParticle("suspend", ent.posX, ent.posY, ent.posZ, 0.0D, 0.0D, 0.0D);
		}
		if (message.equals("chestplate"))
		{
			clientInst.spawnParticle("suspend", ent.posX, ent.posY + 0.6D, ent.posZ, 1.0D, 1.0D, 1.0D);
		}
		if(message.equals("leggings"))
		{
			clientInst.spawnParticle("suspend", ent.posX, ent.posY + 0.4D, ent.posZ, 1.0D, 1.0D, 1.0D);
		}
		if(message.equals("boots"))
		{
			clientInst.spawnParticle("suspend", ent.posX, ent.posY + 0.2D, ent.posZ, 1.0D, 1.0D, 1.0D);
		}*/

		return null;
	}
}
}

 

Edit:  Additionally, it's erroring on func_151247_a, and says to change it to func_151248_b, then that errors and says to change it back to func_151247_a.  What do I want to do here?

Link to comment
Share on other sites

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

    • https://pastebin.com/CKfYxe6f thats the mod list its just some mods that i like and grouped together along with some newer mods that caught my eye. i load into minecraft fine, click singleplayer, this is a new modpack so i click create new world, everything seems fine and then i click create new world it starts preparing for world creation and then this error message pops up. Errors in currently selected datapacks prevented the world from loading. You can either try to load it with only the vanilla data pack ("safe mode"), or go back to the title screen and fix it manually. The game doesnt crash so I don't know if a crash report would help. when i click safe mode the screen freezes for a minute and then nothing happens and im still on that error screen. clicking back to title screen takes me back to the title screen. in the data packs screen there is a lot of red data packs. ive tried turning them all off but then when it tries to validate it says "Data pack validation failed!" also all the data packs just automatically downloaded with the mods i havnt added any extra ones. i can post a picture of the select data packs screen but it would take a lot of scrolling and multiple pictures so just let me know if i need to do that. a few examples of the text on the red dats packs are the following. - examplemod resources (this is what most of them say) - resources used for aquaculture (or whatever other mod name) - mobcatcher resources (again changes with mod name) -${mod_name} some also have mod descriptions or just the mod name or other variations of modname stuff or modname resources and when hovering over any of the red ones it says (made for an older version of minecraft) even when the mod says its for 1.18.2. lmk if you need any more info like logs or stuff and sorry for the long message just want to give lots of info.  
    • Problem was in specific method in Screen (version 1.20.4) protected <T extends GuiEventListener & Renderable & NarratableEntry> T addRenderableWidget(T arg) { this.renderables.add((Renderable)arg); return this.addWidget(arg); } I assume because of these multi-inheritance interfaces. After rewriting it in the fields, everything worked. Final working code: @Shadow @Final public List<Renderable> renderables; @Shadow @Final private List<GuiEventListener> children; @Shadow @Final private List<NarratableEntry> narratables; public void custom$addRenderableWidget(AbstractWidget widget) { renderables.add(widget); children.add(widget); narratables.add(widget); }  
    • hey, I'm trying to make a server with mods and it's not working. when I run it without mods, it works normally Log:[27maj2024 17:53:12.540] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher running: args [--launchTarget, forgeserver, --fml.forgeVersion, 40.2.0, --fml.mcVersion, 1.18.2, --fml.forgeGroup, net.minecraftforge, --fml.mcpVersion, 20220404.173914] [27maj2024 17:53:12.544] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher 9.1.3+9.1.3+main.9b69c82a starting: java version 22.0.1 by Oracle Corporation [27maj2024 17:53:12.660] [main/INFO] [mixin/]: SpongePowered MIXIN Subsystem Version=0.8.5 Source=union:/C:/Users/kamil/Desktop/server/libraries/org/spongepowered/mixin/0.8.5/mixin-0.8.5.jar%2314!/ Service=ModLauncher Env=SERVER [27maj2024 17:53:13.006] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\kamil\Desktop\server\libraries\net\minecraftforge\fmlcore\1.18.2-40.2.0\fmlcore-1.18.2-40.2.0.jar is missing mods.toml file [27maj2024 17:53:13.010] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\kamil\Desktop\server\libraries\net\minecraftforge\javafmllanguage\1.18.2-40.2.0\javafmllanguage-1.18.2-40.2.0.jar is missing mods.toml file [27maj2024 17:53:13.013] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\kamil\Desktop\server\libraries\net\minecraftforge\lowcodelanguage\1.18.2-40.2.0\lowcodelanguage-1.18.2-40.2.0.jar is missing mods.toml file [27maj2024 17:53:13.015] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\kamil\Desktop\server\libraries\net\minecraftforge\mclanguage\1.18.2-40.2.0\mclanguage-1.18.2-40.2.0.jar is missing mods.toml file [27maj2024 17:53:13.101] [main/INFO] [net.minecraftforge.fml.loading.moddiscovery.JarInJarDependencyLocator/]: No dependencies to load found. Skipping! [27maj2024 17:53:15.035] [main/INFO] [mixin/]: Compatibility level set to JAVA_17 [27maj2024 17:53:15.075] [main/INFO] [cpw.mods.modlauncher.LaunchServiceHandler/MODLAUNCHER]: Launching target 'forgeserver' with arguments [] [27maj2024 17:53:15.139] [main/WARN] [mixin/]: Reference map 'bloodmagic.refmap.json' for bloodmagic.mixins.json could not be read. If this is a development environment you can ignore this message [27maj2024 17:53:15.415] [main/WARN] [mixin/]: Error loading class: net/minecraft/world/item/ItemStack (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.416] [main/WARN] [mixin/]: @Mixin target net.minecraft.world.item.ItemStack was not found placebo.mixins.json:ItemStackMixin [27maj2024 17:53:15.439] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.447] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.449] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.456] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.457] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.461] [main/WARN] [mixin/]: Error loading class: java/util/Map$Entry (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.461] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.463] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:15.463] [main/WARN] [mixin/]: Error loading class: java/lang/invoke/MethodHandles$Lookup (java.lang.IllegalArgumentException: Unsupported class file major version 66) [27maj2024 17:53:16.436] [main/WARN] [mixin/]: Error loading class: java/lang/Boolean (java.lang.IllegalArgumentException: Unsupported class file major version 66) Mods:https://ibb.co/xj5qHYK
    • How did you manage to get it working?
    • Hi Everyone! I was playing in modded singleplayer, and suddenly mobs stopped moving, I couldn't hit them, basically I could do things but nothing happened, like destroying blocks didn't drop it, things like that. When I tried to quit and save my world, it was just writing Saving World but nothing happened, and eventually I always had to restart my computer to stop minecraft. Can someone please help me find out what could cause the issue? Here is my debug log: https://pastebin.com/X9F0M9sq This is not the complete debug log, I was pasting the last couple of hundreds of rows because of the size. In case it's needed, I will repaste rows earlier. Thank you very much in advance!  
  • Topics

×
×
  • Create New...

Important Information

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