Jump to content

Recommended Posts

Posted (edited)

I'm relatively new to all of this and sure the answer to this is very simple, yet I can't seem to find any answers within the documentation or these forums. I (working in 1.19.2) am trying to write a system of packets to make it so that, when an item is used by one user, it creates particles that are seen by all nearby players. These particles should spawn at the position of the player who uses the items. Right now I have a packet, "ParticlePacket", that is sent from the client of the player using the item to the server. At the server level, a list of nearby players is made and each is sent a separate packet, "ParticleReceivePacket" to their client. (I know these names are not the best, my apologies.) The packets are sending perfectly fine, I have checked this by sending chat messages to players sending and receiving packets. The issue is that I can't find out how to send the original player as a variable to the clients receiving the packet. Sending specific information through a packet seems that it should be a no-brainer, that's pretty much what they're meant for as I understand. But for some reason how to do this completely escapes me. Any advice?

Here's where I register my packets:
ModMessages.class

package com.pinkdotnet.wowozela;

import com.pinkdotnet.wowozela.packet.ParticlePacket;
import com.pinkdotnet.wowozela.packet.ParticleReceivePacket;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;

public class ModMessages {
	private static SimpleChannel INSTANCE;
	
	private static int packetId = 0;
	private static int id() {
		return packetId++;
	}
	
	public static void register()
	{
		SimpleChannel net = NetworkRegistry.ChannelBuilder
				.named(new ResourceLocation(Wowozela.MODID, "messages"))
				.networkProtocolVersion(() -> "1.0")
				.clientAcceptedVersions(s -> true)
				.serverAcceptedVersions(s -> true)
				.simpleChannel();
		INSTANCE = net;
		
		net.messageBuilder(ParticlePacket.class, id(), NetworkDirection.PLAY_TO_SERVER)
			.decoder(ParticlePacket::new)
			.encoder(ParticlePacket::toBytes)
			.consumerMainThread(ParticlePacket::handle)
			.add();
		net.messageBuilder(ParticleReceivePacket.class, id(), NetworkDirection.PLAY_TO_CLIENT)
		.decoder(ParticleReceivePacket::new)
		.encoder(ParticleReceivePacket::toBytes)
		.consumerMainThread(ParticleReceivePacket::handle)
		.add();
	}
	
	
	
	public static <MSG> void sendToServer(MSG message) {
		INSTANCE.sendToServer(message);
	}
	
	public static <MSG> void sendToPlayer(MSG message, ServerPlayer player) {
		INSTANCE.send(PacketDistributor.PLAYER.with(()-> player), message);
	}
}

Here's my client-to-server packet, sent when an item is used:

ParticlePacket.class

package com.pinkdotnet.wowozela.packet;

import java.io.Console;
import java.util.List;
import java.util.function.Supplier;

import com.pinkdotnet.wowozela.ModMessages;
import com.pinkdotnet.wowozela.particle.ModParticles;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import net.minecraft.network.chat.Component;

public class ParticlePacket {
	public ParticlePacket() {
		
	}
	
	public ParticlePacket(FriendlyByteBuf buf) {
		
	}
	
	public void toBytes(FriendlyByteBuf buf) {
		
	}
	
	public boolean handle(Supplier<NetworkEvent.Context> supplier) {
		NetworkEvent.Context context = supplier.get();
		context.enqueueWork(() -> {
			// ON SERVER
			ServerPlayer sender = context.getSender();
			ServerLevel level = sender.getLevel();
			
			List<ServerPlayer> playersList = level.players();
			
			
			for(ServerPlayer player : playersList)
			{
				if(player != sender)
				{
					double distance = Math.sqrt(Math.pow(player.position().x - sender.position().x, 2) + Math.pow(player.position().z - sender.position().z, 2));
					if(distance < 30) {
						ModMessages.sendToPlayer(new ParticleReceivePacket(), player);
					}
				}
			}
		});
		return true;
	}
}

And here's my server-to-client packet, sent to all nearby players.
 

package com.pinkdotnet.wowozela.packet;

import java.io.Console;
import java.util.List;
import java.util.function.Supplier;

import com.pinkdotnet.wowozela.particle.ModParticles;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import net.minecraft.network.chat.Component;

public class ParticleReceivePacket {

	public ParticleReceivePacket() {

	}
	
	public ParticleReceivePacket(FriendlyByteBuf buf) {
		
	}
	
	public void toBytes(FriendlyByteBuf buf) {
		
	}
	
	public static boolean handle(ParticleReceivePacket message, Supplier<NetworkEvent.Context> supplier) {
		NetworkEvent.Context context = supplier.get();
		context.enqueueWork(() -> {
			// ON CLIENT

			//Below line will spawn particles at location of sender, when sender is avaliable
			//level.addParticle(ModParticles.WOWOZELA_PARTICLES.get(), message.sender.position().x, message.sender.position().y + 1.5, message.sender.position().z, ((message.sender.getLookAngle().x/2)), ((message.sender.getLookAngle().y/2)), ((message.sender.getLookAngle().z/2)));
			
		});
		return true;
	}
}

How can I send the sender of the first packet to the receiver of the second one? Feel free to tell me how dumb I am, because I can already feel that the answer to this one is going to be obvious, I just can't find it anywhere and can't figure it out myself.
EDIT 1: Do I need to handle the server-to-client packet in a separate class from the packet class?

Edited by mintmeal
Elaborating on the original question
Posted

Please don't dump code snippets in the forum.

Post complete reproducable examples to github so we can see everything in context.

e.g. you don;t show your item code that triggers all this

 

You shouldn't need to do any custom networking for this unless your processing is none standard.

That item "use" method should get called on both the client and server.

 

From the server you can use ServerLevel.sendParticles()

See for example PotionItem.useOn() which calls sendParticles when isClientSide is false - there are many other examples in the vanilla code

 

https://forge.gemwire.uk/wiki/Particles#Spawning_Particles

 

To answer exact question:

Players are Entitys. Minecraft serializes them over the network using their entityId.

But the player is often implicit in the connection. Its only when another player is referenced that these ids get sent.

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Posted

Thank you for replying, and sorry for filling your screen with my code dumps, I'll use Github next time. ServerLevel.SendParticles was exactly what I needed. Thank you so much!

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

    • that happens every time I enter a new dimension.
    • This is the last line before the crash: [ebwizardry]: Synchronising spell emitters for PixelTraveler But I have no idea what this means
    • What in particular? I barely used that mod this time around, and it's never been a problem in the past.
    • Im trying to build my mod using shade since i use the luaj library however i keep getting this error Reason: Task ':reobfJar' uses this output of task ':shadowJar' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. So i try adding reobfJar.dependsOn shadowJar  Could not get unknown property 'reobfJar' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. my gradle file plugins { id 'eclipse' id 'idea' id 'maven-publish' id 'net.minecraftforge.gradle' version '[6.0,6.2)' id 'com.github.johnrengelman.shadow' version '7.1.2' id 'org.spongepowered.mixin' version '0.7.+' } apply plugin: 'net.minecraftforge.gradle' apply plugin: 'org.spongepowered.mixin' apply plugin: 'com.github.johnrengelman.shadow' version = mod_version group = mod_group_id base { archivesName = mod_id } // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. java.toolchain.languageVersion = JavaLanguageVersion.of(17) //jarJar.enable() println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" minecraft { mappings channel: mapping_channel, version: mapping_version copyIdeResources = true runs { configureEach { workingDirectory project.file('run') property 'forge.logging.markers', 'REGISTRIES' property 'forge.logging.console.level', 'debug' arg "-mixin.config=derp.mixin.json" mods { "${mod_id}" { source sourceSets.main } } } client { // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. property 'forge.enabledGameTestNamespaces', mod_id } server { property 'forge.enabledGameTestNamespaces', mod_id args '--nogui' } gameTestServer { property 'forge.enabledGameTestNamespaces', mod_id } data { workingDirectory project.file('run-data') args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') } } } sourceSets.main.resources { srcDir 'src/generated/resources' } repositories { flatDir { dirs './libs' } maven { url = "https://jitpack.io" } } configurations { shade implementation.extendsFrom shade } dependencies { minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" implementation 'org.luaj:luaj-jse-3.0.2' implementation fg.deobf("com.github.Virtuoel:Pehkui:${pehkui_version}") annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' minecraftLibrary 'luaj:luaj-jse:3.0.2' shade 'luaj:luaj-jse:3.0.2' } // Example for how to get properties into the manifest for reading at runtime. tasks.named('jar', Jar).configure { manifest { attributes([ 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors, 'Specification-Version' : '1', // We are version 1 of ourselves 'Implementation-Title' : project.name, 'Implementation-Version' : project.jar.archiveVersion, 'Implementation-Vendor' : mod_authors, 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", "TweakOrder" : 0, "MixinConfigs" : "derp.mixin.json" ]) } rename 'mixin.refmap.json', 'derp.mixin-refmap.json' } shadowJar { archiveClassifier = '' configurations = [project.configurations.shade] finalizedBy 'reobfShadowJar' } assemble.dependsOn shadowJar reobf { re shadowJar {} } publishing { publications { mavenJava(MavenPublication) { artifact jar } } repositories { maven { url "file://${project.projectDir}/mcmodsrepo" } } } my entire project:https://github.com/kevin051606/DERP-Mod/tree/Derp-1.0-1.20
  • Topics

×
×
  • Create New...

Important Information

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