From f5de384858cfc2cd3504223cbddd13244bafda11 Mon Sep 17 00:00:00 2001 From: celeste Date: Fri, 18 Aug 2023 21:43:02 -0600 Subject: [PATCH] Move initial join sync to entity tracking This fixes the initial join sync on dedicated servers, as well as various issues around the sync being sent too early (which is most prominent on Quilt), which results in the receiving client crashing This also splits event lambdas into their own functions for readability, and merges PacketSync and PacketGenderInfo to a single WildfireSync class, using PacketGenderInfo (renamed to PacketSync) as the only packet class sent over the network. --- .../java/com/wildfire/main/GenderPlayer.java | 5 +- .../wildfire/main/WildfireEventHandler.java | 120 +++++++----------- .../wildfire/main/WildfireGenderServer.java | 32 +++-- .../main/networking/PacketSendGenderInfo.java | 67 ---------- .../wildfire/main/networking/PacketSync.java | 88 ------------- ...{PacketGenderInfo.java => SyncPacket.java} | 18 ++- .../main/networking/WildfireSync.java | 108 ++++++++++++++++ 7 files changed, 188 insertions(+), 250 deletions(-) delete mode 100644 src/main/java/com/wildfire/main/networking/PacketSendGenderInfo.java delete mode 100644 src/main/java/com/wildfire/main/networking/PacketSync.java rename src/main/java/com/wildfire/main/networking/{PacketGenderInfo.java => SyncPacket.java} (89%) create mode 100644 src/main/java/com/wildfire/main/networking/WildfireSync.java diff --git a/src/main/java/com/wildfire/main/GenderPlayer.java b/src/main/java/com/wildfire/main/GenderPlayer.java index d344b694..4d3cae6c 100644 --- a/src/main/java/com/wildfire/main/GenderPlayer.java +++ b/src/main/java/com/wildfire/main/GenderPlayer.java @@ -44,8 +44,6 @@ public class GenderPlayer { private float bounceMultiplier = Configuration.BOUNCE_MULTIPLIER.getDefault(); private float floppyMultiplier = Configuration.FLOPPY_MULTIPLIER.getDefault(); - public boolean lockSettings = false; - public SyncStatus syncStatus = SyncStatus.UNKNOWN; private boolean showBreastsInArmor = Configuration.SHOW_IN_ARMOR.getDefault(); private boolean armorPhysOverride = Configuration.ARMOR_PHYSICS_OVERRIDE.getDefault(); @@ -191,7 +189,6 @@ public static JsonObject toJsonObject(GenderPlayer plr) { public static GenderPlayer loadCachedPlayer(UUID uuid, boolean markForSync) { GenderPlayer plr = WildfireGender.getPlayerById(uuid); if (plr != null) { - plr.lockSettings = false; plr.syncStatus = SyncStatus.CACHED; Configuration config = plr.getConfig(); plr.updateGender(config.get(Configuration.GENDER)); @@ -218,7 +215,7 @@ public static GenderPlayer loadCachedPlayer(UUID uuid, boolean markForSync) { } return null; } - + public static void saveGenderInfo(GenderPlayer plr) { Configuration config = plr.getConfig(); config.set(Configuration.USERNAME, plr.uuid); diff --git a/src/main/java/com/wildfire/main/WildfireEventHandler.java b/src/main/java/com/wildfire/main/WildfireEventHandler.java index bcf55b40..138bc47d 100644 --- a/src/main/java/com/wildfire/main/WildfireEventHandler.java +++ b/src/main/java/com/wildfire/main/WildfireEventHandler.java @@ -19,98 +19,64 @@ package com.wildfire.main; import com.wildfire.gui.screen.WardrobeBrowserScreen; -import com.wildfire.main.networking.PacketSendGenderInfo; -import com.wildfire.main.networking.PacketSync; - -import java.util.UUID; - +import com.wildfire.main.networking.WildfireSync; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; -import net.minecraft.util.Identifier; +import net.minecraft.entity.Entity; +import net.minecraft.world.World; import org.lwjgl.glfw.GLFW; -public class WildfireEventHandler { - - public static final KeyBinding toggleEditGUI = KeyBindingHelper.registerKeyBinding(new KeyBinding("key.wildfire_gender.gender_menu", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_G, "category.wildfire_gender.generic")); +import java.util.UUID; - private static int timer = 0; +@Environment(EnvType.CLIENT) +public class WildfireEventHandler { + public static final KeyBinding toggleEditGUI = KeyBindingHelper.registerKeyBinding( + new KeyBinding("key.wildfire_gender.gender_menu", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_G, "category.wildfire_gender.generic")); + private static long timer = 0; public static void registerClientEvents() { + ClientEntityEvents.ENTITY_LOAD.register(WildfireEventHandler::onEntityLoad); + ClientTickEvents.END_CLIENT_TICK.register(WildfireEventHandler::onClientTick); + ClientPlayNetworking.registerGlobalReceiver(WildfireSync.SYNC_IDENTIFIER, WildfireSync::handle); + } - ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { - if (!handler.getPlayer().getWorld().isClient()) { - //Send all other players to the player who joined. Note: We don't send the player to - // other players as that will happen once the player finishes sending themselves to the server - PacketSync.sendTo(handler.getPlayer()); - } - }); - - ClientEntityEvents.ENTITY_LOAD.register((entity, world) -> { - if(!world.isClient) return; - if(entity instanceof AbstractClientPlayerEntity plr) { - UUID uuid = plr.getUuid(); - GenderPlayer aPlr = WildfireGender.getPlayerById(plr.getUuid()); - if (aPlr == null) { - aPlr = new GenderPlayer(uuid); - WildfireGender.CLOTHING_PLAYERS.put(uuid, aPlr); - WildfireGender.loadGenderInfoAsync(uuid, uuid.equals(MinecraftClient.getInstance().player.getUuid())); - return; - } - } - /*if(!world.isClient) return; - - if(entity instanceof AbstractClientPlayerEntity plr) { - UUID uuid = plr.getUuid(); - GenderPlayer aPlr = WildfireGender.getPlayerById(plr.getUuid()); - if(aPlr == null) { - aPlr = new GenderPlayer(uuid); - WildfireGender.CLOTHING_PLAYERS.put(uuid, aPlr); - WildfireGender.loadGenderInfoAsync(uuid, uuid.equals(MinecraftClient.getInstance().player.getUuid())); - return; - } - }*/ - }); - - ClientTickEvents.END_CLIENT_TICK.register(client -> { - if(client.world == null) WildfireGender.CLOTHING_PLAYERS.clear(); - - boolean isVanillaServer = !ClientPlayNetworking.canSend(new Identifier(WildfireGender.MODID, "send_gender_info")); - - - if(!isVanillaServer) { - //20 ticks per second / 5 = 4 times per second - - timer++; - if (timer >= 5) { - try { - GenderPlayer aPlr = WildfireGender.getPlayerById(MinecraftClient.getInstance().player.getUuid()); - if(aPlr == null /*|| !aPlr.needsSync*/) return; - PacketSendGenderInfo.send(aPlr); - } catch (Exception e) { - //e.printStackTrace(); - } - timer = 0; - } - } - - while (toggleEditGUI.wasPressed()) { - //client.setScreen(new WildfirePlayerListScreen(client)); //old screen - try { - MinecraftClient.getInstance().setScreen(new WardrobeBrowserScreen(null, MinecraftClient.getInstance().player.getUuid())); - } catch(Exception ignored) {} + private static void onEntityLoad(Entity entity, World world) { + if(!world.isClient() || MinecraftClient.getInstance().player == null) return; + if(entity instanceof AbstractClientPlayerEntity plr) { + UUID uuid = plr.getUuid(); + GenderPlayer aPlr = WildfireGender.getPlayerById(plr.getUuid()); + if(aPlr == null) { + aPlr = new GenderPlayer(uuid); + WildfireGender.CLOTHING_PLAYERS.put(uuid, aPlr); + WildfireGender.loadGenderInfoAsync(uuid, uuid.equals(MinecraftClient.getInstance().player.getUuid())); } - }); + } + } - ClientPlayNetworking.registerGlobalReceiver(new Identifier(WildfireGender.MODID, "sync"), - (client, handler, buf, responseSender) -> { - PacketSync.handle(client, handler, buf, responseSender); - }); + private static void onClientTick(MinecraftClient client) { + if(client.world == null || client.player == null) { + WildfireGender.CLOTHING_PLAYERS.clear(); + return; + } + + // Only attempt to sync if the server will accept the packet, and only once every 5 ticks, or around 4 times a second + if(ClientPlayNetworking.canSend(WildfireSync.SEND_GENDER_IDENTIFIER) && timer++ % 5 == 0) { + GenderPlayer aPlr = WildfireGender.getPlayerById(client.player.getUuid()); + // sendToServer will only actually send a packet if any changes have been made that need to be synced, + // or if we haven't synced before. + if(aPlr != null) WildfireSync.sendToServer(aPlr); + } + + if(toggleEditGUI.wasPressed() && client.currentScreen == null) { + client.setScreen(new WardrobeBrowserScreen(null, client.player.getUuid())); + } } } diff --git a/src/main/java/com/wildfire/main/WildfireGenderServer.java b/src/main/java/com/wildfire/main/WildfireGenderServer.java index 5c0ab908..2244634e 100644 --- a/src/main/java/com/wildfire/main/WildfireGenderServer.java +++ b/src/main/java/com/wildfire/main/WildfireGenderServer.java @@ -17,22 +17,34 @@ */ package com.wildfire.main; -import com.wildfire.main.networking.PacketSendGenderInfo; + +import com.wildfire.main.networking.WildfireSync; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.networking.v1.EntityTrackingEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.util.Identifier; - +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; public class WildfireGenderServer implements ModInitializer { - - @Override public void onInitialize() { // while this class is named 'Server', this is actually a common code path, // so we can safely register here for both sides. WildfireSounds.register(); - ServerPlayNetworking.registerGlobalReceiver(new Identifier(WildfireGender.MODID, "send_gender_info"), - (server, playerEntity, handler, buf, responseSender) -> { - PacketSendGenderInfo.handle(server, playerEntity, handler, buf, responseSender); - }); + ServerPlayNetworking.registerGlobalReceiver(WildfireSync.SEND_GENDER_IDENTIFIER, WildfireSync::handle); + EntityTrackingEvents.START_TRACKING.register(this::onBeginTracking); + } + + private void onBeginTracking(Entity tracked, ServerPlayerEntity syncTo) { + if(tracked instanceof PlayerEntity toSync) { + GenderPlayer genderToSync = WildfireGender.getPlayerById(toSync.getUuid()); + if(genderToSync == null) return; + // Note that we intentionally don't check if we've previously synced a player with this code path; + // because we use entity tracking to sync, it's entirely possible that one player would leave the + // tracking distance of another, change their settings, and then re-enter their tracking distance; + // we wouldn't sync while they're out of tracking distance, and as such, their settings would be out + // of sync until they relog. + WildfireSync.sendToClient(syncTo, genderToSync); + } } -} \ No newline at end of file +} diff --git a/src/main/java/com/wildfire/main/networking/PacketSendGenderInfo.java b/src/main/java/com/wildfire/main/networking/PacketSendGenderInfo.java deleted file mode 100644 index 1e66a8ac..00000000 --- a/src/main/java/com/wildfire/main/networking/PacketSendGenderInfo.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - Wildfire's Female Gender Mod is a female gender mod created for Minecraft. - Copyright (C) 2023 WildfireRomeo - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -package com.wildfire.main.networking; - -import com.wildfire.main.GenderPlayer; -import com.wildfire.main.WildfireGender; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; - -public class PacketSendGenderInfo extends PacketGenderInfo { - - public PacketSendGenderInfo(GenderPlayer plr) { - super(plr); - } - - public PacketSendGenderInfo(PacketByteBuf buffer) { - super(buffer); - } - - public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - PacketSendGenderInfo packet = new PacketSendGenderInfo(buf); - - if (player == null || !player.getUuid().equals(packet.uuid)) { - //Validate the uuid matches the player who sent it - return; - } - GenderPlayer plr = WildfireGender.getOrAddPlayerById(packet.uuid); - packet.updatePlayerFromPacket(plr); - //System.out.println("Received data from player " + plr.uuid); - //Sync changes to other online players - PacketSync.sendToOthers(player, plr); - } - - // Send Packet - - public static void send(GenderPlayer plr) { - if(plr == null || !plr.needsSync) return; - PacketSendGenderInfo packet = new PacketSendGenderInfo(plr); - PacketByteBuf buffer = PacketByteBufs.create(); - packet.encode(buffer); - ClientPlayNetworking.send(new Identifier(WildfireGender.MODID, "send_gender_info"), buffer); - //WildfireGender.NETWORK.sendToServer(new PacketSendGenderInfo(plr)); - plr.needsSync = false; - } -} diff --git a/src/main/java/com/wildfire/main/networking/PacketSync.java b/src/main/java/com/wildfire/main/networking/PacketSync.java deleted file mode 100644 index 2c13962a..00000000 --- a/src/main/java/com/wildfire/main/networking/PacketSync.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - Wildfire's Female Gender Mod is a female gender mod created for Minecraft. - Copyright (C) 2023 WildfireRomeo - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -package com.wildfire.main.networking; - -import com.wildfire.main.GenderPlayer; -import com.wildfire.main.WildfireGender; -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; -import net.fabricmc.fabric.api.networking.v1.PacketSender; -import net.fabricmc.fabric.api.networking.v1.PlayerLookup; -import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; - -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; - -public class PacketSync extends PacketGenderInfo { - - public PacketSync(GenderPlayer plr) { - super(plr); - } - - public PacketSync(PacketByteBuf buffer) { - super(buffer); - } - - public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { - PacketSync packet = new PacketSync(buf); - - if (!packet.uuid.equals(MinecraftClient.getInstance().player.getUuid())) { - GenderPlayer plr = WildfireGender.getOrAddPlayerById(packet.uuid); - packet.updatePlayerFromPacket(plr); - plr.syncStatus = GenderPlayer.SyncStatus.SYNCED; - plr.lockSettings = true; - //System.out.println("Received player data " + plr.uuid); - } else { - //System.out.println("Ignoring packet, this is yourself."); - } - } - - // Send Packet - - public static void sendToOthers(ServerPlayerEntity player, GenderPlayer genderPlayer) { - if (genderPlayer != null && player.getServer() != null) { - PacketSync packet = new PacketSync(genderPlayer); - PacketByteBuf buffer = PacketByteBufs.create(); - packet.encode(buffer); - - for (ServerPlayerEntity serverPlayer : PlayerLookup.all(player.getServer())) { - if (!player.getUuid().equals(serverPlayer.getUuid())) { - ServerPlayNetworking.send(serverPlayer, new Identifier(WildfireGender.MODID, "sync"), buffer); - } - } - } - } - - public static void sendTo(ServerPlayerEntity player) { - for (Map.Entry entry : WildfireGender.CLOTHING_PLAYERS.entrySet()) { - UUID uuid = entry.getKey(); - if (!player.getUuid().equals(uuid)) { - PacketSync packet = new PacketSync(entry.getValue()); - PacketByteBuf buffer = PacketByteBufs.create(); - packet.encode(buffer); - ServerPlayNetworking.send(player, new Identifier(WildfireGender.MODID, "sync"), buffer); - } - } - } -} diff --git a/src/main/java/com/wildfire/main/networking/PacketGenderInfo.java b/src/main/java/com/wildfire/main/networking/SyncPacket.java similarity index 89% rename from src/main/java/com/wildfire/main/networking/PacketGenderInfo.java rename to src/main/java/com/wildfire/main/networking/SyncPacket.java index eec1cac0..588eff36 100644 --- a/src/main/java/com/wildfire/main/networking/PacketGenderInfo.java +++ b/src/main/java/com/wildfire/main/networking/SyncPacket.java @@ -21,11 +21,12 @@ import com.wildfire.main.Breasts; import com.wildfire.main.GenderPlayer; import com.wildfire.main.GenderPlayer.Gender; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.minecraft.network.PacketByteBuf; import java.util.UUID; -public abstract class PacketGenderInfo { +class SyncPacket { protected final UUID uuid; private final Gender gender; private final float bust_size; @@ -42,7 +43,7 @@ public abstract class PacketGenderInfo { private final boolean hurtSounds; - protected PacketGenderInfo(GenderPlayer plr) { + protected SyncPacket(GenderPlayer plr) { this.uuid = plr.uuid; this.gender = plr.getGender(); this.bust_size = plr.getBustSize(); @@ -63,7 +64,7 @@ protected PacketGenderInfo(GenderPlayer plr) { this.cleavage = breasts.getCleavage(); } - protected PacketGenderInfo(PacketByteBuf buffer) { + protected SyncPacket(PacketByteBuf buffer) { this.uuid = buffer.readUuid(); this.gender = buffer.readEnumConstant(Gender.class); this.bust_size = buffer.readFloat(); @@ -82,7 +83,7 @@ protected PacketGenderInfo(PacketByteBuf buffer) { this.cleavage = buffer.readFloat(); } - public void encode(PacketByteBuf buffer) { + protected void encode(PacketByteBuf buffer) { buffer.writeUuid(this.uuid); buffer.writeEnumConstant(this.gender); buffer.writeFloat(this.bust_size); @@ -118,4 +119,13 @@ protected void updatePlayerFromPacket(GenderPlayer plr) { breasts.updateUniboob(uniboob); breasts.updateCleavage(cleavage); } + + /** + * Convenience method for creating a sync packet to send over the network + */ + protected PacketByteBuf getPacket() { + PacketByteBuf packet = PacketByteBufs.create(); + this.encode(packet); + return packet; + } } diff --git a/src/main/java/com/wildfire/main/networking/WildfireSync.java b/src/main/java/com/wildfire/main/networking/WildfireSync.java new file mode 100644 index 00000000..50d86254 --- /dev/null +++ b/src/main/java/com/wildfire/main/networking/WildfireSync.java @@ -0,0 +1,108 @@ +/* + Wildfire's Female Gender Mod is a female gender mod created for Minecraft. + Copyright (C) 2023 WildfireRomeo + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +package com.wildfire.main.networking; + +import com.wildfire.main.GenderPlayer; +import com.wildfire.main.WildfireGender; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.PlayerLookup; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; + +public class WildfireSync { + // While these two identifiers could be combined into one `sync` identifier, this is kept as-is for the sake of compatibility + // with older versions, and servers that may implement syncing on other platforms (such as Spigot or any of its forks). + public static final Identifier SEND_GENDER_IDENTIFIER = new Identifier(WildfireGender.MODID, "send_gender_info"); + public static final Identifier SYNC_IDENTIFIER = new Identifier(WildfireGender.MODID, "sync"); + + @SuppressWarnings("unused") + @Environment(EnvType.CLIENT) + public static void handle(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + SyncPacket packet = new SyncPacket(buf); + if(client.player == null || packet.uuid.equals(client.player.getUuid())) return; + + GenderPlayer plr = WildfireGender.getOrAddPlayerById(packet.uuid); + packet.updatePlayerFromPacket(plr); + plr.syncStatus = GenderPlayer.SyncStatus.SYNCED; + } + + @SuppressWarnings("unused") + public static void handle(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) { + SyncPacket packet = new SyncPacket(buf); + if(player == null || !player.getUuid().equals(packet.uuid)) return; + + GenderPlayer plr = WildfireGender.getOrAddPlayerById(packet.uuid); + packet.updatePlayerFromPacket(plr); + sendToAllClients(player, plr); + } + + /** + * Sync a player's configuration to all nearby connected players + * + * @param toSync The {@link ServerPlayerEntity player} to sync + * @param genderPlayer The {@link GenderPlayer configuration} for the target player + */ + public static void sendToAllClients(ServerPlayerEntity toSync, GenderPlayer genderPlayer) { + if(genderPlayer == null || toSync.getServer() == null) return; + + PacketByteBuf packet = new SyncPacket(genderPlayer).getPacket(); + PlayerLookup.tracking(toSync).forEach((sendTo) -> { + if(sendTo.getUuid().equals(toSync.getUuid())) return; + sendPacketToClient(sendTo, packet); + }); + } + + /** + * Sync a player's configuration to another connected player + * + * @param sendTo The {@link ServerPlayerEntity player} to send the sync to + * @param toSync The {@link GenderPlayer configuration} for the player being synced + */ + public static void sendToClient(ServerPlayerEntity sendTo, GenderPlayer toSync) { + sendPacketToClient(sendTo, new SyncPacket(toSync).getPacket()); + } + + /** + * Send the client player's configuration to the server for syncing to other players + * + * @param plr The {@link GenderPlayer configuration} for the client player + */ + @Environment(EnvType.CLIENT) + public static void sendToServer(GenderPlayer plr) { + if(plr == null || !plr.needsSync) return; + PacketByteBuf buffer = new SyncPacket(plr).getPacket(); + ClientPlayNetworking.send(SEND_GENDER_IDENTIFIER, buffer); + plr.needsSync = false; + } + + private static void sendPacketToClient(ServerPlayerEntity sendTo, PacketByteBuf packet) { + if(ServerPlayNetworking.canSend(sendTo, SYNC_IDENTIFIER)) { + ServerPlayNetworking.send(sendTo, SYNC_IDENTIFIER, packet); + } + } +}