async head texture lookup
This commit is contained in:
parent
de7f78110b
commit
ad1da3ce18
@ -0,0 +1,96 @@
|
|||||||
|
package io.izzel.arclight.mixin.core.tileentity;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mysql.jdbc.StringUtils;
|
||||||
|
import io.izzel.arclight.bridge.server.MinecraftServerBridge;
|
||||||
|
import io.izzel.arclight.mod.util.ArclightHeadLoader;
|
||||||
|
import net.minecraft.tileentity.SkullTileEntity;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Mixin(SkullTileEntity.class)
|
||||||
|
public abstract class SkullTileEntityMixin extends TileEntityMixin {
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
@Shadow public GameProfile playerProfile;
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
private static ExecutorService executor = Executors.newFixedThreadPool(3,
|
||||||
|
new ThreadFactoryBuilder()
|
||||||
|
.setNameFormat("Head Conversion Thread - %1$d")
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
private static LoadingCache<String, GameProfile> skinCache = CacheBuilder.newBuilder().maximumSize(5000L).expireAfterAccess(60L, TimeUnit.MINUTES).build(new ArclightHeadLoader());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author IzzelAliz
|
||||||
|
* @reason
|
||||||
|
*/
|
||||||
|
@Overwrite
|
||||||
|
private void updatePlayerProfile() {
|
||||||
|
GameProfile profile = this.playerProfile;
|
||||||
|
b(profile, input -> {
|
||||||
|
playerProfile = input;
|
||||||
|
markDirty();
|
||||||
|
return false;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"UnusedReturnValue", "ConstantConditions"})
|
||||||
|
private static Future<GameProfile> b(GameProfile gameprofile, Predicate<GameProfile> callback, boolean sync) {
|
||||||
|
if (gameprofile != null && !StringUtils.isNullOrEmpty(gameprofile.getName())) {
|
||||||
|
if (gameprofile.isComplete() && gameprofile.getProperties().containsKey("textures")) {
|
||||||
|
callback.apply(gameprofile);
|
||||||
|
} else if (Bukkit.getServer() == null || ((CraftServer) Bukkit.getServer()).getServer() == null) {
|
||||||
|
callback.apply(gameprofile);
|
||||||
|
} else {
|
||||||
|
GameProfile profile = skinCache.getIfPresent(gameprofile.getName().toLowerCase(Locale.ROOT));
|
||||||
|
if (profile != null && Iterables.getFirst((profile.getProperties()).get("textures"), null) != null) {
|
||||||
|
callback.apply(profile);
|
||||||
|
return Futures.immediateFuture(profile);
|
||||||
|
}
|
||||||
|
Callable<GameProfile> callable = () -> {
|
||||||
|
GameProfile profile1 = skinCache.getUnchecked(gameprofile.getName().toLowerCase(Locale.ROOT));
|
||||||
|
((MinecraftServerBridge) ((CraftServer) Bukkit.getServer()).getServer()).bridge$queuedProcess(() -> {
|
||||||
|
if (profile1 == null) {
|
||||||
|
callback.apply(gameprofile);
|
||||||
|
} else {
|
||||||
|
callback.apply(profile1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return profile1;
|
||||||
|
};
|
||||||
|
if (sync) {
|
||||||
|
try {
|
||||||
|
return Futures.immediateFuture(callable.call());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Throwables.throwIfUnchecked(ex);
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return executor.submit(callable);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback.apply(gameprofile);
|
||||||
|
}
|
||||||
|
return Futures.immediateFuture(gameprofile);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,6 +29,7 @@ public abstract class TileEntityMixin implements TileEntityBridge {
|
|||||||
@Shadow @Nullable protected World world;
|
@Shadow @Nullable protected World world;
|
||||||
@Shadow protected BlockPos pos;
|
@Shadow protected BlockPos pos;
|
||||||
@Shadow public abstract BlockState getBlockState();
|
@Shadow public abstract BlockState getBlockState();
|
||||||
|
@Shadow public abstract void markDirty();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
@Inject(method = "read", at = @At("RETURN"))
|
@Inject(method = "read", at = @At("RETURN"))
|
||||||
|
|||||||
@ -82,6 +82,16 @@ public class ArclightMixinPlugin implements IMixinConfigPlugin {
|
|||||||
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;II)Lnet/minecraft/util/math/AxisAlignedBB;", null, null)
|
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "calculateBoundingBox", "(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;II)Lnet/minecraft/util/math/AxisAlignedBB;", null, null)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
.put("net.minecraft.tileentity.SkullTileEntity",
|
||||||
|
Maps.immutableEntry(
|
||||||
|
ImmutableList.of(
|
||||||
|
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "executor", "Ljava/util/concurrent/ExecutorService;", null, null),
|
||||||
|
new FieldNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "skinCache", "Lcom/google/common/cache/LoadingCache;", null, null)
|
||||||
|
),
|
||||||
|
ImmutableList.of(
|
||||||
|
new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "b", "(Lcom/mojang/authlib/GameProfile;Lcom/google/common/base/Predicate;Z)Ljava/util/concurrent/Future;", null, null)
|
||||||
|
)
|
||||||
|
))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final Set<String> modifyConstructor = ImmutableSet.<String>builder()
|
private final Set<String> modifyConstructor = ImmutableSet.<String>builder()
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
package io.izzel.arclight.mod.util;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.mojang.authlib.Agent;
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mojang.authlib.ProfileLookupCallback;
|
||||||
|
import com.mojang.authlib.properties.Property;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.tileentity.SkullTileEntity;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ArclightHeadLoader extends CacheLoader<String, GameProfile> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameProfile load(String key) {
|
||||||
|
GameProfile[] profiles = {null};
|
||||||
|
ProfileLookupCallback gameProfileLookup = new ProfileLookupCallback() {
|
||||||
|
@Override
|
||||||
|
public void onProfileLookupSucceeded(GameProfile gp) {
|
||||||
|
profiles[0] = gp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProfileLookupFailed(GameProfile gp, Exception excptn) {
|
||||||
|
profiles[0] = gp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
((CraftServer) Bukkit.getServer()).getServer().getGameProfileRepository().findProfilesByNames(new String[]{key}, Agent.MINECRAFT, gameProfileLookup);
|
||||||
|
GameProfile profile = profiles[0];
|
||||||
|
if (profile == null) {
|
||||||
|
UUID uuid = PlayerEntity.getUUID(new GameProfile(null, key));
|
||||||
|
profile = new GameProfile(uuid, key);
|
||||||
|
gameProfileLookup.onProfileLookupSucceeded(profile);
|
||||||
|
} else {
|
||||||
|
Property property = Iterables.getFirst((profile.getProperties()).get("textures"), null);
|
||||||
|
if (property == null) {
|
||||||
|
profile = SkullTileEntity.sessionService.fillProfileProperties(profile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@ public net.minecraft.util.math.shapes.IDoubleListMerger
|
|||||||
public net.minecraft.util.math.shapes.IndirectMerger <init>(Lit/unimi/dsi/fastutil/doubles/DoubleList;Lit/unimi/dsi/fastutil/doubles/DoubleList;ZZ)V
|
public net.minecraft.util.math.shapes.IndirectMerger <init>(Lit/unimi/dsi/fastutil/doubles/DoubleList;Lit/unimi/dsi/fastutil/doubles/DoubleList;ZZ)V
|
||||||
public net.minecraft.util.math.shapes.DoubleCubeMergingList <init>(II)V
|
public net.minecraft.util.math.shapes.DoubleCubeMergingList <init>(II)V
|
||||||
public net.minecraft.block.ComposterBlock$EmptyInventory
|
public net.minecraft.block.ComposterBlock$EmptyInventory
|
||||||
|
public net.minecraft.tileentity.SkullTileEntity field_184299_k #sessionService
|
||||||
# Bukkit
|
# Bukkit
|
||||||
public net.minecraft.entity.player.PlayerEntity func_190531_bD()I
|
public net.minecraft.entity.player.PlayerEntity func_190531_bD()I
|
||||||
public net.minecraft.entity.item.ItemFrameEntity func_174859_a(Lnet/minecraft/util/Direction;)V
|
public net.minecraft.entity.item.ItemFrameEntity func_174859_a(Lnet/minecraft/util/Direction;)V
|
||||||
|
|||||||
@ -339,6 +339,7 @@
|
|||||||
"tileentity.LockableTileEntityMixin",
|
"tileentity.LockableTileEntityMixin",
|
||||||
"tileentity.ShulkerBoxTileEntityMixin",
|
"tileentity.ShulkerBoxTileEntityMixin",
|
||||||
"tileentity.SignTileEntityMixin",
|
"tileentity.SignTileEntityMixin",
|
||||||
|
"tileentity.SkullTileEntityMixin",
|
||||||
"tileentity.TileEntityMixin",
|
"tileentity.TileEntityMixin",
|
||||||
"util.BootstrapMixin",
|
"util.BootstrapMixin",
|
||||||
"util.DamageSourceMixin",
|
"util.DamageSourceMixin",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user