diff --git a/src/AppPlatform_glfw.h b/src/AppPlatform_glfw.h index 4c7eb72..79ed895 100755 --- a/src/AppPlatform_glfw.h +++ b/src/AppPlatform_glfw.h @@ -73,50 +73,20 @@ public: : filename_; std::ifstream source(filename.c_str(), std::ios::binary); - if (source) { - png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - - if (!pngPtr) - return out; - - png_infop infoPtr = png_create_info_struct(pngPtr); - - if (!infoPtr) { - png_destroy_read_struct(&pngPtr, NULL, NULL); - return out; - } - - // Hack to get around the broken libpng for windows - png_set_read_fn(pngPtr,(void*)&source, png_funcReadFile); - - png_read_info(pngPtr, infoPtr); - - // Set up the texdata properties - out.w = png_get_image_width(pngPtr, infoPtr); - out.h = png_get_image_height(pngPtr, infoPtr); - - png_bytep* rowPtrs = new png_bytep[out.h]; - out.data = new unsigned char[4 * out.w * out.h]; - out.memoryHandledExternally = false; - - int rowStrideBytes = 4 * out.w; - for (int i = 0; i < out.h; i++) { - rowPtrs[i] = (png_bytep)&out.data[i*rowStrideBytes]; - } - png_read_image(pngPtr, rowPtrs); - - // Teardown and return - png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); - delete[] (png_bytep)rowPtrs; - source.close(); - - return out; - } - else - { + if (!source) { LOGI("Couldn't find file: %s\n", filename.c_str()); return out; } + + std::vector fileData((std::istreambuf_iterator(source)), std::istreambuf_iterator()); + source.close(); + + if (fileData.empty()) { + LOGI("Couldn't read file: %s\n", filename.c_str()); + return out; + } + + return loadTextureFromMemory(fileData.data(), fileData.size()); } TextureData loadTextureFromMemory(const unsigned char* data, size_t size) override { diff --git a/src/client/player/LocalPlayer.cpp b/src/client/player/LocalPlayer.cpp index ef8ff7f..b4d57ef 100755 --- a/src/client/player/LocalPlayer.cpp +++ b/src/client/player/LocalPlayer.cpp @@ -263,7 +263,8 @@ static void* fetchSkinForPlayer(void* param) { std::vector skinData; if (!HttpClient::download(skinUrl, skinData) || skinData.empty()) { LOGW("[Skin] download failed for %s\n", skinUrl.c_str()); - return NULL; + player->setTextureName("mob/char.png"); + return NULL; } // Save to cache diff --git a/src/client/renderer/entity/HumanoidMobRenderer.h b/src/client/renderer/entity/HumanoidMobRenderer.h index e10c27c..a78ade8 100755 --- a/src/client/renderer/entity/HumanoidMobRenderer.h +++ b/src/client/renderer/entity/HumanoidMobRenderer.h @@ -19,12 +19,13 @@ public: protected: void additionalRendering(Mob* mob, float a); -private: HumanoidModel* humanoidModel; // Last rotation values for cape smoothing (reduces jitter) float lastCapeXRot; float lastCapeZRot; +private: + // i guess ill keep this just in case seomthing breaks }; #endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__*/ diff --git a/src/client/renderer/entity/MobRenderer.h b/src/client/renderer/entity/MobRenderer.h index 3f22618..fee7786 100755 --- a/src/client/renderer/entity/MobRenderer.h +++ b/src/client/renderer/entity/MobRenderer.h @@ -43,8 +43,8 @@ public: protected: void setArmor(Model* armor); Model* getArmor(); + Model* model; // allows derived renderers to swap models dynamically for skin formats private: - Model* model; Model* armor; }; diff --git a/src/client/renderer/entity/PlayerRenderer.cpp b/src/client/renderer/entity/PlayerRenderer.cpp index b184bcb..6a773f0 100755 --- a/src/client/renderer/entity/PlayerRenderer.cpp +++ b/src/client/renderer/entity/PlayerRenderer.cpp @@ -1,5 +1,6 @@ #include "PlayerRenderer.h" #include "EntityRenderDispatcher.h" +#include "../Textures.h" #include "../../../world/entity/player/Player.h" #include "../../../world/level/Level.h" #include "../../../world/item/ArmorItem.h" @@ -14,12 +15,22 @@ static const std::string armorFilenames[10] = { PlayerRenderer::PlayerRenderer( HumanoidModel* humanoidModel, float shadow ) : super(humanoidModel, shadow), + playerModel64(humanoidModel), + playerModel32(new HumanoidModel(0, 0, 64, 32)), armorParts1(new HumanoidModel(1.0f, 0, 64, 64)), armorParts2(new HumanoidModel(0.5f, 0, 64, 64)) { + // default to legacy skin path until we know the exact texture size + model = playerModel32; + humanoidModel = playerModel32; } PlayerRenderer::~PlayerRenderer() { + // prevent MobRenderer destructor from deleting model pointers we manage manually + model = nullptr; + + delete playerModel32; + delete playerModel64; delete armorParts1; delete armorParts2; } @@ -43,6 +54,15 @@ void PlayerRenderer::setupRotations( Entity* mob, float bob, float bodyRot, floa super::setupRotations(mob, bob, bodyRot, a); } +bool PlayerRenderer::isModernPlayerSkin(Mob* mob) { + const std::string texName = mob->getTexture(); + TextureId texId = entityRenderDispatcher->textures->loadTexture(texName); + if (!Textures::isTextureIdValid(texId)) + return false; + const TextureData* texData = entityRenderDispatcher->textures->getTemporaryTextureData(texId); + return texData && texData->w == 64 && texData->h == 64; +} + void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){ //@todo: figure out how to handle HideGUI if (mob != entityRenderDispatcher->cameraEntity && mob->level->adventureSettings.showNameTags) { @@ -50,6 +70,20 @@ void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){ } } +void PlayerRenderer::render(Entity* mob_, float x, float y, float z, float rot, float a) { + Mob* mob = (Mob*) mob_; + HumanoidModel* desired = isModernPlayerSkin(mob) ? playerModel64 : playerModel32; + if (model != desired || humanoidModel != desired) { + model = desired; + humanoidModel = desired; + } + // LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n", + // ((Player*)mob)->name.c_str(), mob->getTexture().c_str(), + // humanoidModel->texWidth, humanoidModel->texHeight, + // (desired == playerModel64 ? "64" : "32")); + HumanoidMobRenderer::render(mob_, x, y, z, rot, a); +} + int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) { Player* player = (Player*) mob; @@ -80,8 +114,11 @@ int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) { } void PlayerRenderer::onGraphicsReset() { - super::onGraphicsReset(); + if (playerModel32) playerModel32->onGraphicsReset(); + if (playerModel64) playerModel64->onGraphicsReset(); if (armorParts1) armorParts1->onGraphicsReset(); if (armorParts2) armorParts2->onGraphicsReset(); + + super::onGraphicsReset(); } diff --git a/src/client/renderer/entity/PlayerRenderer.h b/src/client/renderer/entity/PlayerRenderer.h index f370607..d4b25e2 100755 --- a/src/client/renderer/entity/PlayerRenderer.h +++ b/src/client/renderer/entity/PlayerRenderer.h @@ -11,6 +11,8 @@ public: ~PlayerRenderer(); virtual int prepareArmor(Mob* mob, int layer, float a); + bool isModernPlayerSkin(Mob* mob); + virtual void render(Entity* mob, float x, float y, float z, float rot, float a); virtual void setupPosition(Entity* mob, float x, float y, float z); virtual void setupRotations(Entity* mob, float bob, float bodyRot, float a); @@ -18,6 +20,8 @@ public: virtual void renderName(Mob* mob, float x, float y, float z); virtual void onGraphicsReset(); private: + HumanoidModel* playerModel32; + HumanoidModel* playerModel64; HumanoidModel* armorParts1; HumanoidModel* armorParts2; };