diff --git a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp index 6e2ad2b3..ce90b26f 100644 --- a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp @@ -426,6 +426,10 @@ void IUIScene_CreativeMenu::staticCtor() ITEM_AUX(Item::spawnEgg_Id, 62); // Magma Cube ITEM_AUX(Item::spawnEgg_Id, 65); // Bat ITEM_AUX(Item::spawnEgg_Id, 66); // Witch + + ITEM_AUX(Item::spawnEgg_Id, 67); // Endermite + ITEM_AUX(Item::spawnEgg_Id, 68); // Guardian + ITEM_AUX(Item::spawnEgg_Id, 4); // Elder Guardian ITEM_AUX(Item::spawnEgg_Id, 90); // Pig ITEM_AUX(Item::spawnEgg_Id, 91); // Sheep ITEM_AUX(Item::spawnEgg_Id, 92); // Cow @@ -435,7 +439,6 @@ void IUIScene_CreativeMenu::staticCtor() ITEM_AUX(Item::spawnEgg_Id, 96); // Mooshroom ITEM_AUX(Item::spawnEgg_Id, 98); // Ozelot ITEM_AUX(Item::spawnEgg_Id, 100); // Horse - ITEM_AUX(Item::spawnEgg_Id, 67); // Endermite ITEM_AUX(Item::spawnEgg_Id, 100 | ((EntityHorse::TYPE_DONKEY + 1) << 12) ); // Donkey ITEM_AUX(Item::spawnEgg_Id, 100 | ((EntityHorse::TYPE_MULE + 1) << 12)); // Mule diff --git a/Minecraft.Client/Common/UI/UIScene_MainMenu.h b/Minecraft.Client/Common/UI/UIScene_MainMenu.h index 2b49a44b..0a3665ee 100644 --- a/Minecraft.Client/Common/UI/UIScene_MainMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_MainMenu.h @@ -12,6 +12,7 @@ private: eControl_Achievements, eControl_HelpAndOptions, eControl_UnlockOrDLC, + eControl_MiniGames, #ifndef _DURANGO eControl_Exit, #else @@ -38,7 +39,9 @@ private: UI_MAP_ELEMENT( m_buttons[(int)eControl_HelpAndOptions], "Button4") UI_MAP_ELEMENT( m_buttons[(int)eControl_UnlockOrDLC], "Button5") #ifndef _DURANGO + UI_MAP_ELEMENT( m_buttons[(int)eControl_MiniGames], "Button7") UI_MAP_ELEMENT( m_buttons[(int)eControl_Exit], "Button6") + #else UI_MAP_ELEMENT( m_buttons[(int)eControl_XboxHelp], "Button6") #endif diff --git a/Minecraft.Client/Common/res/1_2_2/mob/guardian.png b/Minecraft.Client/Common/res/1_2_2/mob/guardian.png new file mode 100644 index 00000000..12e1846b Binary files /dev/null and b/Minecraft.Client/Common/res/1_2_2/mob/guardian.png differ diff --git a/Minecraft.Client/Common/res/1_2_2/mob/guardian_beam.png b/Minecraft.Client/Common/res/1_2_2/mob/guardian_beam.png new file mode 100644 index 00000000..68f0109e Binary files /dev/null and b/Minecraft.Client/Common/res/1_2_2/mob/guardian_beam.png differ diff --git a/Minecraft.Client/Common/res/1_2_2/mob/guardian_elder.png b/Minecraft.Client/Common/res/1_2_2/mob/guardian_elder.png new file mode 100644 index 00000000..c8c827bb Binary files /dev/null and b/Minecraft.Client/Common/res/1_2_2/mob/guardian_elder.png differ diff --git a/Minecraft.Client/EntityRenderDispatcher.cpp b/Minecraft.Client/EntityRenderDispatcher.cpp index 474d3fa4..9b610b58 100644 --- a/Minecraft.Client/EntityRenderDispatcher.cpp +++ b/Minecraft.Client/EntityRenderDispatcher.cpp @@ -85,6 +85,8 @@ #include "ArmorStandRenderer.h" #include "EndermiteRenderer.h" +#include "GuardianRenderer.h" +#include "GuardianModel.h" #include "MobRenderer.h" double EntityRenderDispatcher::xOff = 0.0; @@ -128,6 +130,9 @@ EntityRenderDispatcher::EntityRenderDispatcher() renderers[eTYPE_VILLAGER] = new VillagerRenderer(); renderers[eTYPE_VILLAGERGOLEM] = new VillagerGolemRenderer(); renderers[eTYPE_BAT] = new BatRenderer(); + renderers[eTYPE_GUARDIAN] = new GuardianRenderer(new GuardianModel(), 0.5f); + renderers[eTYPE_ELDER_GUARDIAN] = new GuardianRenderer(new GuardianModel(), 0.5f); + renderers[eTYPE_MOB] = new MobRenderer(new HumanoidModel(), 0.5f); diff --git a/Minecraft.Client/EntityRenderer.cpp b/Minecraft.Client/EntityRenderer.cpp index 6d1d15b2..22698db3 100644 --- a/Minecraft.Client/EntityRenderer.cpp +++ b/Minecraft.Client/EntityRenderer.cpp @@ -407,6 +407,7 @@ void EntityRenderer::registerTerrainTextures(IconRegister *iconRegister) { } + ResourceLocation *EntityRenderer::getTextureLocation(shared_ptr mob) { return nullptr; diff --git a/Minecraft.Client/EntityRenderer.h b/Minecraft.Client/EntityRenderer.h index 02208f32..0445fe1e 100644 --- a/Minecraft.Client/EntityRenderer.h +++ b/Minecraft.Client/EntityRenderer.h @@ -75,4 +75,6 @@ public: virtual Model *getNewModel() { return newModel; } virtual Model *getNewModelSlim() { return newModelSlim; } virtual void SetItemFrame(bool bSet) {} + virtual bool shouldRender(shared_ptr entity, float camX, float camY, float camZ) { return true; } + }; diff --git a/Minecraft.Client/GuardianModel.cpp b/Minecraft.Client/GuardianModel.cpp new file mode 100644 index 00000000..61612d83 --- /dev/null +++ b/Minecraft.Client/GuardianModel.cpp @@ -0,0 +1,147 @@ +#include "stdafx.h" +#include "GuardianModel.h" +#include "..\Minecraft.World\Mth.h" +#include "ModelPart.h" +#include "..\Minecraft.World\Guardian.h" + + + +GuardianModel::GuardianModel() : Model() +{ + texWidth = 64; + texHeight = 64; + + + guardianBody = new ModelPart(this); + guardianBody->texOffs(0, 0)->addBox(-6.0f, 10.0f, -8.0f, 12, 12, 16); + guardianBody->texOffs(0, 28)->addBox(-8.0f, 10.0f, -6.0f, 2, 12, 12); + + + ModelPart *rightSide = new ModelPart(this); + rightSide->texOffs(0, 28)->mirror()->addBox(6.0f, 10.0f, -6.0f, 2, 12, 12); + guardianBody->addChild(rightSide); + + guardianBody->texOffs(16, 40)->addBox(-6.0f, 8.0f, -6.0f, 12, 2, 12); + guardianBody->texOffs(16, 40)->addBox(-6.0f, 22.0f, -6.0f, 12, 2, 12); + + + for (int i = 0; i < 12; i++) + { + guardianSpines[i] = new ModelPart(this, 0, 0); + guardianSpines[i]->addBox(-1.0f, -4.5f, -1.0f, 2, 9, 2); + guardianBody->addChild(guardianSpines[i]); + } + + + guardianEye = new ModelPart(this, 8, 0); + guardianEye->addBox(-1.0f, 15.0f, 0.0f, 2, 2, 1); + guardianBody->addChild(guardianEye); + + + guardianTail[0] = new ModelPart(this, 40, 0); + guardianTail[0]->addBox(-2.0f, 14.0f, 7.0f, 4, 4, 8); + + guardianTail[1] = new ModelPart(this, 0, 54); + guardianTail[1]->addBox(0.0f, 14.0f, 0.0f, 3, 3, 7); + + guardianTail[2] = new ModelPart(this); + guardianTail[2]->texOffs(41, 32)->addBox(0.0f, 14.0f, 0.0f, 2, 2, 6); + guardianTail[2]->texOffs(25, 19)->addBox(1.0f, 10.5f, 3.0f, 1, 9, 9); + + guardianBody->addChild(guardianTail[0]); + guardianTail[0]->addChild(guardianTail[1]); + guardianTail[1]->addChild(guardianTail[2]); +} + + + +void GuardianModel::setupAnim(float time, float r, float bob, float yRot, float xRot, + float scale, shared_ptr entity, + unsigned int uiBitmaskOverrideAnim) +{ + shared_ptr guardian = dynamic_pointer_cast(entity); + if (!guardian) return; + + + float afloat[] = { 1.75f, 0.25f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 1.25f, 0.75f, 0.0f, 0.0f }; + float afloat1[] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.25f,1.75f, 1.25f, 0.75f, 0.0f, 0.0f, 0.0f, 0.0f }; + float afloat2[] = { 0.0f, 0.0f, 0.25f,1.75f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f,1.25f}; + float afloat3[] = { 0.0f, 0.0f, 8.0f, -8.0f,-8.0f, 8.0f, 8.0f, -8.0f, 0.0f, 0.0f, 8.0f,-8.0f }; + float afloat4[] = {-8.0f, -8.0f, -8.0f, -8.0f, 0.0f, 0.0f, 0.0f, 0.0f, 8.0f, 8.0f, 8.0f, 8.0f }; + float afloat5[] = { 8.0f, -8.0f, 0.0f, 0.0f,-8.0f,-8.0f, 8.0f, 8.0f, 8.0f, -8.0f, 0.0f, 0.0f }; + + // Body orientation + guardianBody->yRot = yRot / (180.0f / (float)PI); + guardianBody->xRot = xRot / (180.0f / (float)PI); + + + guardianEye->z = -8.25f; + + if (guardian->hasTargetedEntity()) + { + shared_ptr target = guardian->getTargetedEntity(); + if (target) + { + + double d0 = (guardian->y + guardian->getEyeHeight()) + - (target->y + target->getEyeHeight()); + guardianEye->y = (d0 > 0.0) ? 0.0f : 1.0f; + + + double dx = target->x - guardian->x; + double dz = target->z - guardian->z; + float targetYaw = (float)(atan2(dz, dx) * 180.0 / PI) - 90.0f; + float diff = Mth::wrapDegrees(targetYaw - guardian->yRot); + + float clamped = diff / 45.0f; + if (clamped < -2.0f) clamped = -2.0f; + if (clamped > 2.0f) clamped = 2.0f; + guardianEye->x = clamped; + } + } + else + { + guardianEye->y = 0.0f; + guardianEye->x = 0.0f; + } + + + float f1 = (1.0f - guardian->getSpikesAnimation(0.0f)) * 0.55f; + + for (int i = 0; i < 12; ++i) + { + guardianSpines[i]->xRot = (float)PI * afloat[i]; + guardianSpines[i]->yRot = (float)PI * afloat1[i]; + guardianSpines[i]->zRot = (float)PI * afloat2[i]; + + float wave = 1.0f + Mth::cos(bob * 1.5f + (float)i) * 0.01f - f1; + guardianSpines[i]->x = afloat3[i] * wave; + guardianSpines[i]->y = 16.0f + afloat4[i] * wave; + guardianSpines[i]->z = afloat5[i] * wave; + } + + + float tailAnim = guardian->getTailAnimation(0.0f); + + guardianTail[0]->yRot = Mth::sin(tailAnim) * (float)PI * 0.05f; + + guardianTail[1]->yRot = Mth::sin(tailAnim) * (float)PI * 0.1f; + guardianTail[1]->x = -1.5f; + guardianTail[1]->y = 0.5f; + guardianTail[1]->z = 14.0f; + + guardianTail[2]->yRot = Mth::sin(tailAnim) * (float)PI * 0.15f; + guardianTail[2]->x = 0.5f; + guardianTail[2]->y = 0.5f; + guardianTail[2]->z = 6.0f; +} + + + +void GuardianModel::render(shared_ptr entity, float time, float r, float bob, + float yRot, float xRot, float scale, bool usecompiled) +{ + setupAnim(time, r, bob, yRot, xRot, scale, entity); + + guardianBody->render(scale, usecompiled); +} \ No newline at end of file diff --git a/Minecraft.Client/GuardianModel.h b/Minecraft.Client/GuardianModel.h new file mode 100644 index 00000000..24170885 --- /dev/null +++ b/Minecraft.Client/GuardianModel.h @@ -0,0 +1,25 @@ +#pragma once +#include "Model.h" + +class ModelPart; + +class GuardianModel : public Model +{ +public: + ModelPart *guardianBody; + ModelPart *guardianEye; + ModelPart *guardianSpines[12]; + ModelPart *guardianTail[3]; + + GuardianModel(); + + + int getTextureHeight() { return 64; } + + virtual void setupAnim(float time, float r, float bob, float yRot, float xRot, + float scale, shared_ptr entity, + unsigned int uiBitmaskOverrideAnim = 0) override; + + virtual void render(shared_ptr entity, float time, float r, float bob, + float yRot, float xRot, float scale, bool usecompiled) override; +}; \ No newline at end of file diff --git a/Minecraft.Client/GuardianRenderer.cpp b/Minecraft.Client/GuardianRenderer.cpp new file mode 100644 index 00000000..e6174792 --- /dev/null +++ b/Minecraft.Client/GuardianRenderer.cpp @@ -0,0 +1,239 @@ +#include "stdafx.h" +#include "GuardianRenderer.h" +#include "GuardianModel.h" +#include "..\Minecraft.World\Mth.h" +#include "..\Minecraft.World\net.minecraft.world.entity.animal.h" +#include "../Minecraft.World/Guardian.h" +#include "..\Minecraft.World\Level.h" +#include "Tesselator.h" + + + +ResourceLocation GuardianRenderer::GUARDIAN_LOCATION = ResourceLocation(TN_MOB_GUARDIAN); +ResourceLocation GuardianRenderer::GUARDIAN_ELDER_LOCATION = ResourceLocation(TN_MOB_GUARDIAN_ELDER); +ResourceLocation GuardianRenderer::GUARDIAN_BEAM_LOCATION = ResourceLocation(TN_MOB_GUARDIAN_BEAM); + +GuardianRenderer::GuardianRenderer(Model *model, float shadow) + : MobRenderer(model, shadow) +{ + guardianModel = static_cast(model); +} + + + + +ResourceLocation *GuardianRenderer::getTextureLocation(shared_ptr mob) +{ + shared_ptr guardian = dynamic_pointer_cast(mob); + if (guardian && guardian->isElder()) + return &GUARDIAN_ELDER_LOCATION; + return &GUARDIAN_LOCATION; +} + + + + + + + +bool GuardianRenderer::shouldRender(shared_ptr mob, float camX, float camY, float camZ) +{ + if (MobRenderer::shouldRender(mob, camX, camY, camZ)) + return true; + + shared_ptr guardian = dynamic_pointer_cast(mob); + if (!guardian || !guardian->hasTargetedEntity()) + return false; + + shared_ptr target = guardian->getTargetedEntity(); + if (!target) + return false; + + double tx, ty, tz, gx, gy, gz; + getInterpolatedPos(target, (double)target->bbHeight * 0.5, 1.0f, tx, ty, tz); + getInterpolatedPos(guardian, (double)guardian->getEyeHeight(), 1.0f, gx, gy, gz); + + + auto inRange = [&](double x, double y, double z) { + double dx = x - camX, dy = y - camY, dz = z - camZ; + return (dx*dx + dy*dy + dz*dz) < (64.0 * 64.0); + }; + + return inRange(gx, gy, gz) || inRange(tx, ty, tz); +} + + + +void GuardianRenderer::getInterpolatedPos(shared_ptr entity, double yOffset, + float partialTicks, + double &outX, double &outY, double &outZ) +{ + outX = entity->xo + (entity->x - entity->xo) * (double)partialTicks; + outY = yOffset + entity->yo + (entity->y - entity->yo) * (double)partialTicks; + outZ = entity->zo + (entity->z - entity->zo) * (double)partialTicks; +} + + + +void GuardianRenderer::setupRotations(shared_ptr _mob, float bob, + float bodyRot, float a) +{ + shared_ptr mob = dynamic_pointer_cast(_mob); + float bodyXRot = mob->xBodyRotO + (mob->xBodyRot - mob->xBodyRotO) * a; + + + glTranslatef(0, 1.2f, 0); + glRotatef(180.0f - bodyRot, 0, 1, 0); + glRotatef(bodyXRot, 1, 0, 0); + glTranslatef(0, -1.2f, 0); +} + + + +void GuardianRenderer::render(shared_ptr _mob, double x, double y, double z, + float rot, float a) +{ + + MobRenderer::render(_mob, x, y, z, rot, a); + + shared_ptr mob = dynamic_pointer_cast(_mob); + if (!mob || !mob->hasTargetedEntity()) return; + + shared_ptr target = mob->level->getEntity(mob->getTargetedEntityId()); + if (!target) { + target = mob->level->getNearestPlayer(mob->x, mob->y, mob->z, 64.0); + if (!target || target->entityId != mob->getTargetedEntityId()) return; + } + + + float f = mob->getAttackAnimationScale(a); + float time = (float)mob->tickCount + a; + float texVOff = -time * 0.2f - floor(-time * 0.1f); + float eyeHeight = mob->getEyeHeight(); + if (mob && mob->isElder()) + eyeHeight = mob->bbHeight * 0.5f * 2.35f; + + + double targetX = target->xo + (target->x - target->xo) * a; + double targetZ = target->zo + (target->z - target->zo) * a; + + double targetYBase = target->yo + (target->y - target->yo) * a; + double targetY = targetYBase - (target->bbHeight * 0.5f); + + + + double mobX = mob->xo + (mob->x - mob->xo) * a; + double mobY = mob->yo + (mob->y - mob->yo) * a + eyeHeight; + double mobZ = mob->zo + (mob->z - mob->zo) * a; + + double dx = targetX - mobX; + double dy = targetY - mobY; + double dz = targetZ - mobZ; + + double distOrizzontale = sqrt(dx * dx + dz * dz); + double distanzaTotale = sqrt(dx * dx + dy * dy + dz * dz); + + + bindTexture(&GUARDIAN_BEAM_LOCATION); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); + + glPushMatrix(); + glTranslatef((float)x, (float)y + eyeHeight, (float)z); + + + glRotatef((float)(atan2(dx, dz) * 180.0 / PI), 0, 1, 0); + glRotatef((float)(-atan2(dy, distOrizzontale) * 180.0 / PI), 1, 0, 0); + + Tesselator* t = Tesselator::getInstance(); + + + double r1 = 0.2; + double r2 = r1 * 1.41; + + double rotBeam = time * 0.05 * (1.0 - 2.5); + float f7 = f * f; + int red = (int)fmin(255, 64 + (int)(f7 * 240.0f)); + int green = (int)fmin(255, 32 + (int)(f7 * 192.0f)); + int blue = (int)fmax(0, fmin(255, 128 - (int)(f7 * 64.0f))); + + double vMin = 0.0 + texVOff; + double vMax = distanzaTotale * (0.5 / r1) + texVOff; + + + double d12 = cos(rotBeam + PI) * r1; + double d13 = sin(rotBeam + PI) * r1; + double d14 = cos(rotBeam + 0.0) * r1; + double d15 = sin(rotBeam + 0.0) * r1; + double d16 = cos(rotBeam + (PI / 2.0)) * r1; + double d17 = sin(rotBeam + (PI / 2.0)) * r1; + double d18 = cos(rotBeam + (PI * 3.0 / 2.0)) * r1; + double d19 = sin(rotBeam + (PI * 3.0 / 2.0)) * r1; + + + t->begin(); + t->color(red, green, blue, 255); + t->vertexUV(d12, d13, distanzaTotale, 0.4999, vMax); + t->vertexUV(d12, d13, 0.0, 0.4999, vMin); + t->vertexUV(d14, d15, 0.0, 0.0, vMin); + t->vertexUV(d14, d15, distanzaTotale, 0.0, vMax); + t->vertexUV(d16, d17, distanzaTotale, 0.4999, vMax); + t->vertexUV(d16, d17, 0.0, 0.4999, vMin); + t->vertexUV(d18, d19, 0.0, 0.0, vMin); + t->vertexUV(d18, d19, distanzaTotale, 0.0, vMax); + t->end(); + + + glDepthMask(false); + double d24 = (mob->tickCount % 2 == 0) ? 0.5 : 0.0; + + t->begin(); + t->color(red, green, blue, 64); + + double g1 = cos(rotBeam + 2.356) * r2; + double g2 = sin(rotBeam + 2.356) * r2; + double g3 = cos(rotBeam + 0.785) * r2; + double g4 = sin(rotBeam + 0.785) * r2; + double g5 = cos(rotBeam + 3.926) * r2; + double g6 = sin(rotBeam + 3.926) * r2; + double g7 = cos(rotBeam + 5.497) * r2; + double g8 = sin(rotBeam + 5.497) * r2; + + t->vertexUV(g1, g2, distanzaTotale, 0.5, d24 + 0.5); + t->vertexUV(g1, g2, 0.0, 0.5, d24); + t->vertexUV(g3, g4, 0.0, 1.0, d24); + t->vertexUV(g3, g4, distanzaTotale, 1.0, d24 + 0.5); + t->vertexUV(g7, g8, distanzaTotale, 1.0, d24 + 0.5); + t->vertexUV(g7, g8, 0.0, 1.0, d24); + t->vertexUV(g5, g6, 0.0, 0.5, d24); + t->vertexUV(g5, g6, distanzaTotale, 0.5, d24 + 0.5); + t->end(); + + glDepthMask(true); + glDisable(GL_BLEND); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + glPopMatrix(); +} + +void GuardianRenderer::renderModel(shared_ptr mob, float wp, float ws, float bob, + float headRotMinusBodyRot, float headRotx, float scale) +{ + shared_ptr guardian = dynamic_pointer_cast(mob); + if (guardian && guardian->isElder()) + { + glPushMatrix(); + + glTranslatef(0.0f, -2.0f, 0.0f); + glScalef(2.35f, 2.35f, 2.35f); + LivingEntityRenderer::renderModel(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale); + glPopMatrix(); + } + else + { + LivingEntityRenderer::renderModel(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale); + } +} \ No newline at end of file diff --git a/Minecraft.Client/GuardianRenderer.h b/Minecraft.Client/GuardianRenderer.h new file mode 100644 index 00000000..3b09d738 --- /dev/null +++ b/Minecraft.Client/GuardianRenderer.h @@ -0,0 +1,42 @@ +#pragma once +#include "MobRenderer.h" + +class GuardianModel; + +class GuardianRenderer : public MobRenderer +{ +private: + GuardianModel *guardianModel; + + static ResourceLocation GUARDIAN_LOCATION; + static ResourceLocation GUARDIAN_ELDER_LOCATION; + static ResourceLocation GUARDIAN_BEAM_LOCATION; + + + void getInterpolatedPos(shared_ptr entity, double yOffset, + float partialTicks, + double &outX, double &outY, double &outZ); + +public: + GuardianRenderer(Model *model, float shadow); + + + + +virtual bool shouldRender(shared_ptr mob, float camX, float camY, float camZ) override; + + virtual void render(shared_ptr mob, double x, double y, double z, + float rot, float a) override; + +protected: + + + + virtual void setupRotations(shared_ptr mob, float bob, + float bodyRot, float a) override; + + + virtual void renderModel(shared_ptr mob, float wp, float ws, float bob, + float headRotMinusBodyRot, float headRotx, float scale) override; + virtual ResourceLocation *getTextureLocation(shared_ptr mob) override; +}; \ No newline at end of file diff --git a/Minecraft.Client/MobRenderer.cpp b/Minecraft.Client/MobRenderer.cpp index 7e1e3d85..7b841d3b 100644 --- a/Minecraft.Client/MobRenderer.cpp +++ b/Minecraft.Client/MobRenderer.cpp @@ -31,6 +31,17 @@ void MobRenderer::render(shared_ptr _mob, double x, double y, double z, renderLeash(mob, x, y, z, rot, a); } + +bool MobRenderer::shouldRender(shared_ptr entity, float camX, float camY, float camZ) +{ + + double dx = entity->x - camX; + double dy = entity->y - camY; + double dz = entity->z - camZ; + double distSq = dx*dx + dy*dy + dz*dz; + return entity->shouldRenderAtSqrDistance(distSq); +} + bool MobRenderer::shouldShowName(shared_ptr mob) { return LivingEntityRenderer::shouldShowName(mob) && (mob->shouldShowName() || dynamic_pointer_cast(mob)->hasCustomName()); diff --git a/Minecraft.Client/MobRenderer.h b/Minecraft.Client/MobRenderer.h index 6ab4af0c..798fc964 100644 --- a/Minecraft.Client/MobRenderer.h +++ b/Minecraft.Client/MobRenderer.h @@ -14,6 +14,7 @@ class MobRenderer : public LivingEntityRenderer public: MobRenderer(Model *model, float shadow); virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); + virtual bool shouldRender(shared_ptr entity, float camX, float camY, float camZ) override; protected: virtual bool shouldShowName(shared_ptr mob); diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index 6f0adf67..950e6a5b 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -191,6 +191,9 @@ const wchar_t *Textures::preLoaded[TN_COUNT] = L"mob/endermite", + L"mob/guardian", + L"mob/guardian_elder", + L"mob/guardian_beam", #ifdef _LARGE_WORLDS L"misc/additionalmapicons", diff --git a/Minecraft.Client/Textures.h b/Minecraft.Client/Textures.h index 0cbe036b..5f08fe57 100644 --- a/Minecraft.Client/Textures.h +++ b/Minecraft.Client/Textures.h @@ -177,6 +177,9 @@ typedef enum _TEXTURE_NAME TN_MOB_ENDERMITE, + TN_MOB_GUARDIAN, + TN_MOB_GUARDIAN_ELDER, + TN_MOB_GUARDIAN_BEAM, #ifdef _LARGE_WORLDS diff --git a/Minecraft.Client/cmake/sources/Common.cmake b/Minecraft.Client/cmake/sources/Common.cmake index 5f78d3a2..b5024e9a 100644 --- a/Minecraft.Client/cmake/sources/Common.cmake +++ b/Minecraft.Client/cmake/sources/Common.cmake @@ -622,6 +622,8 @@ set(_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_MODEL "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStandModel.h" "${CMAKE_CURRENT_SOURCE_DIR}/EndermiteModel.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/EndermiteModel.h" + "${CMAKE_CURRENT_SOURCE_DIR}/GuardianModel.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/GuardianModel.h" ) source_group("net/minecraft/client/model" FILES ${_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_MODEL}) @@ -899,6 +901,8 @@ set(_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_RENDERER_ENTITY "${CMAKE_CURRENT_SOURCE_DIR}/RabbitRenderer.h" "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStandRenderer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/EndermiteRenderer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/GuardianRenderer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/GuardianRenderer.h" ) source_group("net/minecraft/client/renderer/entity" FILES ${_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_RENDERER_ENTITY}) diff --git a/Minecraft.Client/glWrapper.cpp b/Minecraft.Client/glWrapper.cpp index c49620aa..e447d32b 100644 --- a/Minecraft.Client/glWrapper.cpp +++ b/Minecraft.Client/glWrapper.cpp @@ -389,4 +389,9 @@ void glTexGen(int coord, int mode, FloatBuffer *vec) void glCullFace(int dir) { RenderManager.StateSetFaceCullCW( dir == GL_BACK); -} \ No newline at end of file +} + +void glTexParameterf(int target, int param, float value) +{ + RenderManager.TextureSetParam(param, (int)value); +} diff --git a/Minecraft.Client/stubs.h b/Minecraft.Client/stubs.h index 10ba2d05..60aa4885 100644 --- a/Minecraft.Client/stubs.h +++ b/Minecraft.Client/stubs.h @@ -114,7 +114,7 @@ void glFogf(int,float); void glFog(int,FloatBuffer *); void glColorMaterial(int,int); void glMultiTexCoord2f(int, float, float); - +void glTexParameterf(int target, int param, float value); //1.8.2 void glClientActiveTexture(int); void glActiveTexture(int); diff --git a/Minecraft.World/Class.h b/Minecraft.World/Class.h index b4ac588b..058cffd9 100644 --- a/Minecraft.World/Class.h +++ b/Minecraft.World/Class.h @@ -168,9 +168,11 @@ enum eINSTANCEOF eTYPE_BLAZE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x6, eTYPE_WITCH = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x7, eTYPE_WITHERBOSS = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x8, + eTYPE_GUARDIAN = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x9, eTYPE_ENDERMITE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x10, + eTYPE_ELDER_GUARDIAN = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x11, eTYPE_AMBIENT = eTYPE_MOB | BIT_AMBIENT_MOB, diff --git a/Minecraft.World/EntityIO.cpp b/Minecraft.World/EntityIO.cpp index 7b67d8fe..3d5eec44 100644 --- a/Minecraft.World/EntityIO.cpp +++ b/Minecraft.World/EntityIO.cpp @@ -46,7 +46,7 @@ void EntityIO::staticCtor() { setId(ItemEntity::create, eTYPE_ITEMENTITY, L"Item", 1); setId(ExperienceOrb::create, eTYPE_EXPERIENCEORB, L"XPOrb", 2); - + setId(Guardian::create, eTYPE_ELDER_GUARDIAN, L"ElderGuardian", 4, eMinecraftColour_Armour_Default_Leather_Colour, eMinecraftColour_Sky_IceMountains, IDS_PIGZOMBIE); setId(LeashFenceKnotEntity::create, eTYPE_LEASHFENCEKNOT, L"LeashKnot", 8); setId(Painting::create, eTYPE_PAINTING, L"Painting", 9); setId(Arrow::create, eTYPE_ARROW, L"Arrow", 10); @@ -95,6 +95,12 @@ void EntityIO::staticCtor() setId(WitherBoss::create, eTYPE_WITHERBOSS, L"WitherBoss", 64); setId(Bat::create, eTYPE_BAT, L"Bat", 65, eMinecraftColour_Mob_Bat_Colour1, eMinecraftColour_Mob_Bat_Colour2, IDS_BAT); setId(Witch::create, eTYPE_WITCH, L"Witch", 66, eMinecraftColour_Mob_Witch_Colour1, eMinecraftColour_Mob_Witch_Colour2, IDS_WITCH); + + setId(Endermite::create, eTYPE_ENDERMITE, L"Endermite", 67, + eMinecraftColour_Mob_Endermite_Colour1, + eMinecraftColour_Mob_Endermite_Colour2, IDS_ENDERMITE); + + setId(Guardian::create, eTYPE_GUARDIAN, L"Guardian", 68, eMinecraftColour_Mob_Witch_Colour1, eMinecraftColour_Mob_Witch_Colour2, IDS_WITCH); setId(Pig::create, eTYPE_PIG, L"Pig", 90, eMinecraftColour_Mob_Pig_Colour1, eMinecraftColour_Mob_Pig_Colour2, IDS_PIG); @@ -114,9 +120,7 @@ void EntityIO::staticCtor() setId(ArmorStand::create, eTYPE_ARMORSTAND, L"ArmorStand", 102); - setId(Endermite::create, eTYPE_ENDERMITE, L"Endermite", 67, - eMinecraftColour_Mob_Endermite_Colour1, - eMinecraftColour_Mob_Endermite_Colour2, IDS_ENDERMITE);//change IDS_Endermite later + //change IDS_Endermite later setId(Villager::create, eTYPE_VILLAGER, L"Villager", 120, eMinecraftColour_Mob_Villager_Colour1, eMinecraftColour_Mob_Villager_Colour2, IDS_VILLAGER); diff --git a/Minecraft.World/Guardian.cpp b/Minecraft.World/Guardian.cpp new file mode 100644 index 00000000..d44644e5 --- /dev/null +++ b/Minecraft.World/Guardian.cpp @@ -0,0 +1,480 @@ +#include "stdafx.h" +#include "com.mojang.nbt.h" +#include "net.minecraft.world.level.tile.h" +#include "net.minecraft.world.phys.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.entity.h" +#include "net.minecraft.world.entity.player.h" +#include "net.minecraft.world.entity.ai.attributes.h" +#include "net.minecraft.world.entity.monster.h" +#include "net.minecraft.world.damagesource.h" +#include "SharedConstants.h" +#include "Guardian.h" +#include "..\Minecraft.Client\Textures.h" +#include "..\Minecraft.World\Mth.h" +#include "..\Minecraft.World\net.minecraft.world.entity.animal.h" +#include "MobEffect.h" +#include "MobEffectInstance.h" + + +void Guardian::_init() +{ + clientSideTailAnimation = 0.0f; + clientSideTailAnimationO = 0.0f; + clientSideSpikesAnimation = 0.0f; + clientSideSpikesAnimationO = 0.0f; + clientSideAttackTime = 0.0f; + clientSideTouchedGround = false; + + xBodyRot = xBodyRotO = 0.0f; + zBodyRot = zBodyRotO = 0.0f; + + tx = ty = tz = 0.0f; + attackTimer = 0; +} + +Guardian::Guardian(Level *level) : WaterAnimal(level) +{ + this->defineSynchedData(); + registerAttributes(); + setHealth(getMaxHealth()); + _init(); + if (isElder()) { + this->setSize(1.9975f, 1.9975f); + } + else { + this->setSize(0.85f, 0.85f); + } +} + + + +void Guardian::registerAttributes() +{ + WaterAnimal::registerAttributes(); + getAttributes()->registerAttribute(SharedMonsterAttributes::ATTACK_DAMAGE); + getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6.0); + getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.5); + getAttribute(SharedMonsterAttributes::FOLLOW_RANGE)->setBaseValue(16.0); + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(30.0); +} + + + +void Guardian::defineSynchedData() +{ + WaterAnimal::defineSynchedData(); + entityData->define(16, (byte)0); + entityData->define(17, 0); +} + + +// NBT + + +void Guardian::readAdditionalSaveData(CompoundTag *tag) +{ + WaterAnimal::readAdditionalSaveData(tag); + setElder(tag->getBoolean(L"Elder")); +} + +void Guardian::addAdditonalSaveData(CompoundTag *tag) +{ + WaterAnimal::addAdditonalSaveData(tag); + tag->putBoolean(L"Elder", isElder()); +} + + + +bool Guardian::isElder() +{ + return (entityData->getByte(16) & 4) != 0; +} + +void Guardian::setElder(bool elder) +{ + byte flags = entityData->getByte(16); + if (elder) + { + entityData->set(16, (byte)(flags | 4)); + + + this->setSize(1.9975f, 1.9975f); + getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.30000001192092896); + getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(8.0); + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(80.0); + setHealth(getMaxHealth()); + } + else + { + entityData->set(16, (byte)(flags & ~4)); + this->setSize(0.85f, 0.85f); + } +} + + +void Guardian::setElderClient() +{ + setElder(true); + clientSideSpikesAnimation = clientSideSpikesAnimationO = 1.0f; +} + +bool Guardian::isMoving() +{ + return (entityData->getByte(16) & 2) != 0; +} + +void Guardian::setMoving(bool moving) +{ + byte flags = entityData->getByte(16); + if (moving) + entityData->set(16, (byte)(flags | 2)); + else + entityData->set(16, (byte)(flags & ~2)); +} + + + +int Guardian::getTargetedEntityId() +{ + return entityData->getInteger(17); +} + +void Guardian::setTargetedEntityId(int id) +{ + entityData->set(17, id); + entityData->markDirty(17); +} + +bool Guardian::hasTargetedEntity() +{ + return entityData->getInteger(17) != 0; +} + +shared_ptr Guardian::getTargetedEntity() +{ + if (!hasTargetedEntity()) + return nullptr; + + if (level->isClientSide) + { + if (targetedEntity != nullptr) + return targetedEntity; + + shared_ptr entity = level->getEntity(getTargetedEntityId()); + if (entity != nullptr && dynamic_pointer_cast(entity)) + { + targetedEntity = dynamic_pointer_cast(entity); + return targetedEntity; + } + return nullptr; + } + + shared_ptr e = level->getEntity(getTargetedEntityId()); + return dynamic_pointer_cast(e); +} + + + +int Guardian::getAttackDuration() +{ + // Java func_175464_ck + return isElder() ? 60 : 80; +} + +float Guardian::getAttackAnimationScale(float partialTicks) +{ + return (clientSideAttackTime + partialTicks) / (float)getAttackDuration(); +} + +// Java func_175471_a +float Guardian::getTailAnimation(float partialTicks) +{ + return clientSideSpikesAnimationO + (clientSideSpikesAnimation - clientSideSpikesAnimationO) * partialTicks; +} + +// Java func_175469_o +float Guardian::getSpikesAnimation(float partialTicks) +{ + return isMoving() ? 1.0f : 0.0f; +} + + + +int Guardian::getAmbientSound() { return -1; } +int Guardian::getHurtSound() { return -1; } +int Guardian::getDeathSound() { return -1; } +float Guardian::getSoundVolume() { return 1.0f; } +int Guardian::getDeathLoot() { return 0; } +bool Guardian::makeStepSound() { return false; } + +void Guardian::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) +{ + //loot (prismarine, sponge) +} + +float Guardian::getEyeHeight() +{ + return bbHeight * 0.5f; +} + +bool Guardian::isInWater() +{ + return level->checkAndHandleWater(bb->grow(0, -0.6f, 0), Material::water, shared_from_this()); +} + +float Guardian::rotlerp(float a, float b, float max) +{ + float f = Mth::wrapDegrees(b - a); + if (f > max) f = max; + if (f < -max) f = -max; + return a + f; +} + +void Guardian::lookAt(shared_ptr e, float yMax, float xMax) +{ + double d0 = e->x - x; + double d1 = e->z - z; + double d2; + + if (dynamic_pointer_cast(e)) + { + shared_ptr living = dynamic_pointer_cast(e); + d2 = living->y + living->getEyeHeight() - (y + getEyeHeight()); + } + else + { + d2 = (e->bb->y0 + e->bb->y1) / 2.0 - (y + getEyeHeight()); + } + + double d3 = sqrt(d0 * d0 + d1 * d1); + float f = (float)(atan2(d1, d0) * 180.0 / PI) - 90.0f; + float f1 = (float)(-(atan2(d2, d3) * 180.0 / PI)); + xRot = rotlerp(xRot, f1, xMax); + yRot = rotlerp(yRot, f, yMax); +} + + + +void Guardian::serverAiStep() +{ + WaterAnimal::serverAiStep(); + + if (isElder() && !level->isClientSide) + { + if (((tickCount + entityId) % 1200 == 0)) + { + auto& players = level->players; + for (int i = 0; i < (int)players.size(); i++) + { + shared_ptr player = players[i]; + if (!player) continue; + + if (distanceToSqr(player) >= 2500.0) + continue; + + if (player->abilities.invulnerable) + continue; + + + MobEffectInstance *existing = player->getEffect(MobEffect::digSlowdown); + if (existing == nullptr || existing->getAmplifier() < 2 || existing->getDuration() < 1200) + { + player->addEffect(new MobEffectInstance(MobEffect::digSlowdown->id, 6000, 2)); + } + } + } + } + + + if (!hasTargetedEntity()) + { + shared_ptr nearest = level->getNearestPlayer(x, y, z, 16.0); + if (nearest != nullptr && canSee(nearest) && !nearest->abilities.invulnerable) + { + setTargetedEntityId(nearest->entityId); + attackTimer = 0; + } + } + + shared_ptr target = getTargetedEntity(); + if (target != nullptr) + { + if (!target->isAlive() || distanceToSqr(target) > 256.0 || !canSee(target)) + { + setTargetedEntityId(0); + target = nullptr; + } + } + + if (target != nullptr) + { + lookAt(target, 90.0f, 90.0f); + setMoving(false); + tx = ty = tz = 0.0f; + + attackTimer++; + + + if (attackTimer == 1) + { + level->broadcastEntityEvent(shared_from_this(), 21); + } + else if (attackTimer >= getAttackDuration()) + { + + float dmg = 1.0f; + if (isElder()) dmg += 2.0f; + + target->hurt(DamageSource::mobAttack(dynamic_pointer_cast(shared_from_this())), dmg); + target->hurt(DamageSource::magic, + (float)getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->getValue()); + + setTargetedEntityId(0); + attackTimer = 0; + } + } + else + { + + attackTimer = 0; + setTargetedEntityId(0); + + noActionTime++; + if (noActionTime > 100 || random->nextInt(50) == 0 || + (tx == 0.0f && ty == 0.0f && tz == 0.0f)) + { + float angle = random->nextFloat() * (float)PI * 2.0f; + tx = Mth::cos(angle) * 0.2f; + ty = -0.1f + random->nextFloat() * 0.2f; + tz = Mth::sin(angle) * 0.2f; + noActionTime = 0; + } + + setMoving(true); + } + + + if (isMoving()) + { + xd += (tx - xd) * 0.1f; + yd += (ty - yd) * 0.1f; + zd += (tz - zd) * 0.1f; + + double horizontalMovement = sqrt(xd * xd + zd * zd); + yBodyRot += ((-static_cast(atan2(xd, zd)) * 180.0f / (float)PI) - yBodyRot) * 0.1f; + yRot = yBodyRot; + zBodyRot = zBodyRot + (float)PI * 0.05f; + xBodyRot += ((-static_cast(atan2(horizontalMovement, yd)) * 180.0f / (float)PI) - xBodyRot) * 0.1f; + } +} + + + +void Guardian::aiStep() +{ + if (level->isClientSide) + { + clientSideTailAnimationO = clientSideTailAnimation; + + if (!isInWater()) + { + clientSideTailAnimation = 2.0f; + clientSideTouchedGround = yd < 0.0 && + level->hasChunkAt(Mth::floor(x), Mth::floor(y - 1), Mth::floor(z)); + } + else if (isMoving()) + { + if (clientSideTailAnimation < 0.5f) + clientSideTailAnimation = 4.0f; + else + clientSideTailAnimation += (0.5f - clientSideTailAnimation) * 0.1f; + } + else + { + clientSideTailAnimation += (0.125f - clientSideTailAnimation) * 0.2f; + } + + clientSideSpikesAnimationO = clientSideSpikesAnimation; + clientSideSpikesAnimation += clientSideTailAnimation; + + if (hasTargetedEntity() && clientSideAttackTime < (float)getAttackDuration()) + clientSideAttackTime++; + else if (!hasTargetedEntity()) + clientSideAttackTime = 0.0f; + } + + + if (isInWater()) + { + setAirSupply(300); + } + else if (onGround) + { + yd += 0.5; + xd += (random->nextFloat() * 2.0f - 1.0f) * 0.4f; + zd += (random->nextFloat() * 2.0f - 1.0f) * 0.4f; + yRot = random->nextFloat() * 360.0f; + onGround = false; + hasImpulse = true; + } + + if (hasTargetedEntity()) + yRot = yHeadRot; + + xBodyRotO = xBodyRot; + zBodyRotO = zBodyRot; + + WaterAnimal::aiStep(); +} + +void Guardian::updateSize(bool elder) +{ + if (elder) + this->setSize(1.9975f, 1.9975f); + else + setSize(0.85f, 0.85f); +} + +void Guardian::travel(float xa, float ya) +{ + if (level->isClientSide) + { + if (isInWater()) + { + move(xd, yd, zd); + xd *= 0.9f; + yd *= 0.9f; + zd *= 0.9f; + } + else + { + WaterAnimal::travel(xa, ya); + } + } + else + { + if (isInWater()) + { + moveRelative(xa, ya, 0.1f); + move(xd, yd, zd); + xd *= 0.9f; + yd *= 0.9f; + zd *= 0.9f; + } + else + { + WaterAnimal::travel(xa, ya); + } + } + +} + +MobGroupData *Guardian::finalizeMobSpawn(MobGroupData *groupData, int extraData) +{ + WaterAnimal::finalizeMobSpawn(groupData, extraData); + if (extraData == 1) + setElder(true); + return groupData; +} \ No newline at end of file diff --git a/Minecraft.World/Guardian.h b/Minecraft.World/Guardian.h new file mode 100644 index 00000000..b03bf7bd --- /dev/null +++ b/Minecraft.World/Guardian.h @@ -0,0 +1,79 @@ +#pragma once +using namespace std; +#include "WaterAnimal.h" + +class Level; +class Player; + +class Guardian : public WaterAnimal +{ +public: + eINSTANCEOF GetType() { return eTYPE_GUARDIAN; } + static Entity *create(Level *level) { return new Guardian(level); } + + void _init(); + + + float clientSideTailAnimation; + float clientSideTailAnimationO; + float clientSideSpikesAnimation; + float clientSideSpikesAnimationO; + float clientSideAttackTime; + bool clientSideTouchedGround; + + + float xBodyRot, xBodyRotO; + float zBodyRot, zBodyRotO; + + Guardian(Level *level); + +protected: + virtual void registerAttributes(); + virtual void defineSynchedData(); + virtual int getAmbientSound(); + virtual int getHurtSound(); + virtual int getDeathSound(); + virtual float getSoundVolume(); + virtual int getDeathLoot(); + virtual bool makeStepSound(); + virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel); + virtual void serverAiStep(); + +public: + virtual bool isInWater(); + virtual void aiStep(); + virtual void travel(float xa, float ya); + virtual void readAdditionalSaveData(CompoundTag *tag); + virtual void addAdditonalSaveData(CompoundTag *tag); + virtual float getEyeHeight(); + void updateSize(bool isElder); + + bool isElder(); + void setElder(bool elder); + void setElderClient(); + + bool isMoving(); + void setMoving(bool moving); + + + int getTargetedEntityId(); + void setTargetedEntityId(int entityId); + bool hasTargetedEntity(); + shared_ptr getTargetedEntity(); + + virtual MobGroupData *finalizeMobSpawn(MobGroupData *groupData, int extraData = 0) override; + int getAttackDuration(); + float getTailAnimation(float partialTicks); + float getSpikesAnimation(float partialTicks); + float getAttackAnimationScale(float partialTicks); + +protected: + void lookAt(shared_ptr e, float yMax, float xMax); + +private: + float rotlerp(float a, float b, float max); + + float tx, ty, tz; + int attackTimer; + shared_ptr targetedEntity; +}; \ No newline at end of file diff --git a/Minecraft.World/LivingEntity.cpp b/Minecraft.World/LivingEntity.cpp index 9d3e7f7b..55931132 100644 --- a/Minecraft.World/LivingEntity.cpp +++ b/Minecraft.World/LivingEntity.cpp @@ -2033,3 +2033,34 @@ bool LivingEntity::isAlliedTo(Team *other) } return false; } + +float LivingEntity::getEyeHeight() +{ + + return getHeadHeight(); +} + +Vec3 *LivingEntity::getPositionEyes(float partialTicks) +{ + if (partialTicks == 1.0f) + { + return Vec3::newTemp(x, y + (double)getEyeHeight(), z); + } + else + { + double d0 = xo + (x - xo) * (double)partialTicks; + double d1 = yo + (y - yo) * (double)partialTicks + (double)getEyeHeight(); + double d2 = zo + (z - zo) * (double)partialTicks; + return Vec3::newTemp(d0, d1, d2); + } +} + +HitResult *LivingEntity::rayTrace(double blockReachDistance, float partialTicks) +{ + Vec3 *vec3 = this->getPositionEyes(partialTicks); + Vec3 *vec31 = this->getViewVector(partialTicks); + Vec3 *vec32 = vec3->add(vec31->x * blockReachDistance, vec31->y * blockReachDistance, vec31->z * blockReachDistance); + + + return this->level->clip(vec3, vec32, false, false); +} \ No newline at end of file diff --git a/Minecraft.World/LivingEntity.h b/Minecraft.World/LivingEntity.h index ecc819df..16541dda 100644 --- a/Minecraft.World/LivingEntity.h +++ b/Minecraft.World/LivingEntity.h @@ -320,4 +320,9 @@ public: virtual Team *getTeam(); virtual bool isAlliedTo(shared_ptr other); virtual bool isAlliedTo(Team *other); + +public: + virtual float getEyeHeight(); + virtual Vec3 *getPositionEyes(float partialTicks); + virtual HitResult *rayTrace(double blockReachDistance, float partialTicks); }; diff --git a/Minecraft.World/OceanMonumentFeature.cpp b/Minecraft.World/OceanMonumentFeature.cpp index dd8d78d4..3d98a84f 100644 --- a/Minecraft.World/OceanMonumentFeature.cpp +++ b/Minecraft.World/OceanMonumentFeature.cpp @@ -6,10 +6,16 @@ #include "Mth.h" #include "LevelData.h" + void OceanMonumentFeature::_init() { spacing = 32; separation = 5; + monumentEnemies.push_back(new Biome::MobSpawnerData(eTYPE_GUARDIAN, 1, 2, 4)); +} +std::vector* OceanMonumentFeature::getMonumentEnemies() +{ + return &monumentEnemies; } OceanMonumentFeature::OceanMonumentFeature() : StructureFeature() { _init(); } diff --git a/Minecraft.World/OceanMonumentFeature.h b/Minecraft.World/OceanMonumentFeature.h index 8cc965e1..d24eebb8 100644 --- a/Minecraft.World/OceanMonumentFeature.h +++ b/Minecraft.World/OceanMonumentFeature.h @@ -14,7 +14,7 @@ class OceanMonumentFeature : public StructureFeature { public: // static void staticCtor(); // Removed, merged into _init - + std::vector monumentEnemies; private: int spacing; int separation; @@ -22,6 +22,7 @@ private: void _init(); public: + vector* getMonumentEnemies(); OceanMonumentFeature(); OceanMonumentFeature(std::unordered_map options); ~OceanMonumentFeature(); @@ -49,4 +50,5 @@ public: }; + }; \ No newline at end of file diff --git a/Minecraft.World/OceanMonumentPieces.cpp b/Minecraft.World/OceanMonumentPieces.cpp index d861b519..8882c073 100644 --- a/Minecraft.World/OceanMonumentPieces.cpp +++ b/Minecraft.World/OceanMonumentPieces.cpp @@ -8,7 +8,8 @@ #include #include #include -#include "Squid.h" + +#include "Guardian.h" @@ -176,18 +177,16 @@ bool OceanMonumentPieces::Piece::intersectsXZ(BoundingBox* chunkBB, int x0, int bool OceanMonumentPieces::Piece::spawnElderGuardian(Level* level, BoundingBox* bb, int x, int y, int z) { - int wx = getWorldX(x, z); int wy = getWorldY(y); int wz = getWorldZ(x, z); if (bb->isInside(wx, wy, wz)) { - Squid *guardian = new Squid(level); - //guardian->setElder(true); + Guardian* guardian = new Guardian(level); + guardian->setElder(true); guardian->heal(guardian->getMaxHealth()); - /*entityguardian.setLocationAndAngles((double)i + 0.5D, (double)j, (double)k + 0.5D, 0.0F, 0.0F); - entityguardian.onInitialSpawn(worldIn.getDifficultyForLocation(new BlockPos(entityguardian)), (IEntityLivingData)null); - worldIn.spawnEntityInWorld(entityguardian);*/ + guardian->setPos((double)wx + 0.5, (double)wy, (double)wz + 0.5); + level->addEntity(shared_ptr(guardian)); return true; } return false; @@ -1080,7 +1079,7 @@ bool OceanMonumentPieces::SimpleTopRoom::postProcess(Level* level, Random* rando if (random->nextInt(3) != 0) { int k = 2 + (random->nextInt(4) == 0 ? 0 : 1); - generateBox(level, chunkBB, i, k, j, i, 3, j, Tile::sponge_Id, 1, false); + generateBox(level, chunkBB, i, k, j, i, 3, j, Tile::sponge_Id, 1, Tile::sponge_Id, 1, false); } } diff --git a/Minecraft.World/RandomLevelSource.cpp b/Minecraft.World/RandomLevelSource.cpp index cc709bae..1a24ad06 100644 --- a/Minecraft.World/RandomLevelSource.cpp +++ b/Minecraft.World/RandomLevelSource.cpp @@ -846,9 +846,16 @@ vector *RandomLevelSource::getMobsAt(MobCategory *mobCa { return nullptr; } - if (mobCategory == MobCategory::monster && scatteredFeature->isSwamphut(x, y, z)) + if (mobCategory == MobCategory::monster) { - return scatteredFeature->getSwamphutEnemies(); + if (scatteredFeature->isSwamphut(x, y, z)) + { + return scatteredFeature->getSwamphutEnemies(); + } + if (oceanMonument->isInsideFeature(x, y, z)) + { + return oceanMonument->getMonumentEnemies(); + } } return biome->getMobs(mobCategory); } diff --git a/Minecraft.World/SpawnEggItem.cpp b/Minecraft.World/SpawnEggItem.cpp index 2fe7b841..a4de941f 100644 --- a/Minecraft.World/SpawnEggItem.cpp +++ b/Minecraft.World/SpawnEggItem.cpp @@ -10,7 +10,8 @@ #include "HitResult.h" #include "SpawnEggItem.h" #include "Difficulty.h" - +#include +#include "AABB.h" SpawnEggItem::SpawnEggItem(int id) : Item(id) { @@ -335,7 +336,19 @@ shared_ptr SpawnEggItem::spawnMobAt(Level *level, int auxVal, double x, mob->yBodyRot = mob->yRot; mob->finalizeMobSpawn(nullptr, extraData); + + + level->addEntity(newEntity); + + if (mobId == 4) + { + shared_ptr g = dynamic_pointer_cast(newEntity); + if (g) + g->setElder(true); + + + } mob->playAmbientSound(); } } diff --git a/Minecraft.World/cmake/sources/Common.cmake b/Minecraft.World/cmake/sources/Common.cmake index 5752df23..61e4e2c0 100644 --- a/Minecraft.World/cmake/sources/Common.cmake +++ b/Minecraft.World/cmake/sources/Common.cmake @@ -781,6 +781,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_ANIMAL "${CMAKE_CURRENT_SOURCE_DIR}/WaterAnimal.h" "${CMAKE_CURRENT_SOURCE_DIR}/Wolf.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Wolf.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Rabbit.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Rabbit.h" "${CMAKE_CURRENT_SOURCE_DIR}/net.minecraft.world.entity.animal.h" ) source_group("net/minecraft/world/entity/animal" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_ANIMAL}) @@ -845,6 +847,9 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_ITEM "${CMAKE_CURRENT_SOURCE_DIR}/MinecartTNT.h" "${CMAKE_CURRENT_SOURCE_DIR}/PrimedTnt.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/PrimedTnt.h" + + "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStand.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStand.h" "${CMAKE_CURRENT_SOURCE_DIR}/net.minecraft.world.entity.item.h" ) source_group("net/minecraft/world/entity/item" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_ITEM}) @@ -885,6 +890,12 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_MONSTER "${CMAKE_CURRENT_SOURCE_DIR}/Witch.h" "${CMAKE_CURRENT_SOURCE_DIR}/Zombie.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Zombie.h" + + "${CMAKE_CURRENT_SOURCE_DIR}/Endermite.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Endermite.h" + + "${CMAKE_CURRENT_SOURCE_DIR}/Guardian.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Guardian.h" "${CMAKE_CURRENT_SOURCE_DIR}/net.minecraft.world.entity.monster.h" ) source_group("net/minecraft/world/entity/monster" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_ENTITY_MONSTER}) @@ -1997,10 +2008,7 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE "${CMAKE_CURRENT_SOURCE_DIR}/SeaLanternTile.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/PrismarineTile.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/TallGrass2.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/Rabbit.cpp" - - "${CMAKE_CURRENT_SOURCE_DIR}/Endermite.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStand.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/FishFoodItem.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ArmorStandItem.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/SavannaTreeFeature.cpp" diff --git a/Minecraft.World/net.minecraft.world.entity.monster.h b/Minecraft.World/net.minecraft.world.entity.monster.h index 1512f1fa..dde56293 100644 --- a/Minecraft.World/net.minecraft.world.entity.monster.h +++ b/Minecraft.World/net.minecraft.world.entity.monster.h @@ -28,3 +28,4 @@ //TU 31 #include "Endermite.h" +#include "Guardian.h"