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