From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- Minecraft.Client/TextureMap.cpp | 248 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 Minecraft.Client/TextureMap.cpp (limited to 'Minecraft.Client/TextureMap.cpp') diff --git a/Minecraft.Client/TextureMap.cpp b/Minecraft.Client/TextureMap.cpp new file mode 100644 index 00000000..836a853e --- /dev/null +++ b/Minecraft.Client/TextureMap.cpp @@ -0,0 +1,248 @@ +#include "stdafx.h" +#include "..\Minecraft.World\net.minecraft.world.h" +#include "..\Minecraft.World\net.minecraft.world.level.tile.h" +#include "..\Minecraft.World\net.minecraft.world.item.h" +#include "Minecraft.h" +#include "LevelRenderer.h" +#include "EntityRenderDispatcher.h" +#include "Stitcher.h" +#include "StitchSlot.h" +#include "StitchedTexture.h" +#include "Texture.h" +#include "TextureHolder.h" +#include "TextureManager.h" +#include "TexturePack.h" +#include "TexturePackRepository.h" +#include "TextureMap.h" + +const wstring TextureMap::NAME_MISSING_TEXTURE = L"missingno"; + +TextureMap::TextureMap(int type, const wstring &name, const wstring &path, BufferedImage *missingTexture, bool mipmap) : iconType(type), name(name), path(path), extension(L".png") +{ + this->missingTexture = missingTexture; + + // 4J Initialisers + missingPosition = NULL; + stitchResult = NULL; + + m_mipMap = mipmap; +} + +void TextureMap::stitch() +{ + texturesToRegister.clear(); + + if (iconType == Icon::TYPE_TERRAIN) + { + //for (Tile tile : Tile.tiles) + for(unsigned int i = 0; i < Tile::TILE_NUM_COUNT; ++i) + { + if (Tile::tiles[i] != NULL) + { + Tile::tiles[i]->registerIcons(this); + } + } + + Minecraft::GetInstance()->levelRenderer->registerTextures(this); + EntityRenderDispatcher::instance->registerTerrainTextures(this); + } + + //for (Item item : Item.items) + for(unsigned int i = 0; i < Item::ITEM_NUM_COUNT; ++i) + { + Item *item = Item::items[i]; + if (item != NULL && item->getIconType() == iconType) + { + item->registerIcons(this); + } + } + + // Collection bucket for multiple frames per texture + unordered_map * > textures; // = new HashMap>(); + + Stitcher *stitcher = TextureManager::getInstance()->createStitcher(name); + + for(AUTO_VAR(it,texturesByName.begin()); it != texturesByName.end(); ++it) + { + delete it->second; + } + texturesByName.clear(); + animatedTextures.clear(); + + // Prep missing texture -- anything that has no resources will get pointed at this one + Texture *missingTex = TextureManager::getInstance()->createTexture(NAME_MISSING_TEXTURE, Texture::TM_CONTAINER, missingTexture->getWidth(), missingTexture->getHeight(), Texture::WM_CLAMP, Texture::TFMT_RGBA, Texture::TFLT_NEAREST, Texture::TFLT_NEAREST, m_mipMap, missingTexture); + TextureHolder *missingHolder = new TextureHolder(missingTex); + + stitcher->addTexture(missingHolder); + vector *missingVec = new vector(); + missingVec->push_back(missingTex); + textures.insert( unordered_map * >::value_type( missingHolder, missingVec )); + + // Extract frames from textures and add them to the stitchers + //for (final String name : texturesToRegister.keySet()) + for(AUTO_VAR(it, texturesToRegister.begin()); it != texturesToRegister.end(); ++it) + { + wstring name = it->first; + + wstring filename = path + name + extension; + + // TODO: [EB] Put the frames into a proper object, not this inside out hack + vector *frames = TextureManager::getInstance()->createTextures(filename, m_mipMap); + + if (frames == NULL || frames->empty()) + { + continue; // Couldn't load a texture, skip it + } + + TextureHolder *holder = new TextureHolder(frames->at(0)); + stitcher->addTexture(holder); + + // Store frames + textures.insert( unordered_map * >::value_type( holder, frames ) ); + } + + // Stitch! + //try { + stitcher->stitch(); + //} catch (StitcherException e) { + // throw e; + // TODO: [EB] Retry mechanism + //} + + // Create the final image + stitchResult = stitcher->constructTexture(m_mipMap); + + // Extract all the final positions and store them + AUTO_VAR(areas, stitcher->gatherAreas()); + //for (StitchSlot slot : stitcher.gatherAreas()) + for(AUTO_VAR(it, areas->begin()); it != areas->end(); ++it) + { + StitchSlot *slot = *it; + TextureHolder *textureHolder = slot->getHolder(); + + Texture *texture = textureHolder->getTexture(); + wstring textureName = texture->getName(); + + vector *frames = textures.find(textureHolder)->second; + + StitchedTexture *stored = NULL; + + AUTO_VAR(itTex, texturesToRegister.find(textureName) ); + if(itTex != texturesToRegister.end() ) stored = itTex->second; + + // [EB]: What is this code for? debug warnings for when during transition? + bool missing = false; + if (stored == NULL) + { + missing = true; + stored = StitchedTexture::create(textureName); + + if (textureName.compare(NAME_MISSING_TEXTURE)!=0) + { + //Minecraft::getInstance()->getLogger().warning("Couldn't find premade icon for " + textureName + " doing " + name); +#ifndef _CONTENT_PACKAGE + wprintf(L"Couldn't find premade icon for %ls doing %ls\n", textureName.c_str(), name.c_str() ); +#endif + } + } + + stored->init(stitchResult, frames, slot->getX(), slot->getY(), textureHolder->getTexture()->getWidth(), textureHolder->getTexture()->getHeight(), textureHolder->isRotated()); + + texturesByName.insert( stringStitchedTextureMap::value_type(textureName, stored) ); + if (!missing) texturesToRegister.erase(textureName); + + if (frames->size() > 1) + { + animatedTextures.push_back(stored); + + wstring animationDefinitionFile = textureName + L".txt"; + + TexturePack *texturePack = Minecraft::GetInstance()->skins->getSelected(); + bool requiresFallback = !texturePack->hasFile(L"\\" + textureName + L".png", false); + //try { + InputStream *fileStream = texturePack->getResource(L"\\" + path + animationDefinitionFile, requiresFallback); + + //Minecraft::getInstance()->getLogger().info("Found animation info for: " + animationDefinitionFile); +#ifndef _CONTENT_PACKAGE + wprintf(L"Found animation info for: %ls\n", animationDefinitionFile.c_str() ); +#endif + InputStreamReader isr(fileStream); + BufferedReader br(&isr); + stored->loadAnimationFrames(&br); + delete fileStream; + //} catch (IOException ignored) { + //} + } + } + delete areas; + + missingPosition = texturesByName.find(NAME_MISSING_TEXTURE)->second; + + //for (StitchedTexture texture : texturesToRegister.values()) + for(AUTO_VAR(it, texturesToRegister.begin() ); it != texturesToRegister.end(); ++it) + { + StitchedTexture *texture = it->second; + texture->replaceWith(missingPosition); + } + + stitchResult->writeAsPNG(L"debug.stitched_" + name + L".png"); + stitchResult->updateOnGPU(); +} + +StitchedTexture *TextureMap::getTexture(const wstring &name) +{ + StitchedTexture *result = texturesByName.find(name)->second; + if (result == NULL) result = missingPosition; + return result; +} + +void TextureMap::cycleAnimationFrames() +{ + //for (StitchedTexture texture : animatedTextures) + for(AUTO_VAR(it, animatedTextures.begin() ); it != animatedTextures.end(); ++it) + { + StitchedTexture *texture = *it; + texture->cycleFrames(); + } +} + +Texture *TextureMap::getStitchedTexture() +{ + return stitchResult; +} + +// 4J Stu - register is a reserved keyword in C++ +Icon *TextureMap::registerIcon(const wstring &name) +{ + if (name.empty()) + { + app.DebugPrintf("Don't register NULL\n"); +#ifndef _CONTENT_PACKAGE + __debugbreak(); +#endif + //new RuntimeException("Don't register null!").printStackTrace(); + } + + // TODO: [EB]: Why do we allow multiple registrations? + StitchedTexture *result = NULL; + AUTO_VAR(it, texturesToRegister.find(name)); + if(it != texturesToRegister.end()) result = it->second; + + if (result == NULL) + { + result = StitchedTexture::create(name); + texturesToRegister.insert( stringStitchedTextureMap::value_type(name, result) ); + } + + return result; +} + +int TextureMap::getIconType() +{ + return iconType; +} + +Icon *TextureMap::getMissingIcon() +{ + return missingPosition; +} \ No newline at end of file -- cgit v1.2.3