- Версия(и) Minecraft
- да все, наверное
В
Делаем публичным и нефинальным поле
Можно и без трансформера, если в вашей версии майна ещё есть
И потом втупую делаем прокси вокруг ванильного sessionManager-а, где по условию добавляем ссылку на свой плащ в ретурн метода
Как видите, я люблю оформлять эдакие независимые мини-модули при помощи
Ещё момент в том что мы сеттим ссылку вместо текстуры в ассетах - ну тут я просто не разбирался ибо мне и так норм, но наверное можно найти как использовать текстуру, аналогичным способом можно сеттить прокси на всякие другие штуки тоже.
accesstransformer.cfg
надо добавить такую строчку (это не туториал по accesstransformer-ам, так что гуглите)
accesstransformer.cfg:
public-f net.minecraft.client.resources.SkinManager f_118809_ # sessionService
SkinManager.sessionService
, в зависимости от версии может быть другое имя класса/поля, но идею вы поняли.Можно и без трансформера, если в вашей версии майна ещё есть
ReflectionUtils
(или как оно там называлось), и можно сеттить приватные финальные поля без негоИ потом втупую делаем прокси вокруг ванильного sessionManager-а, где по условию добавляем ссылку на свой плащ в ретурн метода
getTextures
Cape.java:
@EventBusSubscriber(value = Dist.CLIENT, modid = MODID, bus = Bus.MOD)
@OnlyIn(Dist.CLIENT)
public final class Cape {
private static final List<UUID> CAPED = Collections.singletonList(NECAUQUA);
@SubscribeEvent
public static void on(FMLClientSetupEvent e) {
var skinManager = Minecraft.getInstance().getSkinManager();
var original = skinManager.sessionService;
skinManager.sessionService = new MinecraftSessionService() {
@Override
public Map<Type, MinecraftProfileTexture> getTextures(GameProfile profile, boolean requireSecure) {
var textures = original.getTextures(profile, requireSecure);
if (CAPED.contains(profile.getId())) {
textures.put(Type.CAPE, new MinecraftProfileTexture("https://necauqua.dev/images/cape.png", emptyMap()));
}
return textures;
}
// в котлине было бы красиво с делегатой :|
@Override
public void joinServer(GameProfile profile, String authenticationToken, String serverId) throws AuthenticationException {
original.joinServer(profile, authenticationToken, serverId);
}
@Override
public GameProfile hasJoinedServer(GameProfile user, String serverId, InetAddress address) throws AuthenticationUnavailableException {
return original.hasJoinedServer(user, serverId, address);
}
@Override
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
return original.fillProfileProperties(profile, requireSecure);
}
};
}
}
Как видите, я люблю оформлять эдакие независимые мини-модули при помощи
@EventBusSubscriber
(даже до него я что-то своё писал, чтобы были аннотации типа @Init
@PreInit
на рандомных методах по всему моду), но смысл просто в том чтобы когда-нибудь рано (те же иниты/преиниты) сделать обёртку этому сешион-менеджеру - и кстати если несколько модов так сделают то всё будет отлично работать (если они одному и тому-же игроку засетят плащ/скин/etc то просто последний победит).Ещё момент в том что мы сеттим ссылку вместо текстуры в ассетах - ну тут я просто не разбирался ибо мне и так норм, но наверное можно найти как использовать текстуру, аналогичным способом можно сеттить прокси на всякие другие штуки тоже.