Jump to content

[1.12.2] [SOLVED] spawnParticle not working


dalobstah

Recommended Posts

I've been trying to get this to work for a few days without much success. Every example I find doesn't work properly and I can't figure out why.

 

public void onUpdate()
{
    --this.fuse;
    if (this.fuse <= 0)
    {
        this.setDead();

        if (!this.world.isRemote)
        {
            world.setBlockState(pos, Blocks.AIR.getDefaultState());
            world.createExplosion(null, this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, 4.f, true);
        }
    }
    else
    {
        Main.proxy.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D, 0.0D, 0.0D, 0.0D);
    }
        
        
        
    if(world.getBlockState(pos).getBlock() instanceof BlockAir) 
    {
        this.setDead();
    }
}
//Client proxy
@Override
public void spawnParticle(EnumParticleTypes particleType, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed)
{
	MINECRAFT.world.spawnParticle(particleType, xCoord, yCoord, zCoord, xSpeed, ySpeed, zSpeed);
}

^ This is the only code that has worked at all, however it doesn't spawn particles in LAN or multiplayer.

 

this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D, 0.0D, 0.0D, 0.0D);

When I try to use this like in EntityTNTPrimed it doesn't work at all. I also experimented with using WorldServer instead of WorldClient, but that resulted in server crashes.

Also, using else if(!this.world.isRemote) instead of just else didn't effect the code.

Edited by dalobstah
Link to comment
Share on other sites

Particles are a client-side thing. Calling the spawn particle method on the server does nothing.

You also do not need a proxy to spawn a particle. The spawning method is present on both sides, but only the client actually does something, the server has a noop implementation.

Blocks spawn particle in a special method Block#randomDisplayTick that is called on the client only.

If you need to spawn particles for every player either make sure that the data for those players stays consistent so their clients are aware of when to spawn particles or use packets.

Link to comment
Share on other sites

32 minutes ago, V0idWa1k3r said:

Particles are a client-side thing. Calling the spawn particle method on the server does nothing.

You also do not need a proxy to spawn a particle. The spawning method is present on both sides, but only the client actually does something, the server has a noop implementation.

Blocks spawn particle in a special method Block#randomDisplayTick that is called on the client only.

If you need to spawn particles for every player either make sure that the data for those players stays consistent so their clients are aware of when to spawn particles or use packets.

I'm spawning the particles on an entity. Nothing I've tried outside of the client proxy has spawned particles. EntityTNTPrimed spawns particles for every player with just this.world.spawnParticle, however that doesn't work at all for me. How would I go about getting the clients aware of particles or using packets?

Link to comment
Share on other sites

4 hours ago, V0idWa1k3r said:

You either need the data to be consistent for the client with DataParameter variables or use packets.

Do you know why this works

Minecraft MINECRAFT = Minecraft.getMinecraft();
MINECRAFT.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D, 0.0D, 0.0D, 0.0D);

but this doesn't

this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D, 0.0D, 0.0D, 0.0D);

It works in vanilla code and in other 1.12.2 mods source code I've looked at, but it doesn't work in my code. Is there a reason?

Link to comment
Share on other sites

You might be calling the second method on the server and so nothing happens. The first implementation ensures that the particles are spawned on the client. However it is also the case that you might be reaching across logical sides there. Basically I think that whenever you are calling these methods the actions actually happen on a server, not on the client. However because you are running the physical client and not the server the proxy being injected is the client proxy. And in that proxy you are explicitly using the client world for spawning your particles. This way the particles work since you are spawning them through a client world and you see them because it is the physical client but what is actually happening is you are reaching for the client from a server thread - and that is called reaching across logical sides and must never be done.

And the reason the second method isn't called on the client is likely because some kind of condition isn't satisfied on the client but is satisfied on the server. For example vanilla uses data parameters to sync the fuse timer of the TNT to the client so it is always aware of the fuse and is able to do client-related stuff according to it, like the flashing animation. You need to satisfy that condition on the client by using a DataParameter or packets, as I've told you twice already.

  • Thanks 1
Link to comment
Share on other sites

Thank you for the help. I got it to work with packets. I'll put the code below for any future googlers

@Override
public void onUpdate()
{
	setFuse(--this.fuse);
		
    if (getFuse() <= 0)
    {
        this.setDead();

        if (!this.world.isRemote)
        {
            	
            world.setBlockState(pos, Blocks.AIR.getDefaultState());
            world.createExplosion(null, this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, 4.f, true);
        }
    }
    else
    {
        ParticlePacket particlePacket = new ParticlePacket(this.posX, this.posY, this.posZ);
        	
        NetworkRegistry.TargetPoint target = new TargetPoint(world.provider.getDimension(), this.posX + 0.5D, this.posY + 1.0D, this.posZ + 0.5D, 20.d);
        CommonProxy.simpleNetworkWrapper.sendToAllAround(particlePacket, target);
    }
        
        
        
    if(world.getBlockState(pos).getBlock() instanceof BlockAir) 
    {
        this.setDead();
    }
}

 

//Message and client handler
public class ParticlePacket implements IMessage
{

	private boolean messageValid;
	
	private double x, y, z;
	
	public ParticlePacket()
	{
		this.messageValid = false;
	}
	
	public ParticlePacket(double x, double y, double z)
	{
		this.x = x;
		this.y = y;
		this.z = z;
		
		this.messageValid = true;
	}
	
	@Override
	public void fromBytes(ByteBuf buf)
	{
		try
		{
			this.x = buf.readDouble();
			this.y = buf.readDouble();
			this.z = buf.readDouble();
		}
		catch(IndexOutOfBoundsException ioe)
		{
			return;
		}
	}

	@Override
	public void toBytes(ByteBuf buf)
	{
		if(!this.messageValid)
			return;
		
		buf.writeDouble(x);
		buf.writeDouble(y);
		buf.writeDouble(z);
	}
	
	
	public static class Handler implements IMessageHandler<ParticlePacket, IMessage>
	{

		@Override
		public IMessage onMessage(ParticlePacket message, MessageContext ctx)
		{
			if(!message.messageValid && ctx.side != Side.CLIENT)
			{
				return null;
			}
			
			
			Minecraft minecraft = Minecraft.getMinecraft();
		    final WorldClient worldClient = minecraft.world;
			
		    minecraft.addScheduledTask(() -> processMessage(message, worldClient));
		    
			return null;
		}
		
		void processMessage(ParticlePacket message, WorldClient worldClient)
		{
			worldClient.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, message.x + 0.5D, message.y + 1.0D, message.z + 0.5D, 0.0D, 0.0D, 0.0D);
		}
		
	}
}

 

//ClientProxy
public static void preInitClientOnly()
{
	CommonProxy.simpleNetworkWrapper.registerMessage(ParticlePacket.Handler.class, ParticlePacket.class, CommonProxy.FUSE_SMOKE, Side.CLIENT);
}

//CommonProxy
public static final byte FUSE_SMOKE = 88;
public static SimpleNetworkWrapper simpleNetworkWrapper;
	
public static void preInitCommon()
{
	simpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel("TestChannel");
	simpleNetworkWrapper.registerMessage(ServerHandlerDummy.class, ParticlePacket.class, FUSE_SMOKE, Side.SERVER);
}

 

//Server handler
public class ServerHandlerDummy implements IMessageHandler<ParticlePacket, IMessage>
{

	@Override
	public IMessage onMessage(ParticlePacket message, MessageContext ctx)
	{
		return null;
	}

}

 

  • Like 1
  • Thanks 1
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



×
×
  • Create New...

Important Information

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