dalobstah Posted October 24, 2018 Posted October 24, 2018 (edited) 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 October 26, 2018 by dalobstah Quote
IvanSteklow Posted October 24, 2018 Posted October 24, 2018 So, I have same problem with particles. Try to make cycle of particle spawn with random position or try to see how furnace/torch/lava particle generator works. 1 Quote
V0idWa1k3r Posted October 24, 2018 Posted October 24, 2018 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. Quote
dalobstah Posted October 24, 2018 Author Posted October 24, 2018 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? Quote
V0idWa1k3r Posted October 24, 2018 Posted October 24, 2018 13 minutes ago, dalobstah said: How would I go about getting the clients aware of particles or using packets? You either need the data to be consistent for the client with DataParameter variables or use packets. Quote
dalobstah Posted October 25, 2018 Author Posted October 25, 2018 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? Quote
V0idWa1k3r Posted October 25, 2018 Posted October 25, 2018 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. 1 Quote
dalobstah Posted October 25, 2018 Author Posted October 25, 2018 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; } } 1 1 Quote
Recommended Posts
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.