Fixed camera height not updating immediately when loading a world

This commit is contained in:
Sollace 2024-07-22 00:25:24 +02:00
parent 90a5ac34fd
commit cc6cc074e8
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
8 changed files with 70 additions and 57 deletions

View file

@ -27,7 +27,7 @@ public record Flags<T extends Enum<T> & TValue<T>> (
for (int i = 0; i < length; i++) {
values.add(all[buffer.readInt()]);
}
return new Flags<>(def, values, buffer.readInt());
return of(def, buffer.readInt(), values);
}
public void write(PacketByteBuf buffer) {

View file

@ -15,8 +15,8 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
class PonyDataLoader {
static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
public class PonyDataLoader {
public static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
private static final ResourceMetadataReader<PonyData> SERIALIZER = new ResourceMetadataReader<PonyData>() {
private static final Gson GSON = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()

View file

@ -15,12 +15,12 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.util.DefaultSkinHelper;
import net.minecraft.resource.ResourceManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -29,22 +29,21 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
private final PonyConfig config;
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
private final LoadingCache<Key, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, true))));
.build(CacheLoader.from(key -> new Pony(key.texture(), PonyDataLoader.parse(key.texture(), key.defaulted()))));
private final WeakHashMap<UUID, Pony> playerPonies = new WeakHashMap<>();
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(resource -> new Pony(resource, PonyDataLoader.parse(resource, false))));
record Key(Identifier texture, @Nullable UUID uuid, boolean defaulted) {}
public PonyManagerImpl(PonyConfig config) {
this.config = config;
Instance.instance = this;
}
private Pony loadPony(Identifier resource, boolean defaulted) {
private Pony loadPony(Identifier resource, @Nullable UUID uuid, boolean defaulted) {
try {
return (defaulted ? defaultedPoniesCache : poniesCache).get(resource);
return poniesCache.get(new Key(resource, uuid, defaulted));
} catch (ExecutionException e) {
return new Pony(resource, PonyDataLoader.NULL);
}
@ -52,13 +51,26 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
@Override
public Pony getPony(PlayerEntity player) {
final UUID id = player instanceof ForcedPony ? null : player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId();
final UUID id = player instanceof ForcedPony ? null : player.getGameProfile() == null || player.getGameProfile().getId() == null ? player.getUuid() : player.getGameProfile().getId();
Pony pony;
if (player instanceof ServerPlayerEntity && id != null) {
pony = playerPonies.get(id);
if (pony != null) {
return pony;
}
}
@Nullable
Identifier skin = getSkin(player);
if (skin != null) {
skin = MoreObjects.firstNonNull(PonySkinResolver.EVENT.invoker().onPonySkinResolving(player, s -> getPony(s, id), skin), skin);
}
return getPony(skin, id);
pony = getPony(skin, id);
if (!(player instanceof ServerPlayerEntity) && id != null) {
playerPonies.put(id, pony);
}
return pony;
}
@Override
@ -77,10 +89,10 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
@Override
public Pony getPony(@Nullable Identifier resource, @Nullable UUID uuid) {
if (resource == null) {
return uuid == null ? loadPony(DefaultSkinHelper.getTexture(), true) : getBackgroundPony(uuid);
return uuid == null ? loadPony(DefaultSkinHelper.getTexture(), uuid, true) : getBackgroundPony(uuid);
}
Pony pony = loadPony(resource, false);
Pony pony = loadPony(resource, uuid, false);
if (uuid != null && PonyConfig.getInstance().ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
return getBackgroundPony(uuid);
@ -91,9 +103,9 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
@Override
public Pony getBackgroundPony(@Nullable UUID uuid) {
if (config.ponyLevel.get() == PonyLevel.PONIES) {
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getSkinTextures(uuid).texture()), true);
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getSkinTextures(uuid).texture()), uuid, true);
}
return loadPony(DefaultSkinHelper.getSkinTextures(uuid).texture(), true);
return loadPony(DefaultSkinHelper.getSkinTextures(uuid).texture(), uuid, true);
}
@Nullable
@ -113,13 +125,11 @@ public class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceRe
public void removePony(Identifier resource) {
poniesCache.invalidate(resource);
defaultedPoniesCache.invalidate(resource);
}
public void clearCache() {
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
MineLittlePony.logger.info("Turned {} cached ponies into cupcakes.", poniesCache.size());
poniesCache.invalidateAll();
defaultedPoniesCache.invalidateAll();
}
@Override

View file

@ -1,19 +0,0 @@
package com.minelittlepony.client.mixin;
import com.minelittlepony.client.render.EquineRenderManager;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(ClientPlayerEntity.class)
abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implements EquineRenderManager.RegistrationHandler {
public MixinClientPlayerEntity() { super(null, null); }
private final EquineRenderManager.SyncedPony syncedPony = new EquineRenderManager.SyncedPony();
@Override
public EquineRenderManager.SyncedPony getSyncedPony() {
return syncedPony;
}
}

View file

@ -6,22 +6,35 @@ import net.minecraft.entity.player.PlayerEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.render.EquineRenderManager.RegistrationHandler;
import com.minelittlepony.client.render.EquineRenderManager.SyncedPony;
@Mixin(PlayerEntity.class)
abstract class MixinPlayerEntity {
abstract class MixinPlayerEntity extends LivingEntity implements RegistrationHandler {
MixinPlayerEntity() { super(null, null); }
private final SyncedPony syncedPony = new SyncedPony();
@Override
public SyncedPony getSyncedPony() {
return syncedPony;
}
@Inject(method = "getBaseDimensions", at = @At("RETURN"), cancellable = true)
private void onGetBaseDimensions(EntityPose pose, CallbackInfoReturnable<EntityDimensions> info) {
Pony pony = Pony.getManager().getPony((PlayerEntity)(Object)this);
float factor = syncedPony.getCachedPonyData().size().eyeHeightFactor();
if (!pony.race().isHuman()) {
float factor = pony.size().eyeHeightFactor();
if (factor != 1) {
EntityDimensions dimensions = info.getReturnValue();
info.setReturnValue(dimensions.withEyeHeight(dimensions.eyeHeight() * factor));
}
}
@Inject(method = "tick()V", at = @At("TAIL"))
private void onTick(CallbackInfo info) {
syncedPony.synchronize((PlayerEntity)(Object)this);
}
}

View file

@ -5,13 +5,16 @@ import com.minelittlepony.api.events.Channel;
import com.minelittlepony.api.events.PonyDataCallback;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.client.PonyDataLoader;
import com.minelittlepony.client.transform.PonyPosture;
import com.minelittlepony.mson.api.ModelKey;
import com.minelittlepony.util.MathUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import net.fabricmc.api.EnvType;
import net.minecraft.client.MinecraftClient;
@ -78,10 +81,6 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
}
models.applyMetadata(pony.metadata());
models.body().updateLivingState(entity, pony, mode);
if (entity instanceof PlayerEntity player && entity instanceof RegistrationHandler handler) {
handler.getSyncedPony().synchronize(player, pony);
}
}
public void setupTransforms(T entity, MatrixStack stack, float animationProgress, float bodyYaw, float tickDelta, float scale) {
@ -152,14 +151,25 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
public static class SyncedPony {
@Nullable
private Pony lastRenderedPony;
private Supplier<Optional<PonyData>> lastPonyData = PonyDataLoader.NULL;
@Nullable
private Pony lastTransmittedPony;
public void synchronize(PlayerEntity player, Pony pony) {
public Pony getCachedPony() {
return lastRenderedPony;
}
public PonyData getCachedPonyData() {
return lastPonyData.get().orElse(PonyData.NULL);
}
public void synchronize(PlayerEntity player) {
Pony pony = Pony.getManager().getPony(player);
boolean changed = pony.compareTo(lastRenderedPony) != 0;
if (changed) {
lastRenderedPony = pony;
lastPonyData = pony.metadataGetter();
player.calculateDimensions();
}

View file

@ -15,7 +15,7 @@ import net.minecraft.entity.EntityType;
/**
* Central location where new entity renderers are registered and applied.
*/
public final class MobRenderers {
public class MobRenderers {
public static final Map<String, MobRenderers> REGISTRY = new HashMap<>();
public static final MobRenderers VILLAGER = register("villagers", (state, pony) -> {

View file

@ -11,7 +11,6 @@
"MixinEntityRenderers",
"MixinSkullBlockEntityRenderer",
"MixinHeldItemRenderer",
"MixinClientPlayerEntity",
"MixinPlayerEntity",
"MixinPlayerMoveC2SPacket",
"MixinPlayerPositionLookS2CPacket",