diff --git a/Minecraft.Client/ArmorStandArmorModel.cpp b/Minecraft.Client/ArmorStandArmorModel.cpp index 9fe22535..09761770 100644 --- a/Minecraft.Client/ArmorStandArmorModel.cpp +++ b/Minecraft.Client/ArmorStandArmorModel.cpp @@ -32,7 +32,7 @@ void ArmorStandArmorModel::setupAnim(float time, float r, float bob, Rotations ll = stand->getLeftLegPose(); Rotations rl = stand->getRightLegPose(); - + head->xRot = DEG_TO_RAD * h.getX(); head->yRot = DEG_TO_RAD * h.getY(); head->zRot = DEG_TO_RAD * h.getZ(); diff --git a/Minecraft.Client/ArmorStandRenderer.cpp b/Minecraft.Client/ArmorStandRenderer.cpp index 03b53b4d..1947830f 100644 --- a/Minecraft.Client/ArmorStandRenderer.cpp +++ b/Minecraft.Client/ArmorStandRenderer.cpp @@ -1,27 +1,29 @@ #include "stdafx.h" +#include "HumanoidMobRenderer.h" #include "ArmorStandRenderer.h" -#include "ArmorStandModel.h" #include "ArmorStandArmorModel.h" #include "HumanoidModel.h" -#include "ItemInHandLayer.h" +#include "ArmorStandModel.h" #include "CustomHeadLayer.h" #include "Textures.h" -#include "HumanoidMobRenderer.h" #include "../Minecraft.World/ArmorStand.h" #include "../Minecraft.World/ArmorItem.h" +#include "../Minecraft.World/Tile.h" +#include "../Minecraft.World/Facing.h" +#include +#include "EntityRenderDispatcher.h" +#include "SkullTileRenderer.h" +#include "PlayerRenderer.h" +#include "../Minecraft.World/SkullItem.h" +#include "../Minecraft.World/SkullTileEntity.h" static const float DEG_TO_RAD = 3.14159265f / 180.0f; -ResourceLocation ArmorStandRenderer::LOC_ARMOR_STAND = - ResourceLocation(TN_MOB_ARMORSTAND); +ResourceLocation ArmorStandRenderer::LOC_ARMOR_STAND = ResourceLocation(TN_MOB_ARMORSTAND); - - -ArmorStandRenderer::ArmorStandArmorLayer::ArmorStandArmorLayer( - LivingEntityRenderer* renderer) +ArmorStandRenderer::ArmorStandArmorLayer::ArmorStandArmorLayer(LivingEntityRenderer* renderer) : HumanoidArmorLayer(renderer) { - delete armorModel1; delete armorModel2; armorModel1 = new ArmorStandArmorModel(0.5f); @@ -36,26 +38,15 @@ void ArmorStandRenderer::ArmorStandArmorLayer::createArmorModels() armorModel2 = new ArmorStandArmorModel(1.0f); } - - ArmorStandRenderer::ArmorStandRenderer() : LivingEntityRenderer(new ArmorStandModel(0.0f), 0.0f) { - - addLayer(new ArmorStandArmorLayer(this)); - - - addLayer(new ItemInHandLayer(this)); - - + armorLayer = new ArmorStandArmorLayer(this); ArmorStandModel* m = static_cast(getModel()); - addLayer(new CustomHeadLayer(m->head)); + headLayer = m ? new CustomHeadLayer(m->head) : nullptr; } -ArmorStandRenderer::~ArmorStandRenderer() -{ - -} +ArmorStandRenderer::~ArmorStandRenderer() {} ResourceLocation* ArmorStandRenderer::getTextureLocation(shared_ptr entity) { @@ -64,29 +55,39 @@ ResourceLocation* ArmorStandRenderer::getTextureLocation(shared_ptr enti bool ArmorStandRenderer::shouldShowName(shared_ptr entity) { - if (!entity) return false; return entity->isCustomNameVisible(); } void ArmorStandRenderer::setupRotations(shared_ptr mob, - float bob, float bodyRot, float a) + float bob, float bodyRot, float a) { - + shared_ptr stand = dynamic_pointer_cast(mob); glRotatef(180.0f - bodyRot, 0.0f, 1.0f, 0.0f); + + if (stand) + { + long long ticksSinceHit = (long long)stand->tickCount - stand->lastHit; + if (ticksSinceHit >= 0 && ticksSinceHit < 5) + { + float wobble = (float)(ticksSinceHit + a) / 5.0f; + float angle = (float)stand->hurtDir * sinf(wobble * 3.14159265f) * 3.0f; + glRotatef(angle, 0.0f, 0.0f, 1.0f); + } + } } void ArmorStandRenderer::render(shared_ptr entity, - double x, double y, double z, - float rot, float a) + double x, double y, double z, + float rot, float a) { LivingEntityRenderer::render(entity, x, y, z, rot, a); } void ArmorStandRenderer::renderModel(shared_ptr mob, - float wp, float ws, float bob, - float headRotMinusBodyRot, - float headRotx, float scale) + float wp, float ws, float bob, + float headRotMinusBodyRot, + float headRotx, float scale) { shared_ptr stand = dynamic_pointer_cast(mob); if (!stand) return; @@ -94,7 +95,6 @@ void ArmorStandRenderer::renderModel(shared_ptr mob, ArmorStandModel* m = static_cast(getModel()); if (!m) return; - Rotations h = stand->getHeadPose(); Rotations b = stand->getBodyPose(); Rotations la = stand->getLeftArmPose(); @@ -102,120 +102,151 @@ void ArmorStandRenderer::renderModel(shared_ptr mob, Rotations ll = stand->getLeftLegPose(); Rotations rl = stand->getRightLegPose(); - m->setupPose( - h.getX() * DEG_TO_RAD, h.getY() * DEG_TO_RAD, h.getZ() * DEG_TO_RAD, - b.getX() * DEG_TO_RAD, b.getY() * DEG_TO_RAD, b.getZ() * DEG_TO_RAD, - la.getX() * DEG_TO_RAD, la.getY() * DEG_TO_RAD, la.getZ() * DEG_TO_RAD, - ra.getX() * DEG_TO_RAD, ra.getY() * DEG_TO_RAD, ra.getZ() * DEG_TO_RAD, - ll.getX() * DEG_TO_RAD, ll.getY() * DEG_TO_RAD, ll.getZ() * DEG_TO_RAD, - rl.getX() * DEG_TO_RAD, rl.getY() * DEG_TO_RAD, rl.getZ() * DEG_TO_RAD + h.x * DEG_TO_RAD, h.y * DEG_TO_RAD, h.z * DEG_TO_RAD, + b.x * DEG_TO_RAD, b.y * DEG_TO_RAD, b.z * DEG_TO_RAD, + la.x * DEG_TO_RAD, la.y * DEG_TO_RAD, la.z * DEG_TO_RAD, + ra.x * DEG_TO_RAD, ra.y * DEG_TO_RAD, ra.z * DEG_TO_RAD, + ll.x * DEG_TO_RAD, ll.y * DEG_TO_RAD, ll.z * DEG_TO_RAD, + rl.x * DEG_TO_RAD, rl.y * DEG_TO_RAD, rl.z * DEG_TO_RAD ); - - ArmorStandArmorLayer* al = getArmorLayer(); - - if (al) + if (armorLayer) { auto applyPose = [&](HumanoidModel* am) { if (!am) return; - - - am->head->xRot = h.getX() * DEG_TO_RAD; - am->head->yRot = h.getY() * DEG_TO_RAD; - am->head->zRot = h.getZ() * DEG_TO_RAD; - if (am->hair) { - am->hair->xRot = h.getX() * DEG_TO_RAD; - am->hair->yRot = h.getY() * DEG_TO_RAD; - am->hair->zRot = h.getZ() * DEG_TO_RAD; - } - - - am->body->xRot = b.getX() * DEG_TO_RAD; - am->body->yRot = b.getY() * DEG_TO_RAD; - am->body->zRot = b.getZ() * DEG_TO_RAD; - - - am->arm1->xRot = la.getX() * DEG_TO_RAD; - am->arm1->yRot = la.getY() * DEG_TO_RAD; - am->arm1->zRot = la.getZ() * DEG_TO_RAD; - - - am->arm0->xRot = ra.getX() * DEG_TO_RAD; - am->arm0->yRot = ra.getY() * DEG_TO_RAD; - am->arm0->zRot = ra.getZ() * DEG_TO_RAD; - - - am->leg0->xRot = rl.getX() * DEG_TO_RAD; - am->leg0->yRot = rl.getY() * DEG_TO_RAD; - am->leg0->zRot = rl.getZ() * DEG_TO_RAD; - - - am->leg1->xRot = ll.getX() * DEG_TO_RAD; - am->leg1->yRot = ll.getY() * DEG_TO_RAD; - am->leg1->zRot = ll.getZ() * DEG_TO_RAD; + am->head->xRot = h.x * DEG_TO_RAD; am->head->yRot = h.y * DEG_TO_RAD; am->head->zRot = h.z * DEG_TO_RAD; + if (am->hair) { am->hair->xRot = h.x * DEG_TO_RAD; am->hair->yRot = h.y * DEG_TO_RAD; am->hair->zRot = h.z * DEG_TO_RAD; } + am->body->xRot = b.x * DEG_TO_RAD; am->body->yRot = b.y * DEG_TO_RAD; am->body->zRot = b.z * DEG_TO_RAD; + am->arm1->xRot = la.x * DEG_TO_RAD; am->arm1->yRot = la.y * DEG_TO_RAD; am->arm1->zRot = la.z * DEG_TO_RAD; + am->arm0->xRot = ra.x * DEG_TO_RAD; am->arm0->yRot = ra.y * DEG_TO_RAD; am->arm0->zRot = ra.z * DEG_TO_RAD; + am->leg0->xRot = rl.x * DEG_TO_RAD; am->leg0->yRot = rl.y * DEG_TO_RAD; am->leg0->zRot = rl.z * DEG_TO_RAD; + am->leg1->xRot = ll.x * DEG_TO_RAD; am->leg1->yRot = ll.y * DEG_TO_RAD; am->leg1->zRot = ll.z * DEG_TO_RAD; }; - - applyPose(static_cast(al->armorModel1)); - applyPose(static_cast(al->armorModel2)); + applyPose(static_cast(armorLayer->armorModel1)); + applyPose(static_cast(armorLayer->armorModel2)); } - LivingEntityRenderer::renderModel(mob, wp, ws, bob, - headRotMinusBodyRot, headRotx, scale); + LivingEntityRenderer::renderModel(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale); - for (size_t i = 0; i < renderLayers.size(); ++i) { - if (renderLayers[i]) { - renderLayers[i]->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); - } + if (headLayer) + { + float fScale = 1.0f / 16.0f; + float bodyRot = mob->yBodyRotO + (mob->yBodyRot - mob->yBodyRotO) * 0.0f; + float headRot = mob->yHeadRotO + (mob->yHeadRot - mob->yHeadRotO) * 0.0f; + float headRotX = mob->xRotO + (mob->xRot - mob->xRotO) * 0.0f; + headLayer->render(mob, wp, ws, bob, headRot - bodyRot, headRotX, fScale, true); } } +void ArmorStandRenderer::additionalRendering(shared_ptr mob, float a) +{ + shared_ptr headGear = mob->getArmor(3); + if (!headGear) return; + + if ((mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_DontRenderArmour)) != 0) return; + + if (headGear->getItem()->id >= 256) return; + + ArmorStandModel* m = static_cast(getModel()); + if (!m || !m->head) return; + + glPushMatrix(); + m->head->translateTo(1.0f / 16.0f); + + if (Tile::tiles[headGear->id] != nullptr && TileRenderer::canRender(Tile::tiles[headGear->id]->getRenderShape())) + { + float s = 10.0f / 16.0f; + glTranslatef(0.0f, -4.0f / 16.0f, 0.0f); + glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + glScalef(s, -s, s); + } + this->entityRenderDispatcher->itemInHandRenderer->renderItem(mob, headGear, 0); + + glPopMatrix(); +} int ArmorStandRenderer::prepareArmor(shared_ptr mob, int layer, float a) { if (!armorLayer) return -1; shared_ptr itemInstance = mob->getArmor(3 - layer); - if (itemInstance != nullptr) + if (!itemInstance) return -1; + + Item* item = itemInstance->getItem(); + + SkullItem* skullItem = dynamic_cast(item); + if (skullItem && layer == 0) { - Item *item = itemInstance->getItem(); - ArmorItem *armorItem = dynamic_cast(item); - if (armorItem != nullptr) + HumanoidModel* am = armorLayer->getArmorModel(layer); + + switch (itemInstance->getAuxValue()) { - bindTexture(HumanoidMobRenderer::getArmorLocation(armorItem, layer)); - - HumanoidModel *am = armorLayer->getArmorModel(layer); - - am->head->visible = (layer == 0); - if (am->hair) am->hair->visible = (layer == 0); - am->body->visible = (layer == 1 || layer == 2); - am->arm0->visible = (layer == 1); - am->arm1->visible = (layer == 1); - am->leg0->visible = (layer == 2 || layer == 3); - am->leg1->visible = (layer == 2 || layer == 3); - - setArmor(am); - am->attackTime = model->attackTime; - am->riding = model->riding; - am->young = mob->isBaby(); - - if (armorItem->getMaterial() == ArmorItem::ArmorMaterial::CLOTH) - { - int color = armorItem->getColor(itemInstance); - float red = static_cast((color >> 16) & 0xFF) / 255.0f; - float green = static_cast((color >> 8) & 0xFF) / 255.0f; - float blue = static_cast(color & 0xFF) / 255.0f; - glColor3f(red, green, blue); - - if (itemInstance->isEnchanted()) return 0x1f; - return 0x10; - } - - glColor3f(1.0f, 1.0f, 1.0f); - if (itemInstance->isEnchanted()) return 15; - - return 1; + case SkullTileEntity::TYPE_WITHER: + bindTexture(&PlayerRenderer::WITHER_SKELETON_LOCATION); + break; + case SkullTileEntity::TYPE_ZOMBIE: + bindTexture(&PlayerRenderer::ZOMBIE_LOCATION); + break; + case SkullTileEntity::TYPE_CREEPER: + bindTexture(&PlayerRenderer::CREEPER_LOCATION); + break; + case SkullTileEntity::TYPE_CHAR: + bindTexture(&PlayerRenderer::DEFAULT_LOCATION); + break; + case SkullTileEntity::TYPE_SKELETON: + default: + bindTexture(&PlayerRenderer::SKELETON_LOCATION); + break; } + + am->head->visible = true; + if (am->hair) am->hair->visible = false; + am->body->visible = false; + am->arm0->visible = false; + am->arm1->visible = false; + am->leg0->visible = false; + am->leg1->visible = false; + + setArmor(am); + am->attackTime = model->attackTime; + am->riding = model->riding; + am->young = mob->isBaby(); + return 1; } - return -1; -} \ No newline at end of file + + ArmorItem* armorItem = dynamic_cast(item); + if (!armorItem) return -1; + + bindTexture(HumanoidMobRenderer::getArmorLocation(armorItem, layer)); + + HumanoidModel* am = armorLayer->getArmorModel(layer); + am->head->visible = (layer == 0); + if (am->hair) am->hair->visible = (layer == 0); + am->body->visible = (layer == 1 || layer == 2); + am->arm0->visible = (layer == 1); + am->arm1->visible = (layer == 1); + am->leg0->visible = (layer == 2 || layer == 3); + am->leg1->visible = (layer == 2 || layer == 3); + + setArmor(am); + am->attackTime = model->attackTime; + am->riding = model->riding; + am->young = mob->isBaby(); + + if (armorItem->getMaterial() == ArmorItem::ArmorMaterial::CLOTH) + { + int color = armorItem->getColor(itemInstance); + float red = static_cast((color >> 16) & 0xFF) / 255.0f; + float green = static_cast((color >> 8) & 0xFF) / 255.0f; + float blue = static_cast(color & 0xFF) / 255.0f; + glColor3f(red, green, blue); + if (itemInstance->isEnchanted()) return 0x1f; + return 0x10; + } + + glColor3f(1.0f, 1.0f, 1.0f); + if (itemInstance->isEnchanted()) return 15; + return 1; +} + diff --git a/Minecraft.Client/ArmorStandRenderer.h b/Minecraft.Client/ArmorStandRenderer.h index 827c5a66..9742f31e 100644 --- a/Minecraft.Client/ArmorStandRenderer.h +++ b/Minecraft.Client/ArmorStandRenderer.h @@ -2,13 +2,13 @@ #include "LivingEntityRenderer.h" #include "HumanoidArmorLayer.h" #include "ResourceLocation.h" - #include class ArmorStandModel; class LivingEntity; class Entity; class RenderLayer; +class CustomHeadLayer; class ArmorStandRenderer : public LivingEntityRenderer { public: @@ -22,17 +22,12 @@ public: protected: std::vector renderLayers; ArmorStandArmorLayer* armorLayer; + CustomHeadLayer* headLayer; public: - void addLayer(RenderLayer* layer) { - renderLayers.push_back(layer); - } - void addLayer(ArmorStandArmorLayer* layer) { - armorLayer = layer; - } - ArmorStandArmorLayer* getArmorLayer() { - return armorLayer; - } + void addLayer(RenderLayer* layer) { renderLayers.push_back(layer); } + void addLayer(ArmorStandArmorLayer* layer) { armorLayer = layer; } + ArmorStandArmorLayer* getArmorLayer() { return armorLayer; } static ResourceLocation LOC_ARMOR_STAND; @@ -40,15 +35,17 @@ public: virtual ~ArmorStandRenderer(); virtual ResourceLocation* getTextureLocation(shared_ptr entity) override; - virtual bool shouldShowName(shared_ptr mob) override; - virtual void setupRotations(shared_ptr mob, - float bob, float bodyRot, float a) override; - virtual void render(shared_ptr entity, - double x, double y, double z, - float rot, float a) override; - virtual void renderModel(shared_ptr mob, - float wp, float ws, float bob, - float headRotMinusBodyRot, - float headRotx, float scale) override; - virtual int prepareArmor(shared_ptr mob, int layer, float a) override; + virtual bool shouldShowName(shared_ptr mob) override; + + virtual void setupRotations(shared_ptr mob, + float bob, float bodyRot, float a) override; + virtual void render(shared_ptr entity, + double x, double y, double z, + float rot, float a) override; + virtual void renderModel(shared_ptr mob, + float wp, float ws, float bob, + float headRotMinusBodyRot, + float headRotx, float scale) override; + virtual int prepareArmor(shared_ptr mob, int layer, float a) override; + virtual void additionalRendering(shared_ptr mob, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/CustomHeadLayer.cpp b/Minecraft.Client/CustomHeadLayer.cpp index a62cfca0..ad522b70 100644 --- a/Minecraft.Client/CustomHeadLayer.cpp +++ b/Minecraft.Client/CustomHeadLayer.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "CustomHeadLayer.h" #include "ModelPart.h" +#include "SkullTileRenderer.h" +#include "TileRenderer.h" #include "../Minecraft.World/ItemInstance.h" #include "../Minecraft.World/Item.h" #include "../Minecraft.World/Tile.h" @@ -11,7 +13,8 @@ CustomHeadLayer::CustomHeadLayer(ModelPart* headPart) { } -int CustomHeadLayer::colorsOnDamage() { +int CustomHeadLayer::colorsOnDamage() +{ return 1; } @@ -20,59 +23,43 @@ void CustomHeadLayer::render(shared_ptr mob, float headRot, float headRotX, float scale, bool useCompiled) { - ItemInstanceArray slots = mob->getEquipmentSlots(); if (slots.length < 5) return; shared_ptr helmet = slots[4]; if (!helmet) return; - Item* item = helmet->getItem(); if (!item) return; - bool hasHatLayer = false; if (mob->instanceof(eTYPE_PLAYER)) { _SkinAdjustments adj; mob->getSkinAdjustments(&adj); - hasHatLayer = (adj.data[0] & 0x100) != 0; } - - glPushMatrix(); - - headPart->translateTo(0.0625f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - int itemId = item->id; + int itemId = item->id; - if (itemId == Tile::skull_Id) { - - glScalef(1.1875f, -1.1875f, -1.1875f); - if (hasHatLayer) - glTranslatef(0.0f, 0.0625f, 0.0f); - - - - } else if (itemId < 0x100) { - - glTranslatef(0.0f, -0.25f, 0.0f); - glRotatef(180.0f, 0.0f, 1.0f, 0.0f); - glScalef(0.625f, -0.625f, -0.625f); - - if (hasHatLayer) - glTranslatef(0.0f, 0.1875f, 0.0f); - - glRotatef(90.0f, 0.0f, 1.0f, 0.0f); - - - if (itemId > 0 && itemId < Tile::TILE_NUM_COUNT && Tile::tiles[itemId]) { - - } + if (itemId == Tile::skull_Id) { + if (!SkullTileRenderer::instance) { glPopMatrix(); return; } + glScalef(1.1875f, -1.1875f, -1.1875f); + glTranslatef(-0.5f, 0.0f, -0.5f); + int skullType = helmet->getAuxValue() & 0xF; + wstring extra = helmet->hasTag() ? helmet->getTag()->getString(L"SkullOwner") : L""; + SkullTileRenderer::instance->renderSkull(0.0f, 0.0f, 0.0f, -1, 180.0f, skullType, extra); + } else if (itemId < 0x100) { + glTranslatef(0.0f, -0.25f, 0.0f); + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); + glScalef(0.625f, 0.625f, 0.625f); + glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + if (itemId > 0 && itemId < Tile::TILE_NUM_COUNT && Tile::tiles[itemId]) { + TileRenderer tr; + tr.renderTile(Tile::tiles[itemId], helmet->getAuxValue(), 1.0f, 1.0f, useCompiled); } - +} glPopMatrix(); } \ No newline at end of file diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index d3dc4491..458a3236 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -18,6 +18,7 @@ #include "Textures.h" #include "Skins.h" + ResourceLocation PlayerRenderer::SKELETON_LOCATION = ResourceLocation(TN_MOB_SKELETON); ResourceLocation PlayerRenderer::WITHER_SKELETON_LOCATION = ResourceLocation(TN_MOB_WITHER_SKELETON); ResourceLocation PlayerRenderer::ZOMBIE_LOCATION = ResourceLocation(TN_MOB_ZOMBIE); diff --git a/Minecraft.Client/PlayerRenderer.h b/Minecraft.Client/PlayerRenderer.h index ce61abb3..c2d2c12c 100644 --- a/Minecraft.Client/PlayerRenderer.h +++ b/Minecraft.Client/PlayerRenderer.h @@ -22,7 +22,7 @@ private: HumanoidModel *armorParts2; HumanoidModel *armorParts3; bool defaultSlimHands; - +public: static ResourceLocation SKELETON_LOCATION; static ResourceLocation WITHER_SKELETON_LOCATION; static ResourceLocation ZOMBIE_LOCATION; diff --git a/Minecraft.Server/FourKitNatives.cpp b/Minecraft.Server/FourKitNatives.cpp index f634e825..758aea7e 100644 --- a/Minecraft.Server/FourKitNatives.cpp +++ b/Minecraft.Server/FourKitNatives.cpp @@ -33,6 +33,7 @@ #include "../Minecraft.World/SetHealthPacket.h" #include "../Minecraft.World/LevelSoundPacket.h" #include "../Minecraft.World/LevelParticlesPacket.h" +#include "../Minecraft.Client/ParticleType.h" #include "../Minecraft.World/SetEntityLinkPacket.h" #include "../Minecraft.World/SimpleContainer.h" #include "../Minecraft.World/Slot.h" @@ -633,9 +634,6 @@ int __cdecl NativeSendRaw(int entityId, unsigned char *bufferData, int bufferSiz void WriteInventoryItemData(std::shared_ptr item, int index, int* outBuffer) { if (item) { - //ItemFlags Key: - // 0x1 = hasMetadata (has data that needs to be gotten from "ReadMetaFromNative") - uint8_t itemFlags = 0; if (item->getTag() == nullptr) goto doneWithMetadataFlag; CompoundTag* itemTag = item->getTag(); @@ -644,7 +642,7 @@ void WriteInventoryItemData(std::shared_ptr item, int index, int* itemFlags |= 0x1; goto doneWithMetadataFlag; } - else { //we just want to check one tag for metadata and return for this flag, not all of them + else { CompoundTag* displayTag = itemTag->getCompound(L"display"); if (displayTag->contains(L"Name") || displayTag->contains(L"Lore")) { itemFlags |= 0x1; @@ -652,9 +650,7 @@ void WriteInventoryItemData(std::shared_ptr item, int index, int* } } - doneWithMetadataFlag: - outBuffer[(index * 3) + 0] = item->id; outBuffer[(index * 3) + 1] = item->getAuxValue(); outBuffer[(index * 3) + 2] = (((int)itemFlags << 24) | ((int)item->count << 8)); @@ -663,9 +659,6 @@ void WriteInventoryItemData(std::shared_ptr item, int index, int* void __cdecl NativeGetPlayerInventory(int entityId, int *outData) { - // 9 slots per row, 3 slots in the inventory and the hotbar, 4 armor slots, 1 hand slot - // (((slotsPerRow * Rows) + ArmorSlots) * AmountOfIntsPerSlot) + hand slot - // (((9 * 4) + 4) * 3) + 1 = 121 memset(outData, 0, 121 * sizeof(int)); auto player = FindPlayer(entityId); @@ -806,8 +799,7 @@ void __cdecl NativeOpenVirtualContainer(int entityId, int nativeType, const char player->openContainer(container); } -//didnt update this for enchants -// [nameLen:int32][nameUTF8:bytes][loreCount:int32][lore0Len:int32][lore0UTF8:bytes] + int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) { auto player = FindPlayer(entityId); @@ -829,7 +821,6 @@ int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) CompoundTag *display = tag->getCompound(L"display"); bool hasName = display->contains(L"Name"); bool hasLore = display->contains(L"Lore"); - bool hasEnchantments = item->isEnchanted(); if (!hasName && !hasLore) @@ -888,18 +879,14 @@ int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize) ListTag* list = item->getEnchantmentTags(); if (list != nullptr) { int listSize = list->size(); - if ((offset + 4 + (listSize * (4 + 4))) > bufSize) return 0; - memcpy(outBuf + offset, &listSize, 4); offset += 4; for (int i = 0; i < listSize; i++) { int type = list->get(i)->getShort((wchar_t*)ItemInstance::TAG_ENCH_ID); int level = list->get(i)->getShort((wchar_t*)ItemInstance::TAG_ENCH_LEVEL); - memcpy(outBuf + offset, &type, 4); offset += 4; - memcpy(outBuf + offset, &level, 4); offset += 4; } @@ -946,11 +933,8 @@ void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bu item->setTag(nullptr); } } - if (tag && tag->contains(L"ench")) - { tag->remove(L"ench"); - } } return; } @@ -1030,15 +1014,12 @@ void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bu for (int i = 0; i < enchantCount; i++) { if (offset + (4 + 4) > bufSize) break; - int type = 0; memcpy(&type, inBuf + offset, 4); offset += 4; - int level = 0; memcpy(&level, inBuf + offset, 4); offset += 4; - CompoundTag* ench = new CompoundTag(); ench->putShort((wchar_t*)ItemInstance::TAG_ENCH_ID, static_cast(type)); ench->putShort((wchar_t*)ItemInstance::TAG_ENCH_LEVEL, static_cast(level)); @@ -1051,9 +1032,7 @@ void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bu { CompoundTag* tag = item->getTag(); if (tag && tag->contains(L"ench")) - { tag->remove(L"ench"); - } } } } @@ -1190,13 +1169,15 @@ void __cdecl NativeSetExhaustion(int entityId, float exhaustion) fd->setExhaustion(exhaustion); } + void __cdecl NativeSpawnParticle(int entityId, int particleId, float x, float y, float z, float offsetX, float offsetY, float offsetZ, float speed, int count) { auto player = FindPlayer(entityId); if (!player || !player->connection) return; - wchar_t buf[32]; - swprintf_s(buf, L"%d", particleId); - player->connection->send(std::make_shared(std::wstring(buf), x, y, z, offsetX, offsetY, offsetZ, speed, count)); + const ParticleType* type = ParticleType::byId(particleId); + if (!type) type = ParticleType::getDefault(); + arrayWithLength noParams = { nullptr, 0 }; + player->connection->send(std::make_shared(type, false, x, y, z, offsetX, offsetY, offsetZ, speed, count, noParams)); } int __cdecl NativeSetPassenger(int entityId, int passengerEntityId) @@ -1268,4 +1249,4 @@ void __cdecl NativeGetEntityInfo(int entityId, double *outData) outData[4] = (double)entity->dimension; } -} // namespace FourKitBridge +} // namespace FourKitBridge \ No newline at end of file diff --git a/Minecraft.World/ArmorStand.cpp b/Minecraft.World/ArmorStand.cpp index 999917d4..c130a913 100644 --- a/Minecraft.World/ArmorStand.cpp +++ b/Minecraft.World/ArmorStand.cpp @@ -35,11 +35,13 @@ void ArmorStand::init() registerAttributes(); defineSynchedData(); - lastHit = 0; + lastHit = -100LL; + standDamage = 0.0f; + hurtDir = 1; disabledSlots = 0; invisible = false; isMarkerFlag = false; - + heightOffset = 0.0f; for (int i = 0; i < equipmentCount; i++) equipment[i] = nullptr; @@ -56,7 +58,6 @@ void ArmorStand::init() setSize(0.5f, 1.975f); } - void ArmorStand::registerAttributes() { LivingEntity::registerAttributes(); @@ -68,8 +69,7 @@ void ArmorStand::registerAttributes() void ArmorStand::defineSynchedData() { LivingEntity::defineSynchedData(); - // ArmorStand doesn't inherit from Mob, so we must register - // the custom-name fields that Mob::defineSynchedData() normally provides. + entityData->define(3, static_cast(0)); // DATA_CUSTOM_NAME_VISIBLE entityData->define(2, wstring(L"")); // DATA_CUSTOM_NAME entityData->define(DATA_CLIENT_FLAGS, static_cast(0)); @@ -193,13 +193,27 @@ void ArmorStand::tick() { float lockedRot = this->yRot; LivingEntity::tick(); - this->yRot = lockedRot; - this->yRotO = lockedRot; - this->yBodyRot = lockedRot; + if (onGround) + { + BlockPos pos((int)floorf(x), (int)floorf(y) - 1, (int)floorf(z)); + int blockId = level->getTile(pos.getX(), pos.getY(), pos.getZ()); + if (blockId == Tile::topSnow->id) + { + int meta = level->getData(pos.getX(), pos.getY(), pos.getZ()); + float snowHeight = ((meta & 0x7) + 1) * 0.125f; + moveTo(x, floorf(y) + snowHeight, z, yRot, xRot); + } + } + this->yRot = lockedRot; + this->yRotO = lockedRot; + this->yBodyRot = lockedRot; this->yBodyRotO = lockedRot; - this->yHeadRot = lockedRot; + this->yHeadRot = lockedRot; this->yHeadRotO = lockedRot; + if ((long long)tickCount - lastHit > 20) + standDamage = 0.0f; + auto syncPose = [&](int slot, Rotations& local) { Rotations net = entityData->getRotations(slot); @@ -254,6 +268,7 @@ void ArmorStand::causeDamage(float damage) h -= damage; if (h <= 0.5f) { + spawnAtLocation(Item::armor_stand_Id, 1); brokenByAnything(); remove(); } @@ -266,59 +281,63 @@ void ArmorStand::causeDamage(float damage) bool ArmorStand::hurt(DamageSource* source, float damage) { if (isInvulnerable() || level->isClientSide || removed || isMarker()) return false; - if (source != nullptr && source->getMsgId() == eEntityDamageType_Suffocate) return false; - if (source->isExplosion()) - { - brokenByAnything(); - remove(); - return true; - } - - bool isFireDamage = source->isFire(); + if (source->getMsgId() == eEntityDamageType_Suffocate) return false; if (dynamic_cast(source) != nullptr) { - shared_ptr attacker = source->getEntity(); - if (attacker != nullptr && attacker->instanceof(eTYPE_PLAYER)) - { - if (dynamic_pointer_cast(attacker)->abilities.instabuild) - { - level->broadcastEntityEvent(shared_from_this(), (byte)31); - remove(); - return true; - } - } + shared_ptr attacker = source->getDirectEntity(); + if (attacker && attacker->instanceof(eTYPE_PLAYER) && + !dynamic_pointer_cast(attacker)->isAllowedToHurtEntity(shared_from_this())) + return false; } - if (isFireDamage) + if (source->isExplosion()) { - float currentHealth = this->getHealth() - 0.15f; - this->setHealth(currentHealth); - if (currentHealth <= 0.5f) - { - brokenByAnything(); - remove(); - return true; - } - return false; - } - - long long now = (long long)tickCount; - if (now - lastHit > 5) - { - level->broadcastEntityEvent(shared_from_this(), (byte)32); - lastHit = now; - return true; - } - else - { - level->broadcastEntityEvent(shared_from_this(), (byte)31); spawnAtLocation(Item::armor_stand_Id, 1); brokenByAnything(); remove(); return true; } + + if (dynamic_cast(source) != nullptr) + { + shared_ptr attacker = source->getEntity(); + if (attacker && attacker->instanceof(eTYPE_PLAYER) && + dynamic_pointer_cast(attacker)->abilities.instabuild) + { + level->broadcastEntityEvent(shared_from_this(), (byte)31); + remove(); + return true; + } + } + + if (source->isFire()) + { + if (isInWater()) return false; + float h = getHealth() - 0.15f; + setHealth(h); + if (h <= 0.5f) + { + brokenByAnything(); + remove(); + } + return false; + } + + hurtDir = -hurtDir; + standDamage += damage * 10.0f; + lastHit = (long long)tickCount; + level->broadcastEntityEvent(shared_from_this(), (byte)32); + + if (standDamage >= 40.0f) + { + spawnAtLocation(Item::armor_stand_Id, 1); + brokenByAnything(); + remove(); + } + + return true; } diff --git a/Minecraft.World/ArmorStand.h b/Minecraft.World/ArmorStand.h index efbf79ca..629d08aa 100644 --- a/Minecraft.World/ArmorStand.h +++ b/Minecraft.World/ArmorStand.h @@ -55,9 +55,11 @@ private: bool invisible; bool isMarkerFlag; bool noPhysics; + float standDamage; public: long long lastHit; + int hurtDir; explicit ArmorStand(Level* level); virtual ~ArmorStand();