Skip to content

Commit

Permalink
Merge pull request #70 from DimasKama/fast_refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
IMB11 authored May 25, 2024
2 parents 08618a2 + bcdcbeb commit d802d40
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,26 @@
import com.mineblock11.skinshuffle.client.preset.SkinPreset;
import com.mineblock11.skinshuffle.networking.ClientSkinHandling;
import com.mineblock11.skinshuffle.util.NetworkingUtil;
import com.mineblock11.skinshuffle.util.SkinShuffleClientPlayer;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.client.util.SkinTextures;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.Objects;

@Mixin(AbstractClientPlayerEntity.class)
public abstract class PlayerEntityMixin extends PlayerEntity {
public abstract class PlayerEntityMixin extends PlayerEntity implements SkinShuffleClientPlayer {
@Shadow @Nullable private PlayerListEntry playerListEntry;

protected PlayerEntityMixin(World world, BlockPos pos, float yaw, GameProfile gameProfile) {
super(world, pos, yaw, gameProfile);
}
Expand All @@ -65,4 +68,9 @@ private void modifySkinModel(CallbackInfoReturnable<SkinTextures> cir) {
}
}
}

@Override
public void skinShuffle$refreshPlayerListEntry() {
playerListEntry = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@

package com.mineblock11.skinshuffle.mixin;

import com.mineblock11.skinshuffle.networking.ServerSkinHandling;
import com.mineblock11.skinshuffle.util.SkinShufflePlayer;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Pair;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ServerPlayNetworkHandler;
Expand Down Expand Up @@ -87,59 +89,67 @@ protected ServerPlayerEntityMixin(World world, BlockPos pos, float yaw, GameProf
ThreadedAnvilChunkStorage storage = manager.threadedAnvilChunkStorage;
ThreadedAnvilChunkStorage.EntityTracker trackerEntry = storage.entityTrackers.get(this.getId());

PacketByteBuf refreshPlayerListEntryPacket = ServerSkinHandling.createEntityIdPacket(getId());

// Refreshing skin in world for all that see the player
trackerEntry.listeners.forEach(tracking -> trackerEntry.entry.startTracking(tracking.getPlayer()));

// need to change the player entity on the client
ServerWorld level = this.getServerWorld();
this.networkHandler.sendPacket(new PlayerRespawnS2CPacket(
new CommonPlayerSpawnInfo(
level.getDimensionKey(),
level.getRegistryKey(),
BiomeAccess.hashSeed(level.getSeed()),
this.interactionManager.getGameMode(),
this.interactionManager.getPreviousGameMode(),
level.isDebugWorld(),
level.isFlat(),
this.getLastDeathPos(),
this.getPortalCooldown()), (byte) 3
));

this.networkHandler.sendPacket(new PlayerPositionLookS2CPacket(this.getX(), this.getY(), this.getZ(), this.getYaw(), this.getPitch(), Collections.emptySet(), 0));
this.networkHandler.sendPacket(new UpdateSelectedSlotS2CPacket(this.getInventory().selectedSlot));

this.networkHandler.sendPacket(new DifficultyS2CPacket(level.getDifficulty(), level.getLevelProperties().isDifficultyLocked()));
this.networkHandler.sendPacket(new ExperienceBarUpdateS2CPacket(this.experienceProgress, this.totalExperience, this.experienceLevel));
playerManager.sendWorldInfo((ServerPlayerEntity)(Object) this, level);
playerManager.sendCommandTree((ServerPlayerEntity)(Object) this);

this.networkHandler.sendPacket(new HealthUpdateS2CPacket(this.getHealth(), this.getHungerManager().getFoodLevel(), this.getHungerManager().getSaturationLevel()));

for (StatusEffectInstance statusEffect : this.getStatusEffects()) {
this.networkHandler.sendPacket(new EntityStatusEffectS2CPacket(this.getId(), statusEffect));
}
trackerEntry.listeners.forEach(tracking -> {
if (!ServerSkinHandling.trySendRefreshPlayerListEntry(tracking.getPlayer(), refreshPlayerListEntryPacket)) {
trackerEntry.entry.startTracking(tracking.getPlayer());
}
});

if (!ServerSkinHandling.trySendRefreshPlayerListEntry((ServerPlayerEntity) (Object) this, refreshPlayerListEntryPacket)) {
// If we could not send refresh packet, we change the player entity on the client
ServerWorld level = this.getServerWorld();
this.networkHandler.sendPacket(new PlayerRespawnS2CPacket(
new CommonPlayerSpawnInfo(
level.getDimensionKey(),
level.getRegistryKey(),
BiomeAccess.hashSeed(level.getSeed()),
this.interactionManager.getGameMode(),
this.interactionManager.getPreviousGameMode(),
level.isDebugWorld(),
level.isFlat(),
this.getLastDeathPos(),
this.getPortalCooldown()), (byte) 3
));

this.networkHandler.sendPacket(new PlayerPositionLookS2CPacket(this.getX(), this.getY(), this.getZ(), this.getYaw(), this.getPitch(), Collections.emptySet(), 0));
this.networkHandler.sendPacket(new UpdateSelectedSlotS2CPacket(this.getInventory().selectedSlot));

this.networkHandler.sendPacket(new DifficultyS2CPacket(level.getDifficulty(), level.getLevelProperties().isDifficultyLocked()));
this.networkHandler.sendPacket(new ExperienceBarUpdateS2CPacket(this.experienceProgress, this.totalExperience, this.experienceLevel));
playerManager.sendWorldInfo((ServerPlayerEntity) (Object) this, level);
playerManager.sendCommandTree((ServerPlayerEntity) (Object) this);

this.networkHandler.sendPacket(new HealthUpdateS2CPacket(this.getHealth(), this.getHungerManager().getFoodLevel(), this.getHungerManager().getSaturationLevel()));

for (StatusEffectInstance statusEffect : this.getStatusEffects()) {
this.networkHandler.sendPacket(new EntityStatusEffectS2CPacket(this.getId(), statusEffect));
}

var equipmentList = new ArrayList<Pair<EquipmentSlot, ItemStack>>();
for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
ItemStack itemStack = this.getEquippedStack(equipmentSlot);
if (!itemStack.isEmpty()) {
equipmentList.add(new Pair<>(equipmentSlot, itemStack.copy()));
var equipmentList = new ArrayList<Pair<EquipmentSlot, ItemStack>>();
for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) {
ItemStack itemStack = this.getEquippedStack(equipmentSlot);
if (!itemStack.isEmpty()) {
equipmentList.add(new Pair<>(equipmentSlot, itemStack.copy()));
}
}
}

if (!equipmentList.isEmpty()) {
this.networkHandler.sendPacket(new EntityEquipmentUpdateS2CPacket(this.getId(), equipmentList));
}
if (!equipmentList.isEmpty()) {
this.networkHandler.sendPacket(new EntityEquipmentUpdateS2CPacket(this.getId(), equipmentList));
}


if (!this.getPassengerList().isEmpty()) {
this.networkHandler.sendPacket(new EntityPassengersSetS2CPacket(this));
}
if (this.hasVehicle()) {
this.networkHandler.sendPacket(new EntityPassengersSetS2CPacket(this.getVehicle()));
}
if (!this.getPassengerList().isEmpty()) {
this.networkHandler.sendPacket(new EntityPassengersSetS2CPacket(this));
}
if (this.hasVehicle()) {
this.networkHandler.sendPacket(new EntityPassengersSetS2CPacket(this.getVehicle()));
}

this.sendAbilitiesUpdate();
playerManager.sendPlayerStatus((ServerPlayerEntity)(Object) this);
this.sendAbilitiesUpdate();
playerManager.sendPlayerStatus((ServerPlayerEntity) (Object) this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
import com.mineblock11.skinshuffle.SkinShuffle;
import com.mineblock11.skinshuffle.api.SkinQueryResult;
import com.mineblock11.skinshuffle.client.config.SkinPresetManager;
import com.mineblock11.skinshuffle.util.SkinShuffleClientPlayer;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.network.PacketByteBuf;

public class ClientSkinHandling {
Expand Down Expand Up @@ -71,5 +75,18 @@ public static void init() {
ClientPlayNetworking.registerGlobalReceiver(SkinShuffle.id("handshake"), (client1, handler1, buf, responseSender) -> {
handshakeTakenPlace = true;
});

ClientPlayNetworking.registerGlobalReceiver(SkinShuffle.id("refresh_player_list_entry"), (client, handler, buf, responseSender) -> {
int id = buf.readVarInt();
client.execute(() -> {
ClientWorld world = client.world;
if (world != null) {
Entity entity = world.getEntityById(id);
if (entity instanceof AbstractClientPlayerEntity player) {
((SkinShuffleClientPlayer) player).skinShuffle$refreshPlayerListEntry();
}
}
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class ServerSkinHandling {
private static final Identifier REFRESH_PLAYER_LIST_ENTRY_ID = SkinShuffle.id("refresh_player_list_entry");

private static void handleSkinRefresh(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) {
Property skinData = buf.readProperty();
SkinShuffle.LOGGER.info("Recieved skin refresh packet from: " + player.getName().getString());
Expand All @@ -55,6 +58,18 @@ private static void handleSkinRefresh(MinecraftServer server, ServerPlayerEntity
});
}

public static PacketByteBuf createEntityIdPacket(int entityId) {
return PacketByteBufs.create().writeVarInt(entityId);
}

public static boolean trySendRefreshPlayerListEntry(ServerPlayerEntity player, PacketByteBuf buf) {
if (ServerPlayNetworking.canSend(player, REFRESH_PLAYER_LIST_ENTRY_ID)) {
ServerPlayNetworking.send(player, REFRESH_PLAYER_LIST_ENTRY_ID, buf);
return true;
}
return false;
}

public static void init() {
// Send handshake packet to client.
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
*
* Copyright (C) 2023 Calum (mineblock11), enjarai
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/

package com.mineblock11.skinshuffle.util;

public interface SkinShuffleClientPlayer {
void skinShuffle$refreshPlayerListEntry();
}

0 comments on commit d802d40

Please sign in to comment.