diff --git a/Minecraft.Client/BannerRenderer.cpp b/Minecraft.Client/BannerRenderer.cpp index 248d4a92..56bf5b7d 100644 --- a/Minecraft.Client/BannerRenderer.cpp +++ b/Minecraft.Client/BannerRenderer.cpp @@ -3,14 +3,19 @@ #include "BannerModel.h" #include "ModelPart.h" #include "TileEntityRenderDispatcher.h" +#include "Textures.h" #include "../Minecraft.World/net.minecraft.world.level.tile.entity.h" #include "../Minecraft.World/net.minecraft.world.level.tile.h" #include "../Minecraft.World/net.minecraft.world.level.h" #include "../Minecraft.World/DyePowderItem.h" #include "../Minecraft.World/Entity.h" #include "../Minecraft.World/Level.h" +#include "../Minecraft.World/ItemInstance.h" +#include "../Minecraft.World/com.mojang.nbt.h" +#include "../Minecraft.World/BannerTileEntity.h" #include "Lighting.h" #include +#include BannerRenderer *BannerRenderer::instance = nullptr; ResourceLocation BannerRenderer::BANNER_LOCATION = ResourceLocation(TN_MOB_BANNER_BANNER_BASE); @@ -42,14 +47,112 @@ static void applyBannerColor(int baseColor, float alpha, float brightness = 1.0f } } -void BannerRenderer::renderModelColoured(int baseColor, float alpha, bool useCompiled, float brightness) +const wchar_t *BannerRenderer::patternTextureName(const std::wstring &id) +{ + static const struct { const wchar_t *id; const wchar_t *tex; } MAP[] = + { + { L"bl", L"square_bottom_left" }, { L"br", L"square_bottom_right" }, + { L"tl", L"square_top_left" }, { L"tr", L"square_top_right" }, + { L"bs", L"stripe_bottom" }, { L"ts", L"stripe_top" }, + { L"ls", L"stripe_left" }, { L"rs", L"stripe_right" }, + { L"cs", L"stripe_center" }, { L"ms", L"stripe_middle" }, + { L"drs", L"stripe_downright" }, { L"dls", L"stripe_downleft" }, + { L"ss", L"small_stripes" }, { L"cr", L"cross" }, + { L"sc", L"straight_cross" }, { L"bt", L"triangle_bottom" }, + { L"tt", L"triangle_top" }, { L"bts", L"triangles_bottom" }, + { L"tts", L"triangles_top" }, { L"ld", L"diagonal_left" }, + { L"rd", L"diagonal_up_right" }, { L"lud", L"diagonal_up_left" }, + { L"rud", L"diagonal_right" }, { L"mc", L"circle" }, + { L"mr", L"rhombus" }, { L"vh", L"half_vertical" }, + { L"hh", L"half_horizontal" }, { L"vhr", L"half_vertical_right" }, + { L"hhb", L"half_horizontal_bottom" }, { L"bo", L"border" }, + { L"cbo", L"curly_border" }, { L"cre", L"creeper" }, + { L"gra", L"gradient" }, { L"gru", L"gradient_up" }, + { L"bri", L"bricks" }, { L"sku", L"skull" }, + { L"flo", L"flower" }, { L"moj", L"mojang" }, + }; + for (const auto &e : MAP) + { + if (id == e.id) return e.tex; + } + return nullptr; +} + +std::vector BannerRenderer::patternsFromItem(shared_ptr bannerItem) +{ + std::vector out; + if (bannerItem == nullptr || !bannerItem->hasTag()) return out; + + CompoundTag *tag = bannerItem->getTag(); + if (!tag->contains(L"BlockEntityTag", Tag::TAG_Compound)) return out; + CompoundTag *bet = tag->getCompound(L"BlockEntityTag"); + if (!bet->contains(L"Patterns")) return out; + + ListTag *list = static_cast *>( + static_cast(bet->getList(L"Patterns"))); + if (!list) return out; + + for (int i = 0; i < list->size() && i < 6; i++) + { + CompoundTag *entry = list->get(i); + BannerPattern bp; + bp.pattern = entry->getString(L"Pattern"); + bp.color = entry->getInt(L"Color"); + out.push_back(bp); + } + return out; +} + +void BannerRenderer::renderPatterns(const std::vector &patterns, float alpha, float lightU, float lightV) +{ + if (patterns.empty()) return; + + Textures *textures = tileEntityRenderDispatcher ? tileEntityRenderDispatcher->textures : nullptr; + if (textures == nullptr) return; + + float restoreU, restoreV; + glGetLightmapUV(restoreU, restoreV); + if (lightU >= 0.0f) { restoreU = lightU; restoreV = lightV; } + + glEnable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + + for (const BannerPattern &bp : patterns) + { + const wchar_t *tex = patternTextureName(bp.pattern); + if (tex == nullptr) continue; + + ResourceLocation loc(std::wstring(L"mob/banner/") + tex + L".png"); + textures->bindTexture(&loc); + + glMultiTexCoord2f(GL_TEXTURE1, 240.0f, 240.0f); + glColorMask(true, true, true, false); + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + glColor4f(1.0f, 1.0f, 1.0f, alpha); + bannerModel->bannerSlate->render(1.0f / 16.0f, false); + glColorMask(true, true, true, true); + + glMultiTexCoord2f(GL_TEXTURE1, restoreU, restoreV); + glBlendFunc(GL_ONE, GL_ONE); + applyBannerColor(bp.color, alpha); + bannerModel->bannerSlate->render(1.0f / 16.0f, false); + } + + glDisable(GL_BLEND); +} + +void BannerRenderer::renderModelColoured(int baseColor, const std::vector &patterns, float alpha, bool useCompiled, float lightU, float lightV) { bindTexture(&BANNER_LOCATION); - applyBannerColor(baseColor, alpha, brightness); + glDisable(GL_BLEND); + applyBannerColor(baseColor, alpha); bannerModel->bannerSlate->render(1.0f / 16.0f, false); - glColor4f(brightness, brightness, brightness, alpha); + renderPatterns(patterns, alpha, lightU, lightV); + + bindTexture(&BANNER_LOCATION); + glColor4f(1.0f, 1.0f, 1.0f, alpha); bannerModel->bannerStand->render(1.0f / 16.0f, useCompiled); bannerModel->bannerTop->render(1.0f / 16.0f, useCompiled); } @@ -93,15 +196,21 @@ void BannerRenderer::render(shared_ptr _banner, double x, double y, bannerModel->bannerSlate->xRot = (-0.0125f + 0.01f * cosf(f3 * 3.14159265f * 0.02f)) * 3.14159265f; glScalef(f, -f, -f); - renderModelColoured(banner->getBaseColor(), alpha, useCompiled); + int lightCol = banner->level->getLightColor(banner->x, banner->y, banner->z, 0); + float lightU = (float)(lightCol & 0xFFFF); + float lightV = (float)((lightCol >> 16) & 0xFFFF); + renderModelColoured(banner->getBaseColor(), banner->getPatterns(), alpha, useCompiled, lightU, lightV); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glMultiTexCoord2f(GL_TEXTURE1, 240.0f, 240.0f); glPopMatrix(); glEnable(GL_LIGHTING); } -void BannerRenderer::renderBannerForGui(float x, float y, float scaleX, float scaleY, float alpha, int baseColor) +void BannerRenderer::renderBannerForGui(float x, float y, float scaleX, float scaleY, float alpha, int baseColor, shared_ptr bannerItem) { + std::vector patterns = patternsFromItem(bannerItem); + glPushMatrix(); glEnable(GL_COLOR_MATERIAL); @@ -122,7 +231,7 @@ void BannerRenderer::renderBannerForGui(float x, float y, float scaleX, float sc bannerModel->bannerStand->visible = true; Lighting::setAmbient(0.6f); - renderModelColoured(baseColor, alpha, false); + renderModelColoured(baseColor, patterns, alpha, false); Lighting::setAmbient(0.4f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -130,8 +239,10 @@ void BannerRenderer::renderBannerForGui(float x, float y, float scaleX, float sc glPopMatrix(); } -void BannerRenderer::renderBannerForHand(float alpha, int baseColor) +void BannerRenderer::renderBannerForHand(float alpha, int baseColor, shared_ptr bannerItem) { + std::vector patterns = patternsFromItem(bannerItem); + glDisable(GL_LIGHTING); glPushMatrix(); @@ -139,7 +250,7 @@ void BannerRenderer::renderBannerForHand(float alpha, int baseColor) bannerModel->bannerSlate->xRot = 0.0f; bannerModel->bannerStand->visible = true; - renderModelColoured(baseColor, alpha, false); + renderModelColoured(baseColor, patterns, alpha, false); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glPopMatrix(); diff --git a/Minecraft.Client/BannerRenderer.h b/Minecraft.Client/BannerRenderer.h index b511dd4d..ff4ded14 100644 --- a/Minecraft.Client/BannerRenderer.h +++ b/Minecraft.Client/BannerRenderer.h @@ -1,6 +1,9 @@ #pragma once #include "TileEntityRenderer.h" +#include "../Minecraft.World/BannerTileEntity.h" +#include class BannerModel; +class ItemInstance; class BannerRenderer : public TileEntityRenderer { @@ -11,13 +14,17 @@ private: static ResourceLocation BANNER_LOCATION; BannerModel *bannerModel; - void renderModelColoured(int baseColor, float alpha, bool useCompiled, float brightness = 1.0f); + void renderModelColoured(int baseColor, const std::vector &patterns, float alpha, bool useCompiled, float lightU = -1.0f, float lightV = -1.0f); + void renderPatterns(const std::vector &patterns, float alpha, float lightU = -1.0f, float lightV = -1.0f); + + static std::vector patternsFromItem(shared_ptr bannerItem); + static const wchar_t *patternTextureName(const std::wstring &patternId); public: BannerRenderer(); virtual void init(TileEntityRenderDispatcher *dispatcher) override; virtual void render(shared_ptr banner, double x, double y, double z, float a, bool setColor, float alpha = 1.0f, bool useCompiled = true); - void renderBannerForGui(float x, float y, float scaleX, float scaleY, float alpha, int baseColor); - void renderBannerForHand(float alpha, int baseColor); + void renderBannerForGui(float x, float y, float scaleX, float scaleY, float alpha, int baseColor, shared_ptr bannerItem = nullptr); + void renderBannerForHand(float alpha, int baseColor, shared_ptr bannerItem = nullptr); }; diff --git a/Minecraft.Client/glWrapper.cpp b/Minecraft.Client/glWrapper.cpp index b6753a72..9081bcc3 100644 --- a/Minecraft.Client/glWrapper.cpp +++ b/Minecraft.Client/glWrapper.cpp @@ -370,15 +370,26 @@ void glColorMask(bool red, bool green, bool blue, bool alpha) RenderManager.StateSetWriteEnable(red, green, blue, alpha); } +static float s_lightmapU = 240.0f; +static float s_lightmapV = 240.0f; + void glMultiTexCoord2f(int, float u , float v) { // Clamp these values just to be safe - the lighting code can get broken if we pass things to StateSetVertexTextureUV that are >= 1 if( u > 255.0f ) u = 255.0f; if( v > 255.0f ) v = 255.0f; + s_lightmapU = u; + s_lightmapV = v; RenderManager.StateSetVertexTextureUV( u / 256.0f, v / 256.0f); } +void glGetLightmapUV(float &u, float &v) +{ + u = s_lightmapU; + v = s_lightmapV; +} + void glTexGen(int coord, int mode, FloatBuffer *vec) { float *data = vec->_getDataPointer(); diff --git a/Minecraft.Client/stubs.h b/Minecraft.Client/stubs.h index 97792a26..c9f3b0f2 100644 --- a/Minecraft.Client/stubs.h +++ b/Minecraft.Client/stubs.h @@ -114,6 +114,7 @@ void glFogf(int,float); void glFog(int,FloatBuffer *); void glColorMaterial(int,int); void glMultiTexCoord2f(int, float, float); +void glGetLightmapUV(float &u, float &v); void glTexParameterf(int target, int param, float value); //1.8.2 void glClientActiveTexture(int); diff --git a/Minecraft.World/BannerItem.cpp b/Minecraft.World/BannerItem.cpp index 34eaecb2..162ed802 100644 --- a/Minecraft.World/BannerItem.cpp +++ b/Minecraft.World/BannerItem.cpp @@ -10,22 +10,22 @@ const unsigned int BannerItem::COLOR_DESCS[16] = { - IDS_TILE_BANNER_BLACK, - IDS_TILE_BANNER_RED, - IDS_TILE_BANNER_GREEN, - IDS_TILE_BANNER_BROWN, - IDS_TILE_BANNER_BLUE, - IDS_TILE_BANNER_PURPLE, - IDS_TILE_BANNER_CYAN, - IDS_TILE_BANNER_SILVER, - IDS_TILE_BANNER_GRAY, - IDS_TILE_BANNER_PINK, - IDS_TILE_BANNER_LIME, - IDS_TILE_BANNER_YELLOW, - IDS_TILE_BANNER_LIGHT_BLUE, - IDS_TILE_BANNER_MAGENTA, - IDS_TILE_BANNER_ORANGE, IDS_TILE_BANNER_WHITE, + IDS_TILE_BANNER_ORANGE, + IDS_TILE_BANNER_MAGENTA, + IDS_TILE_BANNER_LIGHT_BLUE, + IDS_TILE_BANNER_YELLOW, + IDS_TILE_BANNER_LIME, + IDS_TILE_BANNER_PINK, + IDS_TILE_BANNER_GRAY, + IDS_TILE_BANNER_SILVER, + IDS_TILE_BANNER_CYAN, + IDS_TILE_BANNER_PURPLE, + IDS_TILE_BANNER_BLUE, + IDS_TILE_BANNER_BROWN, + IDS_TILE_BANNER_GREEN, + IDS_TILE_BANNER_RED, + IDS_TILE_BANNER_BLACK, }; BannerItem::BannerItem(int id) : Item(id) @@ -70,7 +70,7 @@ bool BannerItem::useOn(shared_ptr instance, shared_ptr pla shared_ptr bte = dynamic_pointer_cast(level->getTileEntity(x, y, z)); if (bte != nullptr) { - int color = instance->getAuxValue() & 15; + int color = 15 - (instance->getAuxValue() & 15); bte->setBaseColor(color); bte->setChanged(); } diff --git a/Minecraft.World/BannerTile.cpp b/Minecraft.World/BannerTile.cpp index 2a0dfc93..d99dd377 100644 --- a/Minecraft.World/BannerTile.cpp +++ b/Minecraft.World/BannerTile.cpp @@ -133,7 +133,7 @@ void BannerTile::registerIcons(IconRegister *iconRegister) void BannerTile::playerWillDestroy(Level *level, int x, int y, int z, int data, shared_ptr player) { shared_ptr bte = dynamic_pointer_cast(level->getTileEntity(x, y, z)); - m_dropColor = (bte != nullptr) ? (bte->getBaseColor() & 15) : 15; + m_dropColor = (bte != nullptr) ? (15 - (bte->getBaseColor() & 15)) : 0; BaseEntityTile::playerWillDestroy(level, x, y, z, data, player); } diff --git a/Minecraft.World/WeighedTreasure.cpp b/Minecraft.World/WeighedTreasure.cpp index 815b9f0d..d8d484af 100644 --- a/Minecraft.World/WeighedTreasure.cpp +++ b/Minecraft.World/WeighedTreasure.cpp @@ -4,6 +4,7 @@ #include "LootTableManager.h" #include "WeighedRandom.h" #include "WeighedTreasure.h" +#include "EnchantmentHelper.h" #include @@ -21,6 +22,16 @@ namespace shared_ptr item = std::make_shared(drop.itemId, 1, drop.data); + if (drop.damageFraction > 0.0) + { + item->setAuxValue((int)((double)item->getMaxDamage() * drop.damageFraction)); + } + + if (drop.enchantLevels > 0) + { + EnchantmentHelper::enchantItem(random, item, drop.enchantLevels); + } + if (item->getMaxStackSize() >= drop.count) { shared_ptr copy = item->copy();