Jump to content

Recommended Posts

Posted

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);
}
}

Posted

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)
{

}

Posted

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.

Posted

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.

Posted

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

Posted

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.

Posted

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);
		}
}
}

Posted

Yep it's being called.

event.entityLiving.worldObj.isRemote

is not evaluating true though.

 

Scratch that edit, it does work inverted or when removed, however it crashes and corrupts the world when you take damage while wearing the armor at night.

Posted

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.

Posted

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?

Posted

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.

Posted

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);
}
}

Posted

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.

Posted

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

Posted

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.

Posted

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?

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.