Add networking option to only send player skin data when the server has requested it.

This commit is contained in:
Sollace 2021-08-03 18:30:34 +02:00
parent eb8ab20e23
commit fcbc95e14e
6 changed files with 68 additions and 32 deletions

View file

@ -36,6 +36,11 @@ public interface IPony {
*/
boolean isPerformingRainboom(LivingEntity entity);
/**
* Returns whether this is one of the default ponies assigned to a player without a custom skin.
*/
boolean isDefault();
/**
* Unlike sneaking, crouching is a more specific animation parameter that controls whether the player is visible
* nose to the ground, crouching the sand.

View file

@ -73,7 +73,7 @@ public class MsgPonyData implements IPonyData {
this.noSkin = noSkin;
}
public void toBuffer(PacketByteBuf buffer) {
public PacketByteBuf toBuffer(PacketByteBuf buffer) {
buffer.writeInt(race.ordinal());
buffer.writeInt(tailLength.ordinal());
buffer.writeInt(gender.ordinal());
@ -89,6 +89,7 @@ public class MsgPonyData implements IPonyData {
buffer.writeInt(gear[i].ordinal());
}
buffer.writeInt(wearableColor);
return buffer;
}
public boolean isNoSkin() {

View file

@ -1,51 +1,70 @@
package com.minelittlepony.api.pony.network.fabric;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.network.MsgPonyData;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import com.minelittlepony.client.MineLittlePony;
@Environment(EnvType.CLIENT)
public interface Channel {
Consumer<MsgPonyData> CLIENT_PONY_DATA = clientToServer(
new Identifier("minelittlepony", "pony_data"),
MsgPonyData::new,
MsgPonyData::toBuffer,
(packet, player) -> {
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, packet.isNoSkin(), EnvType.SERVER);
});
public class Channel {
private static final Identifier CLIENT_PONY_DATA = new Identifier("minelittlepony", "pony_data");
private static final Identifier REQUEST_PONY_DATA = new Identifier("minelittlepony", "request_pony_data");
static void bootstrap() { }
private static boolean registered;
static <T> Consumer<T> clientToServer(Identifier id, Function<PacketByteBuf, T> factory,
BiConsumer<T, PacketByteBuf> bufferWriter,
BiConsumer<T, PlayerEntity> handler) {
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, hhandler, buffer, responseSender) -> {
T packet = factory.apply(buffer);
public static void bootstrap() {
ClientLoginConnectionEvents.INIT.register((handler, client) -> {
registered = false;
MineLittlePony.logger.info("Resetting registered flag");
});
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
MineLittlePony.logger.info("Sending consent packet to " + handler.getPlayer().getName().getString());
sender.sendPacket(REQUEST_PONY_DATA, PacketByteBufs.empty());
});
ClientPlayNetworking.registerGlobalReceiver(REQUEST_PONY_DATA, (client, handler, ignored, sender) -> {
if (client.player != null) {
IPony pony = MineLittlePony.getInstance().getManager().getPony(client.player);
registered = true;
MineLittlePony.logger.info("Server has just consented");
sender.sendPacket(CLIENT_PONY_DATA, new MsgPonyData(pony.getMetadata(), pony.isDefault()).toBuffer(PacketByteBufs.create()));
}
});
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
MsgPonyData packet = new MsgPonyData(buffer);
server.execute(() -> {
handler.accept(packet, player);
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, packet.isNoSkin(), EnvType.SERVER);
});
});
return packet -> {
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
throw new RuntimeException("Client packet send called by the server");
}
public static void broadcastPonyData(MsgPonyData packet) {
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
throw new RuntimeException("Client packet send called by the server");
}
if (MineLittlePony.getInstance().getConfig().passiveNetworking.get()
&& !registered) {
if (MinecraftClient.getInstance().isInSingleplayer() || MinecraftClient.getInstance().isIntegratedServerRunning()) {
MineLittlePony.logger.info("Sending pony skin data over as we are either in single-player or lan");
} else {
MineLittlePony.logger.info("Skipping network packet as the server has not consented");
return;
}
}
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
bufferWriter.accept(packet, buf);
ClientPlayNetworking.send(id, buf);
};
ClientPlayNetworking.send(CLIENT_PONY_DATA, packet.toBuffer(PacketByteBufs.create()));
}
}

View file

@ -55,6 +55,11 @@ public class Pony implements IPony {
return this;
}
@Override
public boolean isDefault() {
return defaulted;
}
@Override
public void updateForEntity(Entity entity) {
if (entity instanceof RegistrationHandler && ((RegistrationHandler)entity).shouldUpdateRegistration(this)) {
@ -63,7 +68,7 @@ public class Pony implements IPony {
PlayerEntity clientPlayer = MinecraftClient.getInstance().player;
if (clientPlayer != null) {
if (Objects.equals(entity, clientPlayer) || Objects.equals(((PlayerEntity)entity).getGameProfile(), clientPlayer.getGameProfile())) {
Channel.CLIENT_PONY_DATA.accept(new MsgPonyData(metadata, defaulted));
Channel.broadcastPonyData(new MsgPonyData(metadata, defaulted));
}
}
PonyDataCallback.EVENT.invoker().onPonyDataAvailable((PlayerEntity)entity, metadata, defaulted, EnvType.CLIENT);

View file

@ -27,6 +27,11 @@ public class PonyConfig extends JsonConfig {
public final Setting<Boolean> ponyskulls = value("settings", "ponyskulls", true);
public final Setting<Boolean> frustrum = value("settings", "frustrum", true);
/**
* Temporary flag to enable post-1.18 networking behaviour.
*/
public final Setting<Boolean> passiveNetworking = value("settings", "passiveNetworking", false);
/**
* Debug override for pony sizes.
*/

View file

@ -20,6 +20,7 @@
"minelp.options.tpsmagic": "Magic in third-person",
"minelp.options.ponyskulls": "Pony Skulls",
"minelp.options.frustrum": "Frustum checks",
"minelp.options.passivenetworking": "Passive Networking [Beta]",
"minelp.options.button": "Display On Title Screen",
"minelp.options.button.on": "Always Display\n\nBoth the pony button and HD Skins button are visible (if installed)",
"minelp.options.button.auto": "Display only when HD Skins is not installed",