From eb23fc1a83bdd4a457af03a2e4e65dee32743256 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Sat, 21 Mar 2026 17:37:16 -0500 Subject: [PATCH] TU19: merge Minecraft.World/Util --- Minecraft.World/Util/AABB.cpp | 23 +- Minecraft.World/Util/AABB.h | 3 +- Minecraft.World/Util/ArrayWithLength.h | 1 + Minecraft.World/Util/BasicTypeContainers.cpp | 2 + Minecraft.World/Util/BasicTypeContainers.h | 3 +- Minecraft.World/Util/BoundingBox.cpp | 64 +- Minecraft.World/Util/BoundingBox.h | 4 + Minecraft.World/Util/C4JThread.cpp | 8 +- Minecraft.World/Util/Class.h | 780 ++++++++++++++++--- Minecraft.World/Util/CombatEntry.cpp | 50 ++ Minecraft.World/Util/CombatEntry.h | 30 + Minecraft.World/Util/CombatTracker.cpp | 236 ++++++ Minecraft.World/Util/CombatTracker.h | 55 ++ Minecraft.World/Util/DamageSource.cpp | 107 ++- Minecraft.World/Util/DamageSource.h | 24 +- Minecraft.World/Util/DelayedRelease.cpp | 2 +- Minecraft.World/Util/DelayedRelease.h | 2 +- Minecraft.World/Util/Direction.cpp | 34 +- Minecraft.World/Util/Direction.h | 6 + Minecraft.World/Util/Facing.cpp | 3 + Minecraft.World/Util/Facing.h | 2 + Minecraft.World/Util/FoodConstants.cpp | 1 + Minecraft.World/Util/FoodConstants.h | 1 + Minecraft.World/Util/HashExtension.h | 4 +- Minecraft.World/Util/HitResult.cpp | 4 +- Minecraft.World/Util/HtmlString.cpp | 52 ++ Minecraft.World/Util/HtmlString.h | 17 + Minecraft.World/Util/JavaMath.cpp | 2 +- Minecraft.World/Util/Language.h | 3 +- Minecraft.World/Util/Mth.cpp | 70 +- Minecraft.World/Util/Mth.h | 16 +- Minecraft.World/Util/ParticleTypes.h | 5 +- Minecraft.World/Util/Pos.cpp | 66 +- Minecraft.World/Util/Pos.h | 33 +- Minecraft.World/Util/SharedConstants.cpp | 5 +- Minecraft.World/Util/SharedConstants.h | 6 +- Minecraft.World/Util/SoundTypes.h | 69 +- Minecraft.World/Util/Vec3.cpp | 39 +- Minecraft.World/Util/Vec3.h | 5 +- Minecraft.World/Util/WeighedTreasure.cpp | 2 +- Minecraft.World/Util/WeighedTreasure.h | 3 +- 41 files changed, 1574 insertions(+), 268 deletions(-) create mode 100644 Minecraft.World/Util/CombatEntry.cpp create mode 100644 Minecraft.World/Util/CombatEntry.h create mode 100644 Minecraft.World/Util/CombatTracker.cpp create mode 100644 Minecraft.World/Util/CombatTracker.h create mode 100644 Minecraft.World/Util/HtmlString.cpp create mode 100644 Minecraft.World/Util/HtmlString.h diff --git a/Minecraft.World/Util/AABB.cpp b/Minecraft.World/Util/AABB.cpp index 97e0df198..c4a8bff2e 100644 --- a/Minecraft.World/Util/AABB.cpp +++ b/Minecraft.World/Util/AABB.cpp @@ -107,6 +107,17 @@ AABB* AABB::grow(double xa, double ya, double za) { return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1); } +AABB* AABB::minmax(AABB* other) { + double _x0 = std::min(x0, other->x0); + double _y0 = std::min(y0, other->y0); + double _z0 = std::min(z0, other->z0); + double _x1 = std::max(x1, other->x1); + double _y1 = std::max(y1, other->y1); + double _z1 = std::max(z1, other->z1); + + return newTemp(_x0, _y0, _z0, _x1, _y1, _z1); +} + AABB* AABB::cloneMove(double xa, double ya, double za) { return AABB::newTemp(x0 + xa, y0 + ya, z0 + za, x1 + xa, y1 + ya, z1 + za); } @@ -294,12 +305,12 @@ bool AABB::containsZ(Vec3* v) { } void AABB::set(AABB* b) { - this->x0 = b->x0; - this->y0 = b->y0; - this->z0 = b->z0; - this->x1 = b->x1; - this->y1 = b->y1; - this->z1 = b->z1; + x0 = b->x0; + y0 = b->y0; + z0 = b->z0; + x1 = b->x1; + y1 = b->y1; + z1 = b->z1; } std::wstring AABB::toString() { diff --git a/Minecraft.World/Util/AABB.h b/Minecraft.World/Util/AABB.h index 109ee3674..bcd941f39 100644 --- a/Minecraft.World/Util/AABB.h +++ b/Minecraft.World/Util/AABB.h @@ -44,8 +44,7 @@ public: AABB* set(double x0, double y0, double z0, double x1, double y1, double z1); AABB* expand(double xa, double ya, double za); AABB* grow(double xa, double ya, double za); - -public: + AABB* minmax(AABB* other); AABB* cloneMove(double xa, double ya, double za); double clipXCollide(AABB* c, double xa); double clipYCollide(AABB* c, double ya); diff --git a/Minecraft.World/Util/ArrayWithLength.h b/Minecraft.World/Util/ArrayWithLength.h index e381d08a7..d433329f1 100644 --- a/Minecraft.World/Util/ArrayWithLength.h +++ b/Minecraft.World/Util/ArrayWithLength.h @@ -99,6 +99,7 @@ class Enchantment; class ClipChunk; typedef arrayWithLength doubleArray; +typedef array2DWithLength coords2DArray; typedef arrayWithLength byteArray; typedef arrayWithLength charArray; typedef arrayWithLength shortArray; diff --git a/Minecraft.World/Util/BasicTypeContainers.cpp b/Minecraft.World/Util/BasicTypeContainers.cpp index 9078477ac..8b2966b66 100644 --- a/Minecraft.World/Util/BasicTypeContainers.cpp +++ b/Minecraft.World/Util/BasicTypeContainers.cpp @@ -14,6 +14,8 @@ const float Float::MAX_VALUE = FLT_MAX; const double Double::MAX_VALUE = DBL_MAX; +const double Double::MIN_NORMAL = DBL_MIN; + int Integer::parseInt(std::wstring& str, int radix /* = 10*/) { return wcstol(str.c_str(), NULL, radix); } \ No newline at end of file diff --git a/Minecraft.World/Util/BasicTypeContainers.h b/Minecraft.World/Util/BasicTypeContainers.h index 494b1797f..72b3785b1 100644 --- a/Minecraft.World/Util/BasicTypeContainers.h +++ b/Minecraft.World/Util/BasicTypeContainers.h @@ -35,6 +35,7 @@ public: class Double { public: static const double MAX_VALUE; + static const double MIN_NORMAL; static bool isNaN(double a) { #ifdef __PS3__ @@ -53,4 +54,4 @@ public: // 4J Stu - The String class should only be used if we need to use the // BaseClass::class type As such I have renamed it so that we don't confuse it // with places where we should use std::string -class _String {}; +class _String {}; \ No newline at end of file diff --git a/Minecraft.World/Util/BoundingBox.cpp b/Minecraft.World/Util/BoundingBox.cpp index 9492487a9..7ee4589b4 100644 --- a/Minecraft.World/Util/BoundingBox.cpp +++ b/Minecraft.World/Util/BoundingBox.cpp @@ -13,6 +13,17 @@ BoundingBox::BoundingBox() { z1 = 0; } +BoundingBox::BoundingBox(intArray sourceData) { + if (sourceData.length == 6) { + x0 = sourceData[0]; + y0 = sourceData[1]; + z0 = sourceData[2]; + x1 = sourceData[3]; + y1 = sourceData[4]; + z1 = sourceData[5]; + } +} + BoundingBox* BoundingBox::getUnknownBox() { return new BoundingBox(INT_MAX, INT_MAX, INT_MAX, INT_MIN, INT_MIN, INT_MIN); @@ -55,12 +66,12 @@ BoundingBox* BoundingBox::orientBox(int footX, int footY, int footZ, int offX, } BoundingBox::BoundingBox(BoundingBox* other) { - this->x0 = other->x0; - this->y0 = other->y0; - this->z0 = other->z0; - this->x1 = other->x1; - this->y1 = other->y1; - this->z1 = other->z1; + x0 = other->x0; + y0 = other->y0; + z0 = other->z0; + x1 = other->x1; + y1 = other->y1; + z1 = other->z1; } BoundingBox::BoundingBox(int x0, int y0, int z0, int x1, int y1, int z1) { @@ -80,8 +91,8 @@ BoundingBox::BoundingBox(int x0, int z0, int x1, int z1) { // the bounding box for this constructor is limited to world size, // excluding bedrock level - this->y0 = 1; - this->y1 = 512; + y0 = 1; + y1 = 512; } bool BoundingBox::intersects(BoundingBox* other) { @@ -100,12 +111,12 @@ bool BoundingBox::intersects(int x0, int z0, int x1, int z1) { } void BoundingBox::expand(BoundingBox* other) { - this->x0 = Math::_min(this->x0, other->x0); - this->y0 = Math::_min(this->y0, other->y0); - this->z0 = Math::_min(this->z0, other->z0); - this->x1 = Math::_max(this->x1, other->x1); - this->y1 = Math::_max(this->y1, other->y1); - this->z1 = Math::_max(this->z1, other->z1); + x0 = Math::_min(x0, other->x0); + y0 = Math::_min(y0, other->y0); + z0 = Math::_min(z0, other->z0); + x1 = Math::_max(x1, other->x1); + y1 = Math::_max(y1, other->y1); + z1 = Math::_max(z1, other->z1); } BoundingBox* BoundingBox::getIntersection(BoundingBox* other) { @@ -113,12 +124,12 @@ BoundingBox* BoundingBox::getIntersection(BoundingBox* other) { return NULL; } BoundingBox* result = new BoundingBox(); - result->x0 = Math::_max(this->x0, other->x0); - result->y0 = Math::_max(this->y0, other->y0); - result->z0 = Math::_max(this->z0, other->z0); - result->x1 = Math::_min(this->x1, other->x1); - result->y1 = Math::_min(this->y1, other->y1); - result->z1 = Math::_min(this->z1, other->z1); + result->x0 = Math::_max(x0, other->x0); + result->y0 = Math::_max(y0, other->y0); + result->z0 = Math::_max(z0, other->z0); + result->x1 = Math::_min(x1, other->x1); + result->y1 = Math::_min(y1, other->y1); + result->z1 = Math::_min(z1, other->z1); return result; } @@ -152,4 +163,17 @@ std::wstring BoundingBox::toString() { return L"(" + _toString(x0) + L", " + _toString(y0) + L", " + _toString(z0) + L"; " + _toString(x1) + L", " + _toString(y1) + L", " + _toString(z1) + L")"; +} + +IntArrayTag* BoundingBox::createTag(const std::wstring& name) { + // 4J-JEV: If somebody knows a better way to do this, please tell me. + int* data = new int[6](); + data[0] = x0; + data[1] = y0; + data[2] = z0; + data[3] = x1; + data[4] = y1; + data[5] = z1; + + return new IntArrayTag(name, intArray(data, 6)); } \ No newline at end of file diff --git a/Minecraft.World/Util/BoundingBox.h b/Minecraft.World/Util/BoundingBox.h index ccd8afad1..11ba91ddf 100644 --- a/Minecraft.World/Util/BoundingBox.h +++ b/Minecraft.World/Util/BoundingBox.h @@ -1,10 +1,13 @@ #pragma once +#include "ArrayWithLength.h" + class BoundingBox { public: int x0, y0, z0, x1, y1, z1; BoundingBox(); + BoundingBox(intArray sourceData); static BoundingBox* getUnknownBox(); static BoundingBox* orientBox(int footX, int footY, int footZ, int offX, int offY, int offZ, int width, int height, @@ -29,4 +32,5 @@ public: int getZCenter(); std::wstring toString(); + IntArrayTag* createTag(const std::wstring& name); }; \ No newline at end of file diff --git a/Minecraft.World/Util/C4JThread.cpp b/Minecraft.World/Util/C4JThread.cpp index 7577e8d4d..ace672d19 100644 --- a/Minecraft.World/Util/C4JThread.cpp +++ b/Minecraft.World/Util/C4JThread.cpp @@ -250,7 +250,7 @@ DWORD WINAPI C4JThread::entryPoint(LPVOID lpParam) { void C4JThread::Run() { #ifdef __PS3__ // prio specifies the priority value of the PPU thread within the - //range from 0 to 3071 where 0 is the highest. + // range from 0 to 3071 where 0 is the highest. // One of the following values is set to flags: // 0 - non-joinable non-interrupt thread // SYS_PPU_THREAD_CREATE_JOINABLE - Create a joinable thread @@ -270,7 +270,7 @@ void C4JThread::Run() { #elif defined __PSVITA__ StrArg strArg = {this}; // m_threadID = sceKernelCreateThread(m_threadName, entryPoint, m_priority, - //m_stackSize, 0, m_CPUMask, NULL); + // m_stackSize, 0, m_CPUMask, NULL); sceKernelStartThread(m_threadID, sizeof(strArg), &strArg); #else ResumeThread(m_threadHandle); @@ -356,7 +356,7 @@ void C4JThread::SetPriority(int priority) { } #elif defined __PSVITA__ int Mid = g_DefaultPriority; //(SCE_KERNEL_LOWEST_PRIORITY_USER + - //SCE_KERNEL_HIGHEST_PRIORITY_USER) / 2; + // SCE_KERNEL_HIGHEST_PRIORITY_USER) / 2; switch (priority) { case THREAD_PRIORITY_LOWEST: m_priority = SCE_KERNEL_LOWEST_PRIORITY_USER; @@ -1062,4 +1062,4 @@ void C4JThread::PopAffinity() { assert(err == SCE_OK); } -#endif // __ORBIS__ +#endif // __ORBIS__ \ No newline at end of file diff --git a/Minecraft.World/Util/Class.h b/Minecraft.World/Util/Class.h index 697d0f21f..072b1c4be 100644 --- a/Minecraft.World/Util/Class.h +++ b/Minecraft.World/Util/Class.h @@ -8,127 +8,258 @@ class InputStream; // are #defines here to simplify declaring classes with this added // functionality. +// 0b FFFF CCCC CCCC CCCC CCCC CCCC CCEE EEEE +// |||| |||| |||| |||| |||| |||| |||| |||| +// |||| |||| |||| |||| |||| |||| |||| |||\- BIT00: ENUM: +// |||| |||| |||| |||| |||| |||| |||| ||\-- BIT01: ENUM: +// |||| |||| |||| |||| |||| |||| |||| |\--- BIT02: ENUM: +// |||| |||| |||| |||| |||| |||| |||| \---- BIT03: ENUM: +// |||| |||| |||| |||| |||| |||| |||| +// |||| |||| |||| |||| |||| |||| |||\------ BIT04: ENUM: +// |||| |||| |||| |||| |||| |||| ||\------- BIT05: ENUM: +// |||| |||| |||| |||| |||| |||| |\-------- BIT06: CLASS: WATER_MOB +// |||| |||| |||| |||| |||| |||| \--------- BIT07: CLASS: AMBIENT_MOB +// |||| |||| |||| |||| |||| |||| +// |||| |||| |||| |||| |||| |||\----------- BIT08: CLASS: !ENTITY (so +// we can hide TILE_ENTITY and DISPENSER_TILE_ENTITY bits which aren't +// relevant for entities) +// |||| |||| |||| |||| |||| ||\------------ BIT09: CLASS: +// MINECART_CONTAINER +// |||| |||| |||| |||| |||| |\------------- BIT10: CLASS: SLIME +// |||| |||| |||| |||| |||| \-------------- BIT11: CLASS: ZOMBIE +// |||| |||| |||| |||| |||| +// |||| |||| |||| |||| |||\---------------- BIT12: CLASS: SPIDER +// |||| |||| |||| |||| ||\----------------- BIT13: CLASS: COW +// |||| |||| |||| |||| |\------------------ BIT14: CLASS: TAMABLE +// |||| |||| |||| |||| \------------------- BIT15: CLASS: ANIMAL +// |||| |||| |||| |||| +// |||| |||| |||| |||\--------------------- BIT16: CLASS: +// MONSTER +// |||| |||| |||| ||\---------------------- BIT17: CLASS: +// GOLEM +// |||| |||| |||| |\----------------------- BIT18: CLASS: AGABLE_MOB +// |||| |||| |||| \------------------------ BIT19: CLASS: +// PATHFINDER_MOB +// |||| |||| |||| +// |||| |||| |||\-------------------------- BIT20: CLASS: +// PLAYER +// |||| |||| ||\--------------------------- BIT21: CLASS: +// MOB +// |||| |||| |\---------------------------- BIT22: CLASS: +// HANGING_ENTITY +// |||| |||| \----------------------------- BIT23: CLASS: +// THROWABLE +// |||| |||| +// |||| |||\------------------------------- BIT24: CLASS: FIREBALL +// |||| ||\-------------------------------- BIT25: CLASS: MINECART +// |||| |\--------------------------------- BIT26: CLASS: LIVING_ENTITY +// |||| \---------------------------------- BIT27: CLASS: ENTITY +// |||| +// |||\------------------------------------ BIT28: FLAGS: valid in +// spawner flag +// ||\------------------------------------- BIT29: FLAGS: +// Spawnlimitcheck +// |\-------------------------------------- BIT30: FLAGS: Enemy +// \--------------------------------------- BIT31: FLAGS: projectile + +#define Bit(a) ((1) << (a)) + +const unsigned int BIT_NOT_LIVING_ENTITY = Bit(25); + +// Classes + +const unsigned int BIT_FLYING_MOB = Bit(9); +const unsigned int BIT_WATER_MOB = Bit(10); +const unsigned int BIT_AMBIENT_MOB = Bit(11); + +const unsigned int BIT_NOT_ENTITY = Bit(12); +const unsigned int BIT_SLIME = Bit(13); +const unsigned int BIT_ZOMBIE = Bit(14); +const unsigned int BIT_SPIDER = Bit(15); + +const unsigned int BIT_COW = Bit(16); +const unsigned int BIT_TAMABLE = Bit(17); +const unsigned int BIT_ANIMAL = Bit(18); +const unsigned int BIT_MONSTER = Bit(19); +const unsigned int BIT_MINECART_CONTAINER = Bit(19) | BIT_NOT_LIVING_ENTITY; + +const unsigned int BIT_GOLEM = Bit(20); +const unsigned int BIT_HANGING_ENTITY = Bit(20) | BIT_NOT_LIVING_ENTITY; +const unsigned int BIT_AGABLE_MOB = Bit(21); +const unsigned int BIT_THROWABLE = Bit(21) | BIT_NOT_LIVING_ENTITY; +const unsigned int BIT_PATHFINDER_MOB = Bit(22); +const unsigned int BIT_FIREBALL = Bit(22) | BIT_NOT_LIVING_ENTITY; +const unsigned int BIT_PLAYER = Bit(23); +const unsigned int BIT_MINECART = Bit(23) | BIT_NOT_LIVING_ENTITY; + +const unsigned int BIT_MOB = Bit(24); +const unsigned int BIT_GLOBAL_ENTITY = Bit(24) | BIT_NOT_LIVING_ENTITY; +// const unsigned int BIT_NOT_LIVING_ENTITY +// = Bit(25); +const unsigned int BIT_LIVING_ENTITY = Bit(26); +const unsigned int BIT_ENTITY = Bit(27); + +// Flags +const unsigned int BIT_VALID_IN_SPAWNER = Bit(28); +const unsigned int BIT_ANIMALS_SPAWN_LIMIT_CHECK = Bit(29); +const unsigned int BIT_ENEMY = Bit(30); +const unsigned int BIT_PROJECTILE = Bit(31U); + +// Tile Entities +const unsigned int BIT_TILE_ENTITY = Bit(24) | BIT_NOT_ENTITY; +const unsigned int BIT_DISPENSERTILEENTITY = Bit(25) | BIT_NOT_ENTITY; +const unsigned int BIT_OTHER_NOT_ENTITIES = Bit(26) | BIT_NOT_ENTITY; + +// 4J-JEV: These abstract classes only have one subclass, so ignore them. +// const unsigned int BIT_WATER_MOB = +// Bit(15); const unsigned int BIT_FLYING_MOB = Bit(17); const unsigned int +// BIT_AMBIENT_MOB = Bit(18); const unsigned int +// BIT_GLOBAL_ENTITY = Bit(); + +// #define ETYPE(a,b,c) ( (a) | (b) | (c) ) + // 4J Stu - This Enum can be used as a more lightweight version of the above, // without having do dynamic casts 4J-PB - for replacement of instanceof enum eINSTANCEOF { eTYPE_NOTSET = 0, - // 4J-RR arranging these pathfinder types in a bitfield fashion so that a - // single and can determine whether they are derived from the 3 subclasses - // of pathfinders (water animals, animals, and monsters) that the mob - // spawner uses - eTYPE_WATERANIMAL = 0x100, - eTYPE_SQUID = 0x101, + // Flags. + eTYPE_VALID_IN_SPAWNER_FLAG = BIT_VALID_IN_SPAWNER, + eTYPE_ANIMALS_SPAWN_LIMIT_CHECK = BIT_ANIMALS_SPAWN_LIMIT_CHECK, + eTYPE_ENEMY = BIT_ENEMY, + eTYPE_PROJECTILE = BIT_PROJECTILE, - eTYPE_ANIMAL = 0x200, + eTYPE_ENTITY = BIT_ENTITY, - // 4J Stu - These have the ANIMAL, AGABLE_MOB and ANIMALS_SPAWN_LIMIT_CHECK - // bits set - eTYPE_COW = 0x82201, - eTYPE_SHEEP = 0x82202, - eTYPE_PIG = 0x82203, - eTYPE_SNOWMAN = 0x82204, - eTYPE_OZELOT = 0x82205, + eTYPE_LIVINGENTITY = eTYPE_ENTITY | BIT_LIVING_ENTITY, + + eTYPE_MOB = eTYPE_LIVINGENTITY | BIT_MOB, + + eTYPE_PATHFINDER_MOB = eTYPE_MOB | BIT_PATHFINDER_MOB, + + eTYPE_AGABLE_MOB = eTYPE_PATHFINDER_MOB | BIT_AGABLE_MOB, + + eTYPE_VILLAGER = eTYPE_AGABLE_MOB | 0x1, // 0x12000, // 4J Stu - When adding new categories, please also update // ConsoleSchematicFile::generateSchematicFile so these can be saved out to - // schematics 4J Stu- These have the ANIMAL and AGABLE_MOB bits set, but NOT - // ANIMALS_SPAWN_LIMIT_CHECK - eTYPE_CHICKEN = 0x2206, - eTYPE_WOLF = 0x2207, - eTYPE_MUSHROOMCOW = 0x2208, + // schematics + eTYPE_ANIMAL = eTYPE_AGABLE_MOB | BIT_ANIMAL, + + eTYPE_TAMABLE_ANIMAL = eTYPE_ANIMAL | BIT_TAMABLE, + + eTYPE_OCELOT = eTYPE_TAMABLE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1, + eTYPE_WOLF = eTYPE_TAMABLE_ANIMAL | 0x2, + + eTYPE_HORSE = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1, + eTYPE_SHEEP = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x2, + eTYPE_PIG = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x3, + eTYPE_CHICKEN = eTYPE_ANIMAL | 0x4, + + eTYPE_COW = eTYPE_ANIMAL | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | BIT_COW, + eTYPE_MUSHROOMCOW = eTYPE_COW | 0x1, + + eTYPE_WATERANIMAL = eTYPE_PATHFINDER_MOB | BIT_WATER_MOB, // 0x100, + eTYPE_SQUID = eTYPE_WATERANIMAL | 0x1, + + eTYPE_GOLEM = eTYPE_PATHFINDER_MOB | BIT_GOLEM, + + eTYPE_SNOWMAN = + eTYPE_GOLEM | eTYPE_ANIMALS_SPAWN_LIMIT_CHECK | 0x1, // 0x4, + eTYPE_VILLAGERGOLEM = eTYPE_GOLEM | 0x2, // 0x1000, // 4J Stu - If you add new hostile mobs here you should also update the - // string lookup function at CConsoleMinecraftApp::getEntityName - eTYPE_MONSTER = 0x400, - eTYPE_ENEMY = 0x800, - eTYPE_CREEPER = 0xC01, - eTYPE_GIANT = 0xC02, - eTYPE_SKELETON = 0xC03, - eTYPE_SPIDER = 0xC04, - eTYPE_ZOMBIE = 0xC05, - eTYPE_PIGZOMBIE = 0xC06, - eTYPE_ENDERMAN = 0xC07, - eTYPE_SILVERFISH = 0xC08, - eTYPE_CAVESPIDER = 0xC09, - eTYPE_BLAZE = 0xC0A, + // std::string lookup function at CConsoleMinecraftApp::getEntityName + eTYPE_MONSTER = eTYPE_ENEMY | eTYPE_PATHFINDER_MOB | BIT_MONSTER, + eTYPE_SPIDER = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | BIT_SPIDER, + eTYPE_CAVESPIDER = eTYPE_SPIDER | 0x1, + + eTYPE_ZOMBIE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | BIT_ZOMBIE, + eTYPE_PIGZOMBIE = eTYPE_ZOMBIE | 0x1, + + eTYPE_CREEPER = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x1, + eTYPE_GIANT = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x2, + eTYPE_SKELETON = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x3, + eTYPE_ENDERMAN = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x4, + eTYPE_SILVERFISH = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x5, + 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_AMBIENT = eTYPE_MOB | BIT_AMBIENT_MOB, + eTYPE_BAT = eTYPE_AMBIENT | eTYPE_VALID_IN_SPAWNER_FLAG | 0x1, + + eTYPE_FLYING_MOB = eTYPE_MOB | BIT_FLYING_MOB, eTYPE_GHAST = - 0xC0B, // Now considering as a monster even though class inheritance - // doesn't work like this - but otherwise breaks mob spawning + eTYPE_FLYING_MOB | eTYPE_VALID_IN_SPAWNER_FLAG | eTYPE_ENEMY | 0x1, + eTYPE_SLIME = - 0xC0C, // Now considering as a monster even though class inheritance - // doesn't work like this - but otherwise breaks mob spawning - eTYPE_LAVASLIME = 0xC0D, + eTYPE_MOB | eTYPE_VALID_IN_SPAWNER_FLAG | eTYPE_ENEMY | BIT_SLIME, + eTYPE_LAVASLIME = eTYPE_SLIME | 0x1, - eTYPE_VILLAGERGOLEM = 0x1000, + eTYPE_ENDERDRAGON = eTYPE_MOB | 0x5, - eTYPE_AGABLE_MOB = 0x2000, + eTYPE_PLAYER = eTYPE_LIVINGENTITY | BIT_PLAYER, // 0x8000, + eTYPE_SERVERPLAYER = eTYPE_PLAYER | 0x1, + eTYPE_REMOTEPLAYER = eTYPE_PLAYER | 0x2, + eTYPE_LOCALPLAYER = eTYPE_PLAYER | 0x3, - eTYPE_PLAYER = 0x8000, - eTYPE_SERVERPLAYER = 0x8001, + eTYPE_GLOBAL_ENTITY = eTYPE_ENTITY | BIT_GLOBAL_ENTITY, + eTYPE_LIGHTNINGBOLT = eTYPE_GLOBAL_ENTITY | 0x1, - // Include AGABLE_MOB - eTYPE_VILLAGER = 0x12000, + eTYPE_MINECART = eTYPE_ENTITY | BIT_MINECART, // 0x200000, - eTYPE_PROJECTILE = 0x40000, - eTYPE_ARROW = 0x40001, - eTYPE_FIREBALL = 0x40002, - eTYPE_FISHINGHOOK = 0x40003, - eTYPE_SNOWBALL = 0x40004, - eTYPE_THROWNEGG = 0x40005, - eTYPE_EYEOFENDERSIGNAL = 0x40006, - eTYPE_SMALL_FIREBALL = 0x40007, - eTYPE_THROWNENDERPEARL = 0x40008, - eTYPE_THROWNPOTION = 0x40009, - eTYPE_THROWNEXPBOTTLE = 0x4000A, + eTYPE_MINECART_RIDEABLE = eTYPE_MINECART | 0x1, + eTYPE_MINECART_SPAWNER = eTYPE_MINECART | 0x6, + eTYPE_MINECART_FURNACE = eTYPE_MINECART | 0x3, + eTYPE_MINECART_TNT = eTYPE_MINECART | 0x4, - eTYPE_ANIMALS_SPAWN_LIMIT_CHECK = 0x80000, + eTYPE_MINECART_CONTAINER = eTYPE_MINECART | BIT_MINECART_CONTAINER, - // Never used, exists to ensure all later entities don't match the bitmasks - // above - eTYPE_OTHERS = 0x100000, + eTYPE_MINECART_CHEST = eTYPE_MINECART_CONTAINER | 0x2, + eTYPE_MINECART_HOPPER = eTYPE_MINECART_CONTAINER | 0x5, - eTYPE_NETHER_SPHERE, - eTYPE_ENDER_CRYSTAL, - eTYPE_ENDERDRAGON, - eTYPE_BOSS_MOB_PART, + eTYPE_FIREBALL = eTYPE_ENTITY | eTYPE_PROJECTILE | BIT_FIREBALL, // 0x2, - eTYPE_ENTITY, + eTYPE_DRAGON_FIREBALL = eTYPE_FIREBALL | 0x1, + eTYPE_WITHER_SKULL = eTYPE_FIREBALL | 0x2, + eTYPE_LARGE_FIREBALL = eTYPE_FIREBALL | 0x3, + eTYPE_SMALL_FIREBALL = eTYPE_FIREBALL | 0x4, - eTYPE_MOB, + eTYPE_THROWABLE = eTYPE_ENTITY | eTYPE_PROJECTILE | BIT_THROWABLE, - eTYPE_LIGHTNINGBOLT, + eTYPE_SNOWBALL = eTYPE_THROWABLE | 0x1, + eTYPE_THROWNEGG = eTYPE_THROWABLE | 0x2, + eTYPE_THROWNENDERPEARL = eTYPE_THROWABLE | 0x3, + eTYPE_THROWNPOTION = eTYPE_THROWABLE | 0x4, + eTYPE_THROWNEXPBOTTLE = eTYPE_THROWABLE | 0x5, - eTYPE_PAINTING, - eTYPE_ITEMENTITY, - eTYPE_FALLINGTILE, - eTYPE_BOAT, - eTYPE_MINECART, - eTYPE_PRIMEDTNT, + eTYPE_HANGING_ENTITY = eTYPE_ENTITY | BIT_HANGING_ENTITY, - eTYPE_TILEENTITY, - eTYPE_CHESTTILEENTITY, - eTYPE_DISPENSERTILEENTITY, - eTYPE_MOBSPAWNERTILEENTITY, - eTYPE_FURNACETILEENTITY, - eTYPE_SIGNTILEENTITY, - eTYPE_MUSICTILEENTITY, - eTYPE_RECORDPLAYERTILE, - eTYPE_PISTONPIECEENTITY, - eTYPE_BREWINGSTANDTILEENTITY, - eTYPE_ENCHANTMENTTABLEENTITY, - eTYPE_THEENDPORTALTILEENTITY, - eTYPE_SKULLTILEENTITY, - eTYPE_ENDERCHESTTILEENTITY, + eTYPE_PAINTING = eTYPE_HANGING_ENTITY | 0x1, + eTYPE_ITEM_FRAME = eTYPE_HANGING_ENTITY | 0x2, + eTYPE_LEASHFENCEKNOT = eTYPE_HANGING_ENTITY | 0x3, - eType_NODE, + // Other Entities. - eType_ITEM, - eType_ITEMINSTANCE, - eType_MAPITEM, - eType_TILE, - eType_FIRETILE, + eTYPE_OTHER_ENTITIES = eTYPE_ENTITY + 1, + + eTYPE_EXPERIENCEORB = (eTYPE_OTHER_ENTITIES + 2), // 1.8.2 + eTYPE_EYEOFENDERSIGNAL = (eTYPE_OTHER_ENTITIES + 3) | eTYPE_PROJECTILE, + eTYPE_FIREWORKS_ROCKET = (eTYPE_OTHER_ENTITIES + 4) | eTYPE_PROJECTILE, + eTYPE_FISHINGHOOK = (eTYPE_OTHER_ENTITIES + 5) | eTYPE_PROJECTILE, + eTYPE_DELAYEDRELEASE = (eTYPE_OTHER_ENTITIES + 6), // 1.8.2 + eTYPE_BOAT = (eTYPE_OTHER_ENTITIES + 7), + eTYPE_FALLINGTILE = (eTYPE_OTHER_ENTITIES + 8), + eTYPE_ITEMENTITY = (eTYPE_OTHER_ENTITIES + 9), + eTYPE_PRIMEDTNT = (eTYPE_OTHER_ENTITIES + 10), + eTYPE_ARROW = (eTYPE_OTHER_ENTITIES + 11) | eTYPE_PROJECTILE, + eTYPE_MULTIENTITY_MOB_PART = (eTYPE_OTHER_ENTITIES + 12), + eTYPE_NETHER_SPHERE = (eTYPE_OTHER_ENTITIES + 13), + eTYPE_ENDER_CRYSTAL = (eTYPE_OTHER_ENTITIES + 14), + + // === PARTICLES === // eType_BREAKINGITEMPARTICLE, eType_BUBBLEPARTICLE, @@ -148,8 +279,6 @@ enum eINSTANCEOF { eType_WATERDROPPARTICLE, // 1.8.2 - eTYPE_DELAYEDRELEASE, - eTYPE_EXPERIENCEORB, eType_CRITPARTICLE, eType_CRITPARTICLE2, eType_HUGEEXPLOSIONPARTICLE, @@ -164,10 +293,467 @@ enum eINSTANCEOF { eTYPE_SPELLPARTICLE, // TU9 - eTYPE_HANGING_ENTITY, - eTYPE_ITEM_FRAME, eTYPE_DRAGONBREATHPARTICLE, - eTYPE_DRAGON_FIREBALL, - eType_ENDERPARTICLE, + + eType_FIREWORKSSTARTERPARTICLE, + eType_FIREWORKSSPARKPARTICLE, + eType_FIREWORKSOVERLAYPARTICLE, + + // === Tile Entities === // + + eTYPE_TILEENTITY = BIT_TILE_ENTITY, + + eTYPE_CHESTTILEENTITY = eTYPE_TILEENTITY | 0x01, + eTYPE_MOBSPAWNERTILEENTITY = eTYPE_TILEENTITY | 0x02, + eTYPE_FURNACETILEENTITY = eTYPE_TILEENTITY | 0x03, + eTYPE_SIGNTILEENTITY = eTYPE_TILEENTITY | 0x04, + eTYPE_MUSICTILEENTITY = eTYPE_TILEENTITY | 0x05, + eTYPE_RECORDPLAYERTILE = eTYPE_TILEENTITY | 0x06, + eTYPE_PISTONPIECEENTITY = eTYPE_TILEENTITY | 0x07, + eTYPE_BREWINGSTANDTILEENTITY = eTYPE_TILEENTITY | 0x08, + eTYPE_ENCHANTMENTTABLEENTITY = eTYPE_TILEENTITY | 0x09, + eTYPE_THEENDPORTALTILEENTITY = eTYPE_TILEENTITY | 0x0A, + eTYPE_SKULLTILEENTITY = eTYPE_TILEENTITY | 0x0B, + eTYPE_ENDERCHESTTILEENTITY = eTYPE_TILEENTITY | 0x0C, + eTYPE_BEACONTILEENTITY = eTYPE_TILEENTITY | 0x0D, + eTYPE_COMMANDBLOCKTILEENTITY = eTYPE_TILEENTITY | 0x0E, + eTYPE_COMPARATORTILEENTITY = eTYPE_TILEENTITY | 0x0F, + eTYPE_DAYLIGHTDETECTORTILEENTITY = eTYPE_TILEENTITY | 0x10, + eTYPE_HOPPERTILEENTITY = eTYPE_TILEENTITY | 0x11, + + eTYPE_DISPENSERTILEENTITY = eTYPE_TILEENTITY | BIT_DISPENSERTILEENTITY, + eTYPE_DROPPERTILEENTITY = eTYPE_DISPENSERTILEENTITY | 0x1, + + // === Never used === // + // exists to ensure all later entities don't match the bitmasks above + + eTYPE_OTHERS = BIT_OTHER_NOT_ENTITIES, + + eType_NODE, + eType_ITEM, + eType_ITEMINSTANCE, + eType_MAPITEM, + eType_TILE, + eType_FIRETILE, }; + +inline bool eTYPE_DERIVED_FROM(eINSTANCEOF super, eINSTANCEOF sub) { + if ((super & 0x3F) != 0x00) + return super == sub; + else + return (super & sub) == super; +} + +inline bool eTYPE_FLAGSET(eINSTANCEOF flag, eINSTANCEOF claz) { + return (flag & claz) == flag; +} + +/// FOR CHECKING /// + +#if !(defined _WINDOWS64) + +class SubClass { + static void checkDerivations() {} +}; + +#else + +class SubClass { +public: + bool m_isTerminal; + const std::string m_name; + const eINSTANCEOF m_id; + std::vector m_parents; + + static std::unordered_map s_ids; + + SubClass(const std::string& name, eINSTANCEOF id) : m_name(name), m_id(id) { + s_ids.insert(std::pair(id, this)); + m_isTerminal = true; + } + + SubClass* addParent(eINSTANCEOF id) { + SubClass* parent = s_ids.at(id); + parent->m_isTerminal = false; + + m_parents.push_back(id); + + for (AUTO_VAR(itr, parent->m_parents.begin()); + itr != parent->m_parents.end(); itr++) { + m_parents.push_back(*itr); + } + + return this; + } + + bool justFlag() { return (m_id & 0xF00000) == m_id; } + +#define SUBCLASS(x) (new SubClass(#x, x)) + + static void checkDerivations() { + std::vector* classes = new std::vector(); + + classes->push_back(SUBCLASS(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back(SUBCLASS(eTYPE_ENEMY)); + classes->push_back(SUBCLASS(eTYPE_PROJECTILE)); + + classes->push_back(SUBCLASS(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_LIVINGENTITY)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_MOB)->addParent(eTYPE_LIVINGENTITY)); + classes->push_back( + SUBCLASS(eTYPE_PATHFINDER_MOB)->addParent(eTYPE_MOB)); + classes->push_back( + SUBCLASS(eTYPE_AGABLE_MOB)->addParent(eTYPE_PATHFINDER_MOB)); + classes->push_back( + SUBCLASS(eTYPE_VILLAGER)->addParent(eTYPE_AGABLE_MOB)); + classes->push_back(SUBCLASS(eTYPE_ANIMAL)->addParent(eTYPE_AGABLE_MOB)); + classes->push_back( + SUBCLASS(eTYPE_TAMABLE_ANIMAL)->addParent(eTYPE_ANIMAL)); + classes->push_back(SUBCLASS(eTYPE_OCELOT) + ->addParent(eTYPE_TAMABLE_ANIMAL) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back( + SUBCLASS(eTYPE_WOLF)->addParent(eTYPE_TAMABLE_ANIMAL)); + classes->push_back(SUBCLASS(eTYPE_HORSE) + ->addParent(eTYPE_ANIMAL) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back(SUBCLASS(eTYPE_SHEEP) + ->addParent(eTYPE_ANIMAL) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back(SUBCLASS(eTYPE_PIG) + ->addParent(eTYPE_ANIMAL) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back(SUBCLASS(eTYPE_CHICKEN)->addParent(eTYPE_ANIMAL)); + classes->push_back(SUBCLASS(eTYPE_COW) + ->addParent(eTYPE_ANIMAL) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back(SUBCLASS(eTYPE_MUSHROOMCOW)->addParent(eTYPE_COW)); + classes->push_back( + SUBCLASS(eTYPE_WATERANIMAL)->addParent(eTYPE_PATHFINDER_MOB)); + classes->push_back(SUBCLASS(eTYPE_SQUID)->addParent(eTYPE_WATERANIMAL)); + classes->push_back( + SUBCLASS(eTYPE_GOLEM)->addParent(eTYPE_PATHFINDER_MOB)); + classes->push_back(SUBCLASS(eTYPE_SNOWMAN) + ->addParent(eTYPE_GOLEM) + ->addParent(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)); + classes->push_back( + SUBCLASS(eTYPE_VILLAGERGOLEM)->addParent(eTYPE_GOLEM)); + classes->push_back(SUBCLASS(eTYPE_MONSTER) + ->addParent(eTYPE_ENEMY) + ->addParent(eTYPE_PATHFINDER_MOB)); + classes->push_back(SUBCLASS(eTYPE_SPIDER) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_CAVESPIDER)->addParent(eTYPE_SPIDER)); + classes->push_back(SUBCLASS(eTYPE_ZOMBIE) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_PIGZOMBIE)->addParent(eTYPE_ZOMBIE)); + classes->push_back(SUBCLASS(eTYPE_CREEPER) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_GIANT) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_SKELETON) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_ENDERMAN) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_SILVERFISH) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_BLAZE) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_WITCH) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_WITHERBOSS) + ->addParent(eTYPE_MONSTER) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_AMBIENT)->addParent(eTYPE_MOB)); + classes->push_back(SUBCLASS(eTYPE_BAT) + ->addParent(eTYPE_AMBIENT) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG)); + classes->push_back(SUBCLASS(eTYPE_FLYING_MOB)->addParent(eTYPE_MOB)); + classes->push_back(SUBCLASS(eTYPE_GHAST) + ->addParent(eTYPE_FLYING_MOB) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG) + ->addParent(eTYPE_ENEMY)); + classes->push_back(SUBCLASS(eTYPE_SLIME) + ->addParent(eTYPE_MOB) + ->addParent(eTYPE_VALID_IN_SPAWNER_FLAG) + ->addParent(eTYPE_ENEMY)); + classes->push_back(SUBCLASS(eTYPE_LAVASLIME)->addParent(eTYPE_SLIME)); + classes->push_back(SUBCLASS(eTYPE_ENDERDRAGON)->addParent(eTYPE_MOB)); + classes->push_back( + SUBCLASS(eTYPE_PLAYER)->addParent(eTYPE_LIVINGENTITY)); + classes->push_back( + SUBCLASS(eTYPE_SERVERPLAYER)->addParent(eTYPE_PLAYER)); + classes->push_back( + SUBCLASS(eTYPE_REMOTEPLAYER)->addParent(eTYPE_PLAYER)); + classes->push_back( + SUBCLASS(eTYPE_LOCALPLAYER)->addParent(eTYPE_PLAYER)); + classes->push_back(SUBCLASS(eTYPE_MINECART)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_MINECART_RIDEABLE)->addParent(eTYPE_MINECART)); + classes->push_back( + SUBCLASS(eTYPE_MINECART_SPAWNER)->addParent(eTYPE_MINECART)); + classes->push_back( + SUBCLASS(eTYPE_MINECART_FURNACE)->addParent(eTYPE_MINECART)); + classes->push_back( + SUBCLASS(eTYPE_MINECART_TNT)->addParent(eTYPE_MINECART)); + classes->push_back( + SUBCLASS(eTYPE_MINECART_CONTAINER)->addParent(eTYPE_MINECART)); + classes->push_back(SUBCLASS(eTYPE_MINECART_CHEST) + ->addParent(eTYPE_MINECART_CONTAINER)); + classes->push_back(SUBCLASS(eTYPE_MINECART_HOPPER) + ->addParent(eTYPE_MINECART_CONTAINER)); + classes->push_back(SUBCLASS(eTYPE_FIREBALL) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back( + SUBCLASS(eTYPE_DRAGON_FIREBALL)->addParent(eTYPE_FIREBALL)); + classes->push_back( + SUBCLASS(eTYPE_WITHER_SKULL)->addParent(eTYPE_FIREBALL)); + classes->push_back( + SUBCLASS(eTYPE_LARGE_FIREBALL)->addParent(eTYPE_FIREBALL)); + classes->push_back( + SUBCLASS(eTYPE_SMALL_FIREBALL)->addParent(eTYPE_FIREBALL)); + classes->push_back(SUBCLASS(eTYPE_THROWABLE) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back( + SUBCLASS(eTYPE_SNOWBALL)->addParent(eTYPE_THROWABLE)); + classes->push_back( + SUBCLASS(eTYPE_THROWNEGG)->addParent(eTYPE_THROWABLE)); + classes->push_back( + SUBCLASS(eTYPE_THROWNENDERPEARL)->addParent(eTYPE_THROWABLE)); + classes->push_back( + SUBCLASS(eTYPE_THROWNPOTION)->addParent(eTYPE_THROWABLE)); + classes->push_back( + SUBCLASS(eTYPE_THROWNEXPBOTTLE)->addParent(eTYPE_THROWABLE)); + classes->push_back( + SUBCLASS(eTYPE_HANGING_ENTITY)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_PAINTING)->addParent(eTYPE_HANGING_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_ITEM_FRAME)->addParent(eTYPE_HANGING_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_LEASHFENCEKNOT)->addParent(eTYPE_HANGING_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_GLOBAL_ENTITY)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_LIGHTNINGBOLT)->addParent(eTYPE_GLOBAL_ENTITY)); + + // classes->push_back( SUBCLASS(eTYPE_OTHER_ENTITIES )->addParent( + // eTYPE_ENTITY ) ); + classes->push_back( + SUBCLASS(eTYPE_EXPERIENCEORB)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_EYEOFENDERSIGNAL) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back(SUBCLASS(eTYPE_FIREWORKS_ROCKET) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back(SUBCLASS(eTYPE_FISHINGHOOK) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back( + SUBCLASS(eTYPE_DELAYEDRELEASE)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_BOAT)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_FALLINGTILE)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_ITEMENTITY)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_PRIMEDTNT)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_ARROW) + ->addParent(eTYPE_ENTITY) + ->addParent(eTYPE_PROJECTILE)); + classes->push_back( + SUBCLASS(eTYPE_MULTIENTITY_MOB_PART)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_NETHER_SPHERE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_ENDER_CRYSTAL)->addParent(eTYPE_ENTITY)); + + classes->push_back( + SUBCLASS(eType_BREAKINGITEMPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_BUBBLEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_EXPLODEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_FLAMEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_FOOTSTEPPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_HEARTPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_LAVAPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_NOTEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_NETHERPORTALPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_REDDUSTPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_SMOKEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_SNOWSHOVELPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_SPLASHPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_TAKEANIMATIONPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_TERRAINPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_WATERDROPPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_CRITPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_CRITPARTICLE2)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_HUGEEXPLOSIONPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_HUGEEXPLOSIONSEEDPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eType_PLAYERCLOUDPARTICLEPARTICLE) + ->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_SUSPENDEDPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_SUSPENDEDTOWNPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_DRIPPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_ENCHANTMENTTABLEPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_SPELLPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eTYPE_DRAGONBREATHPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_ENDERPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_FIREWORKSSTARTERPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_FIREWORKSSPARKPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back( + SUBCLASS(eType_FIREWORKSOVERLAYPARTICLE)->addParent(eTYPE_ENTITY)); + classes->push_back(SUBCLASS(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_CHESTTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_MOBSPAWNERTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_FURNACETILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_SIGNTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_MUSICTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_RECORDPLAYERTILE)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_PISTONPIECEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_BREWINGSTANDTILEENTITY) + ->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_ENCHANTMENTTABLEENTITY) + ->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_THEENDPORTALTILEENTITY) + ->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_SKULLTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_ENDERCHESTTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_BEACONTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_COMMANDBLOCKTILEENTITY) + ->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_COMPARATORTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_DAYLIGHTDETECTORTILEENTITY) + ->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_HOPPERTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back( + SUBCLASS(eTYPE_DISPENSERTILEENTITY)->addParent(eTYPE_TILEENTITY)); + classes->push_back(SUBCLASS(eTYPE_DROPPERTILEENTITY) + ->addParent(eTYPE_DISPENSERTILEENTITY)); + + // classes->push_back( SUBCLASS(eTYPE_OTHERS) ); + classes->push_back(SUBCLASS(eType_NODE)); + classes->push_back(SUBCLASS(eType_ITEM)); + classes->push_back(SUBCLASS(eType_ITEMINSTANCE)); + classes->push_back(SUBCLASS(eType_MAPITEM)); + classes->push_back(SUBCLASS(eType_TILE)); + classes->push_back(SUBCLASS(eType_FIRETILE)); + + std::vector > m_falsePositives; + std::vector > m_falseNegatives; + + std::vector::iterator it1; + for (it1 = classes->begin(); it1 != classes->end(); it1++) { + SubClass* current = *it1; + // if ( current->justFlag() ) continue; + + std::vector::iterator it2; + for (it2 = classes->begin(); it2 != classes->end(); it2++) { + SubClass* comparing = *it2; + // if ( comparing->justFlag() ) continue; + + // We shouldn't be comparing to leaf classes anyway. + // if ( comparing->m_isTerminal ) continue; + + eINSTANCEOF typeCurr, typeComp; + typeCurr = current->m_id; + typeComp = comparing->m_id; + + bool shouldDerive, doesDerive; + + { + std::vector::iterator it3; + it3 = find(current->m_parents.begin(), + current->m_parents.end(), typeComp); + shouldDerive = (typeComp == typeCurr) || + (it3 != current->m_parents.end()); + } + + doesDerive = eTYPE_DERIVED_FROM(typeComp, typeCurr); + + if (shouldDerive != doesDerive) { + std::vector >* errorArray; + if (shouldDerive) + errorArray = &m_falseNegatives; + else + errorArray = &m_falsePositives; + + errorArray->push_back( + std::pair(comparing, current)); + } + } + } + + std::vector >::iterator itrErr; + for (itrErr = m_falsePositives.begin(); + itrErr != m_falsePositives.end(); itrErr++) { + SubClass *sub = itrErr->first, *super = itrErr->second; + printf("[Class.h] Error: '%s' incorrectly derives from '%s'.\n", + sub->m_name.c_str(), super->m_name.c_str()); + } + for (itrErr = m_falseNegatives.begin(); + itrErr != m_falseNegatives.end(); itrErr++) { + SubClass *sub = itrErr->first, *super = itrErr->second; + printf("[Class.h] Error: '%s' doesn't derive '%s'.\n", + sub->m_name.c_str(), super->m_name.c_str()); + } + + if ((m_falsePositives.size() > 0) || (m_falseNegatives.size() > 0)) { + __debugbreak(); + } + } +}; + +#endif \ No newline at end of file diff --git a/Minecraft.World/Util/CombatEntry.cpp b/Minecraft.World/Util/CombatEntry.cpp new file mode 100644 index 000000000..54bae8e8a --- /dev/null +++ b/Minecraft.World/Util/CombatEntry.cpp @@ -0,0 +1,50 @@ +#include "../Platform/stdafx.h" +#include "../Headers/net.minecraft.world.damagesource.h" +#include "../Headers/net.minecraft.world.entity.h" +#include "BasicTypeContainers.h" +#include "CombatEntry.h" + +CombatEntry::CombatEntry(DamageSource* source, int time, float health, + float damage, CombatTracker::eLOCATION location, + float fallDistance) { + this->source = NULL; + if (source != NULL) { + // 4J: this might actually be a derived damage source so use copy func + this->source = source->copy(); + } + this->time = time; + this->damage = damage; + this->health = health; + this->location = location; + this->fallDistance = fallDistance; +} + +CombatEntry::~CombatEntry() { delete source; } + +DamageSource* CombatEntry::getSource() { return source; } + +int CombatEntry::getTime() { return time; } + +float CombatEntry::getDamage() { return damage; } + +float CombatEntry::getHealthBeforeDamage() { return health; } + +float CombatEntry::getHealthAfterDamage() { return health - damage; } + +bool CombatEntry::isCombatRelated() { + return source->getEntity() && + source->getEntity()->instanceof(eTYPE_LIVINGENTITY); +} + +CombatTracker::eLOCATION CombatEntry::getLocation() { return location; } + +std::wstring CombatEntry::getAttackerName() { + return getSource()->getEntity() == NULL + ? L"" + : getSource()->getEntity()->getNetworkName(); +} + +float CombatEntry::getFallDistance() { + if (source == DamageSource::outOfWorld) return Float::MAX_VALUE; + return fallDistance; +} \ No newline at end of file diff --git a/Minecraft.World/Util/CombatEntry.h b/Minecraft.World/Util/CombatEntry.h new file mode 100644 index 000000000..032f66925 --- /dev/null +++ b/Minecraft.World/Util/CombatEntry.h @@ -0,0 +1,30 @@ +#pragma once +#include "CombatTracker.h" + +class DamageSource; + +class CombatEntry { +private: + DamageSource* source; + int time; + float damage; + float health; + CombatTracker::eLOCATION + location; // 4J: Location is now an enum, not a std::string + float fallDistance; + +public: + CombatEntry(DamageSource* source, int time, float health, float damage, + CombatTracker::eLOCATION nextLocation, float fallDistance); + ~CombatEntry(); + + DamageSource* getSource(); + int getTime(); + float getDamage(); + float getHealthBeforeDamage(); + float getHealthAfterDamage(); + bool isCombatRelated(); + CombatTracker::eLOCATION getLocation(); + std::wstring getAttackerName(); + float getFallDistance(); +}; \ No newline at end of file diff --git a/Minecraft.World/Util/CombatTracker.cpp b/Minecraft.World/Util/CombatTracker.cpp new file mode 100644 index 000000000..b3cf2bff6 --- /dev/null +++ b/Minecraft.World/Util/CombatTracker.cpp @@ -0,0 +1,236 @@ +#include "../Platform/stdafx.h" +#include "../Headers/net.minecraft.world.entity.h" +#include "../Headers/net.minecraft.world.level.h" +#include "../Headers/net.minecraft.world.level.tile.h" +#include "../Headers/net.minecraft.world.phys.h" +#include "../Headers/net.minecraft.world.damagesource.h" +#include "CombatTracker.h" + +CombatTracker::CombatTracker(LivingEntity* mob) { this->mob = mob; } + +CombatTracker::~CombatTracker() { + for (AUTO_VAR(it, entries.begin()); it != entries.end(); ++it) { + delete (*it); + } +} + +void CombatTracker::prepareForDamage() { + resetPreparedStatus(); + + if (mob->onLadder()) { + int type = mob->level->getTile( + Mth::floor(mob->x), Mth::floor(mob->bb->y0), Mth::floor(mob->z)); + + if (type == Tile::ladder->id) { + nextLocation = eLocation_LADDER; + } else if (type == Tile::vine->id) { + nextLocation = eLocation_VINES; + } + } else if (mob->isInWater()) { + nextLocation = eLocation_WATER; + } +} + +void CombatTracker::recordDamage(DamageSource* source, float health, + float damage) { + recheckStatus(); + prepareForDamage(); + + CombatEntry* entry = new CombatEntry(source, mob->tickCount, health, damage, + nextLocation, mob->fallDistance); + + entries.push_back(entry); + lastDamageTime = mob->tickCount; + takingDamage = true; + inCombat |= entry->isCombatRelated(); +} + +std::shared_ptr CombatTracker::getDeathMessagePacket() { + if (entries.size() == 0) + return std::shared_ptr( + new ChatPacket(mob->getNetworkName())); + + CombatEntry* knockOffEntry = getMostSignificantFall(); + CombatEntry* killingBlow = entries[entries.size() - 1]; + + std::shared_ptr result; + + std::shared_ptr killingEntity = + killingBlow->getSource()->getEntity(); + + if (knockOffEntry != NULL && + killingBlow->getSource()->equals(DamageSource::fall)) { + std::shared_ptr attackerEntity = + knockOffEntry->getSource()->getEntity(); + + if (knockOffEntry->getSource()->equals(DamageSource::fall) || + knockOffEntry->getSource()->equals(DamageSource::outOfWorld)) { + ChatPacket::EChatPacketMessage message; + + switch (getFallLocation(knockOffEntry)) { + case eLocation_GENERIC: + message = ChatPacket::e_ChatDeathFellAccidentGeneric; + break; + case eLocation_LADDER: + message = ChatPacket::e_ChatDeathFellAccidentLadder; + break; + case eLocation_VINES: + message = ChatPacket::e_ChatDeathFellAccidentVines; + break; + case eLocation_WATER: + message = ChatPacket::e_ChatDeathFellAccidentWater; + break; + } + + result = std::shared_ptr( + new ChatPacket(mob->getNetworkName(), message)); + } else if (attackerEntity != NULL && + (killingEntity == NULL || attackerEntity != killingEntity)) { + std::shared_ptr attackerItem = + attackerEntity->instanceof(eTYPE_LIVINGENTITY) + ? std::dynamic_pointer_cast(attackerEntity) + ->getCarriedItem() + : nullptr; + + if (attackerItem != NULL && attackerItem->hasCustomHoverName()) { + result = std::shared_ptr(new ChatPacket( + mob->getNetworkName(), + ChatPacket::e_ChatDeathFellAssistItem, + attackerEntity->GetType(), attackerEntity->getNetworkName(), + attackerItem->getHoverName())); + } else { + result = std::shared_ptr(new ChatPacket( + mob->getNetworkName(), ChatPacket::e_ChatDeathFellAssist, + attackerEntity->GetType(), + attackerEntity->getNetworkName())); + } + } else if (killingEntity != NULL) { + std::shared_ptr killerItem = + killingEntity->instanceof(eTYPE_LIVINGENTITY) + ? std::dynamic_pointer_cast(killingEntity) + ->getCarriedItem() + : nullptr; + if (killerItem != NULL && killerItem->hasCustomHoverName()) { + result = std::shared_ptr(new ChatPacket( + mob->getNetworkName(), + ChatPacket::e_ChatDeathFellFinishItem, + killingEntity->GetType(), killingEntity->getNetworkName(), + killerItem->getHoverName())); + } else { + result = std::shared_ptr(new ChatPacket( + mob->getNetworkName(), ChatPacket::e_ChatDeathFellFinish, + killingEntity->GetType(), killingEntity->getNetworkName())); + } + } else { + result = std::shared_ptr(new ChatPacket( + mob->getNetworkName(), ChatPacket::e_ChatDeathFellKiller)); + } + } else { + result = killingBlow->getSource()->getDeathMessagePacket( + std::dynamic_pointer_cast(mob->shared_from_this())); + } + + return result; +} + +std::shared_ptr CombatTracker::getKiller() { + std::shared_ptr bestMob = nullptr; + std::shared_ptr bestPlayer = nullptr; + float bestMobDamage = 0; + float bestPlayerDamage = 0; + + for (AUTO_VAR(it, entries.begin()); it != entries.end(); ++it) { + CombatEntry* entry = *it; + if (entry->getSource() != NULL && + entry->getSource()->getEntity() != NULL && + entry->getSource()->getEntity()->instanceof(eTYPE_PLAYER) && + (bestPlayer == NULL || entry->getDamage() > bestPlayerDamage)) { + bestPlayerDamage = entry->getDamage(); + bestPlayer = std::dynamic_pointer_cast( + entry->getSource()->getEntity()); + } + + if (entry->getSource() != NULL && + entry->getSource()->getEntity() != NULL && + entry->getSource()->getEntity()->instanceof(eTYPE_LIVINGENTITY) && + (bestMob == NULL || entry->getDamage() > bestMobDamage)) { + bestMobDamage = entry->getDamage(); + bestMob = std::dynamic_pointer_cast( + entry->getSource()->getEntity()); + } + } + + if (bestPlayer != NULL && bestPlayerDamage >= bestMobDamage / 3) { + return bestPlayer; + } else { + return bestMob; + } +} + +CombatEntry* CombatTracker::getMostSignificantFall() { + CombatEntry* result = NULL; + CombatEntry* alternative = NULL; + int altDamage = 0; + float bestFall = 0; + + for (int i = 0; i < entries.size(); i++) { + CombatEntry* entry = entries.at(i); + CombatEntry* previous = i > 0 ? entries.at(i - 1) : NULL; + + bool isFall = entry->getSource()->equals(DamageSource::fall); + bool isOutOfWorld = + entry->getSource()->equals(DamageSource::outOfWorld); + + if ((isFall || isOutOfWorld) && (entry->getFallDistance() > 0) && + (result == NULL || entry->getFallDistance() > bestFall)) { + if (i > 0) { + result = previous; + } else { + result = entry; + } + bestFall = entry->getFallDistance(); + } + + if (entry->getLocation() != eLocation_GENERIC && + (alternative == NULL || entry->getDamage() > altDamage)) { + alternative = entry; + } + } + + if (bestFall > 5 && result != NULL) { + return result; + } else if (altDamage > 5 && alternative != NULL) { + return alternative; + } else { + return NULL; + } +} + +CombatTracker::eLOCATION CombatTracker::getFallLocation(CombatEntry* entry) { + return entry->getLocation(); +} + +bool CombatTracker::isTakingDamage() { + recheckStatus(); + return takingDamage; +} + +bool CombatTracker::isInCombat() { + recheckStatus(); + return inCombat; +} + +void CombatTracker::resetPreparedStatus() { nextLocation = eLocation_GENERIC; } + +void CombatTracker::recheckStatus() { + int reset = inCombat ? RESET_COMBAT_STATUS_TIME : RESET_DAMAGE_STATUS_TIME; + + if (takingDamage && mob->tickCount - lastDamageTime > reset) { + for (AUTO_VAR(it, entries.begin()); it != entries.end(); ++it) { + delete (*it); + } + entries.clear(); + takingDamage = false; + inCombat = false; + } +} \ No newline at end of file diff --git a/Minecraft.World/Util/CombatTracker.h b/Minecraft.World/Util/CombatTracker.h new file mode 100644 index 000000000..9a37ad8b4 --- /dev/null +++ b/Minecraft.World/Util/CombatTracker.h @@ -0,0 +1,55 @@ +#pragma once + +#include "SharedConstants.h" + +class CombatEntry; +class LivingEntity; +class ChatPacket; + +class CombatTracker { +public: + static const int RESET_DAMAGE_STATUS_TIME = + SharedConstants::TICKS_PER_SECOND * 5; + static const int RESET_COMBAT_STATUS_TIME = + SharedConstants::TICKS_PER_SECOND * 15; + + // 4J: This enum replaces + enum eLOCATION { + eLocation_GENERIC = 0, + eLocation_LADDER, + eLocation_VINES, + eLocation_WATER, + + eLocation_COUNT, + }; + +private: + std::vector entries; + LivingEntity* mob; // Owner + int lastDamageTime; + bool inCombat; + bool takingDamage; + eLOCATION nextLocation; // 4J: Location is now an enum, not a std::string + +public: + CombatTracker(LivingEntity* mob); + ~CombatTracker(); + + void prepareForDamage(); + void recordDamage(DamageSource* source, float health, float damage); + std::shared_ptr + getDeathMessagePacket(); // 4J: Changed this to return a chat packet + std::shared_ptr getKiller(); + +private: + CombatEntry* getMostSignificantFall(); + eLOCATION getFallLocation(CombatEntry* entry); + +public: + bool isTakingDamage(); + bool isInCombat(); + +private: + void resetPreparedStatus(); + void recheckStatus(); +}; \ No newline at end of file diff --git a/Minecraft.World/Util/DamageSource.cpp b/Minecraft.World/Util/DamageSource.cpp index e48124729..2f2c6e7fc 100644 --- a/Minecraft.World/Util/DamageSource.cpp +++ b/Minecraft.World/Util/DamageSource.cpp @@ -2,26 +2,34 @@ #include "../Headers/net.minecraft.world.entity.h" #include "../Headers/net.minecraft.world.entity.player.h" #include "../Headers/net.minecraft.world.entity.projectile.h" +#include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.damagesource.h" #include "../Headers/net.minecraft.world.food.h" #include "../Headers/net.minecraft.network.packet.h" DamageSource* DamageSource::inFire = - (new DamageSource(ChatPacket::e_ChatDeathInFire))->setIsFire(); + (new DamageSource(ChatPacket::e_ChatDeathInFire, + ChatPacket::e_ChatDeathInFirePlayer)) + ->setIsFire(); DamageSource* DamageSource::onFire = - (new DamageSource(ChatPacket::e_ChatDeathOnFire)) + (new DamageSource(ChatPacket::e_ChatDeathOnFire, + ChatPacket::e_ChatDeathOnFirePlayer)) ->bypassArmor() ->setIsFire(); DamageSource* DamageSource::lava = - (new DamageSource(ChatPacket::e_ChatDeathLava))->setIsFire(); + (new DamageSource(ChatPacket::e_ChatDeathLava, + ChatPacket::e_ChatDeathLavaPlayer)) + ->setIsFire(); DamageSource* DamageSource::inWall = (new DamageSource(ChatPacket::e_ChatDeathInWall))->bypassArmor(); DamageSource* DamageSource::drown = - (new DamageSource(ChatPacket::e_ChatDeathDrown))->bypassArmor(); + (new DamageSource(ChatPacket::e_ChatDeathDrown, + ChatPacket::e_ChatDeathDrownPlayer)) + ->bypassArmor(); DamageSource* DamageSource::starve = (new DamageSource(ChatPacket::e_ChatDeathStarve))->bypassArmor(); -DamageSource* DamageSource::cactus = - new DamageSource(ChatPacket::e_ChatDeathCactus); +DamageSource* DamageSource::cactus = new DamageSource( + ChatPacket::e_ChatDeathCactus, ChatPacket::e_ChatDeathCactusPlayer); DamageSource* DamageSource::fall = (new DamageSource(ChatPacket::e_ChatDeathFall))->bypassArmor(); DamageSource* DamageSource::outOfWorld = @@ -30,11 +38,6 @@ DamageSource* DamageSource::outOfWorld = ->bypassInvul(); DamageSource* DamageSource::genericSource = (new DamageSource(ChatPacket::e_ChatDeathGeneric))->bypassArmor(); -DamageSource* DamageSource::explosion = - (new DamageSource(ChatPacket::e_ChatDeathExplosion)) - ->setScalesWithDifficulty(); -DamageSource* DamageSource::controlledExplosion = - (new DamageSource(ChatPacket::e_ChatDeathExplosion)); DamageSource* DamageSource::magic = (new DamageSource(ChatPacket::e_ChatDeathMagic))->bypassArmor()->setMagic(); DamageSource* DamageSource::dragonbreath = @@ -46,18 +49,21 @@ DamageSource* DamageSource::anvil = DamageSource* DamageSource::fallingBlock = (new DamageSource(ChatPacket::e_ChatDeathFallingBlock)); -DamageSource* DamageSource::mobAttack(std::shared_ptr mob) { - return new EntityDamageSource(ChatPacket::e_ChatDeathMob, mob); +DamageSource* DamageSource::mobAttack(std::shared_ptr mob) { + return new EntityDamageSource(ChatPacket::e_ChatDeathMob, + ChatPacket::e_ChatDeathMob, mob); } DamageSource* DamageSource::playerAttack(std::shared_ptr player) { - return new EntityDamageSource(ChatPacket::e_ChatDeathPlayer, player); + return new EntityDamageSource(ChatPacket::e_ChatDeathPlayer, + ChatPacket::e_ChatDeathPlayerItem, player); } DamageSource* DamageSource::arrow(std::shared_ptr arrow, std::shared_ptr owner) { - return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathArrow, arrow, - owner)) + return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathArrow, + ChatPacket::e_ChatDeathArrowItem, + arrow, owner)) ->setProjectile(); } @@ -65,11 +71,13 @@ DamageSource* DamageSource::fireball(std::shared_ptr fireball, std::shared_ptr owner) { if (owner == NULL) { return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathOnFire, + ChatPacket::e_ChatDeathOnFire, fireball, fireball)) ->setIsFire() ->setProjectile(); } return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathFireball, + ChatPacket::e_ChatDeathArrowItem, fireball, owner)) ->setIsFire() ->setProjectile(); @@ -78,28 +86,52 @@ DamageSource* DamageSource::fireball(std::shared_ptr fireball, DamageSource* DamageSource::thrown(std::shared_ptr entity, std::shared_ptr owner) { return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathThrown, + ChatPacket::e_ChatDeathThrownItem, entity, owner)) ->setProjectile(); } DamageSource* DamageSource::indirectMagic(std::shared_ptr entity, std::shared_ptr owner) { - return (new IndirectEntityDamageSource(ChatPacket::e_ChatDeathIndirectMagic, - entity, owner)) + return (new IndirectEntityDamageSource( + ChatPacket::e_ChatDeathIndirectMagic, + ChatPacket::e_ChatDeathIndirectMagicItem, entity, owner)) ->bypassArmor() ->setMagic(); ; } DamageSource* DamageSource::thorns(std::shared_ptr source) { - return (new EntityDamageSource(ChatPacket::e_ChatDeathThorns, source)) + return (new EntityDamageSource(ChatPacket::e_ChatDeathThorns, + ChatPacket::e_ChatDeathThorns, source)) ->setMagic(); } +DamageSource* DamageSource::explosion(Explosion* explosion) { + if ((explosion != NULL) && (explosion->getSourceMob() != NULL)) { + return (new EntityDamageSource(ChatPacket::e_ChatDeathExplosionPlayer, + ChatPacket::e_ChatDeathExplosionPlayer, + explosion->getSourceMob())) + ->setScalesWithDifficulty() + ->setExplosion(); + } else { + return (new DamageSource(ChatPacket::e_ChatDeathExplosion)) + ->setScalesWithDifficulty() + ->setExplosion(); + } +} + bool DamageSource::isProjectile() { return _isProjectile; } DamageSource* DamageSource::setProjectile() { - this->_isProjectile = true; + _isProjectile = true; + return this; +} + +bool DamageSource::isExplosion() { return _isExplosion; } + +DamageSource* DamageSource::setExplosion() { + _isExplosion = true; return this; } @@ -109,8 +141,9 @@ float DamageSource::getFoodExhaustion() { return exhaustion; } bool DamageSource::isBypassInvul() { return _bypassInvul; } -// DamageSource::DamageSource(const std::wstring &msgId) -DamageSource::DamageSource(ChatPacket::EChatPacketMessage msgId) { +// DamageSource::DamageSource(const wstring &msgId) +DamageSource::DamageSource(ChatPacket::EChatPacketMessage msgId, + ChatPacket::EChatPacketMessage msgWithItemId) { // 4J added initialisors _bypassArmor = false; _bypassInvul = false; @@ -119,9 +152,11 @@ DamageSource::DamageSource(ChatPacket::EChatPacketMessage msgId) { isFireSource = false; _isProjectile = false; _isMagic = false; + _isExplosion = false; // this->msgId = msgId; m_msgId = msgId; + m_msgWithItemId = msgWithItemId; } std::shared_ptr DamageSource::getDirectEntity() { return getEntity(); } @@ -161,18 +196,36 @@ DamageSource* DamageSource::setMagic() { return this; } -// std::wstring DamageSource::getLocalizedDeathMessage(std::shared_ptr -// player) +// wstring DamageSource::getLocalizedDeathMessage(shared_ptr player) //{ // return L"death." + msgId + player->name; // //return I18n.get(L"death." + msgId, player.name); // } std::shared_ptr DamageSource::getDeathMessagePacket( - std::shared_ptr player) { - return std::shared_ptr(new ChatPacket(player->name, m_msgId)); + std::shared_ptr player) { + std::shared_ptr source = player->getKillCredit(); + if (source != NULL) { + return std::shared_ptr(new ChatPacket( + player->getNetworkName(), + m_msgWithItemId != ChatPacket::e_ChatCustom ? m_msgWithItemId + : m_msgId, + source->GetType(), source->getNetworkName())); + } else { + return std::shared_ptr( + new ChatPacket(player->getNetworkName(), m_msgId)); + } } bool DamageSource::isFire() { return isFireSource; } -ChatPacket::EChatPacketMessage DamageSource::getMsgId() { return m_msgId; } \ No newline at end of file +ChatPacket::EChatPacketMessage DamageSource::getMsgId() { return m_msgId; } + +// 4J: Very limited check for equality (used to detect fall damage, etc) +bool DamageSource::equals(DamageSource* source) { + return m_msgId == source->m_msgId && + m_msgWithItemId == source->m_msgWithItemId; +} + +// 4J: Copy function +DamageSource* DamageSource::copy() { return new DamageSource(*this); } \ No newline at end of file diff --git a/Minecraft.World/Util/DamageSource.h b/Minecraft.World/Util/DamageSource.h index 7fe7d0dc0..0c7467372 100644 --- a/Minecraft.World/Util/DamageSource.h +++ b/Minecraft.World/Util/DamageSource.h @@ -1,10 +1,11 @@ #pragma once -class Mob; +class LivingEntity; class Entity; class Arrow; class Fireball; class Player; +class Explosion; #include "../Network/Packets/ChatPacket.h" @@ -20,15 +21,13 @@ public: static DamageSource* fall; static DamageSource* outOfWorld; static DamageSource* genericSource; - static DamageSource* explosion; - static DamageSource* controlledExplosion; static DamageSource* magic; static DamageSource* dragonbreath; static DamageSource* wither; static DamageSource* anvil; static DamageSource* fallingBlock; - static DamageSource* mobAttack(std::shared_ptr mob); + static DamageSource* mobAttack(std::shared_ptr mob); static DamageSource* playerAttack(std::shared_ptr player); static DamageSource* arrow(std::shared_ptr arrow, std::shared_ptr owner); @@ -39,6 +38,7 @@ public: static DamageSource* indirectMagic(std::shared_ptr entity, std::shared_ptr owner); static DamageSource* thorns(std::shared_ptr source); + static DamageSource* explosion(Explosion* explosion); private: bool _bypassArmor; @@ -49,10 +49,13 @@ private: bool _isProjectile; bool _scalesWithDifficulty; bool _isMagic; + bool _isExplosion; public: bool isProjectile(); DamageSource* setProjectile(); + bool isExplosion(); + DamageSource* setExplosion(); bool isBypassArmor(); float getFoodExhaustion(); @@ -60,10 +63,15 @@ public: // std::wstring msgId; ChatPacket::EChatPacketMessage m_msgId; // 4J Made int so we can localise + ChatPacket::EChatPacketMessage + m_msgWithItemId; // 4J: Renamed from m_msgWithSourceId (it was already + // renamed in places, just made consistent) protected: // DamageSource(const std::wstring &msgId); - DamageSource(ChatPacket::EChatPacketMessage msgId); + DamageSource(ChatPacket::EChatPacketMessage msgId, + ChatPacket::EChatPacketMessage msgWithItemId = + ChatPacket::e_ChatCustom); public: virtual ~DamageSource() {} @@ -87,9 +95,13 @@ public: // virtual std::wstring getLocalizedDeathMessage(std::shared_ptr // player); virtual std::shared_ptr getDeathMessagePacket( - std::shared_ptr player); + std::shared_ptr player); bool isFire(); ChatPacket::EChatPacketMessage getMsgId(); // 4J Stu - Used to return String + + // 4J Added + bool equals(DamageSource* source); + virtual DamageSource* copy(); }; \ No newline at end of file diff --git a/Minecraft.World/Util/DelayedRelease.cpp b/Minecraft.World/Util/DelayedRelease.cpp index 4b8fafd63..629178e0c 100644 --- a/Minecraft.World/Util/DelayedRelease.cpp +++ b/Minecraft.World/Util/DelayedRelease.cpp @@ -19,7 +19,7 @@ void DelayedRelease::tick() { } } -bool DelayedRelease::hurt(DamageSource* source, int damage) { return false; } +bool DelayedRelease::hurt(DamageSource* source, float damage) { return false; } void DelayedRelease::defineSynchedData() {} diff --git a/Minecraft.World/Util/DelayedRelease.h b/Minecraft.World/Util/DelayedRelease.h index 42c63af8d..deef6e8c0 100644 --- a/Minecraft.World/Util/DelayedRelease.h +++ b/Minecraft.World/Util/DelayedRelease.h @@ -20,7 +20,7 @@ protected: public: virtual void tick(); - virtual bool hurt(DamageSource* source, int damage); + virtual bool hurt(DamageSource* source, float damage); protected: virtual void defineSynchedData(); diff --git a/Minecraft.World/Util/Direction.cpp b/Minecraft.World/Util/Direction.cpp index 0ba3669fe..bac1a79af 100644 --- a/Minecraft.World/Util/Direction.cpp +++ b/Minecraft.World/Util/Direction.cpp @@ -6,6 +6,8 @@ const int Direction::STEP_X[] = {0, -1, 0, 1}; const int Direction::STEP_Z[] = {1, 0, -1, 0}; +const std::wstring Direction::NAMES[] = {L"SOUTH", L"WEST", L"NORTH", L"EAST"}; + // for [direction] it gives [tile-face] int Direction::DIRECTION_FACING[4] = {Facing::SOUTH, Facing::WEST, Facing::NORTH, Facing::EAST}; @@ -14,16 +16,13 @@ int Direction::DIRECTION_FACING[4] = {Facing::SOUTH, Facing::WEST, int Direction::FACING_DIRECTION[] = {UNDEFINED, UNDEFINED, NORTH, SOUTH, WEST, EAST}; -int Direction::DIRECTION_OPPOSITE[4] = {Direction::NORTH, Direction::EAST, - Direction::SOUTH, Direction::WEST}; +int Direction::DIRECTION_OPPOSITE[4] = {NORTH, EAST, SOUTH, WEST}; // for [direction] it gives [90 degrees clockwise direction] -int Direction::DIRECTION_CLOCKWISE[] = {Direction::WEST, Direction::NORTH, - Direction::EAST, Direction::SOUTH}; +int Direction::DIRECTION_CLOCKWISE[] = {WEST, NORTH, EAST, SOUTH}; // for [direction] it gives [90 degrees counter clockwise direction] -int Direction::DIRECTION_COUNTER_CLOCKWISE[] = { - Direction::EAST, Direction::SOUTH, Direction::WEST, Direction::NORTH}; +int Direction::DIRECTION_COUNTER_CLOCKWISE[] = {EAST, SOUTH, WEST, NORTH}; int Direction::RELATIVE_DIRECTION_FACING[4][6] = { // south @@ -38,3 +37,26 @@ int Direction::RELATIVE_DIRECTION_FACING[4][6] = { // east {Facing::UP, Facing::DOWN, Facing::WEST, Facing::EAST, Facing::SOUTH, Facing::NORTH}}; + +int Direction::getDirection(double xd, double zd) { + if (Mth::abs((float)xd) > Mth::abs((float)zd)) { + if (xd > 0) { + return WEST; + } else { + return EAST; + } + } else { + if (zd > 0) { + return NORTH; + } else { + return SOUTH; + } + } +} + +int Direction::getDirection(int x0, int z0, int x1, int z1) { + int xd = x0 - x1; + int zd = z0 - z1; + + return getDirection(xd, zd); +} \ No newline at end of file diff --git a/Minecraft.World/Util/Direction.h b/Minecraft.World/Util/Direction.h index c1182f1dd..9204bb6a8 100644 --- a/Minecraft.World/Util/Direction.h +++ b/Minecraft.World/Util/Direction.h @@ -11,6 +11,9 @@ public: static const int STEP_X[]; static const int STEP_Z[]; + static const std::wstring NAMES[]; + ; + // for [direction] it gives [tile-face] static int DIRECTION_FACING[]; @@ -28,4 +31,7 @@ public: // for [direction][world-facing] it gives [tile-facing] static int RELATIVE_DIRECTION_FACING[4][6]; + + static int getDirection(double xd, double zd); + static int getDirection(int x0, int z0, int x1, int z1); }; \ No newline at end of file diff --git a/Minecraft.World/Util/Facing.cpp b/Minecraft.World/Util/Facing.cpp index b2fcf5aa3..4476da038 100644 --- a/Minecraft.World/Util/Facing.cpp +++ b/Minecraft.World/Util/Facing.cpp @@ -8,3 +8,6 @@ const int Facing::STEP_X[6] = {0, 0, 0, 0, -1, 1}; const int Facing::STEP_Y[6] = {-1, 1, 0, 0, 0, 0}; const int Facing::STEP_Z[6] = {0, 0, -1, 1, 0, 0}; + +const std::wstring Facing::NAMES[] = {L"DOWN", L"UP", L"NORTH", + L"SOUTH", L"WEST", L"EAST"}; \ No newline at end of file diff --git a/Minecraft.World/Util/Facing.h b/Minecraft.World/Util/Facing.h index 62dcc49b1..5f4ce831e 100644 --- a/Minecraft.World/Util/Facing.h +++ b/Minecraft.World/Util/Facing.h @@ -13,4 +13,6 @@ public: static const int STEP_X[6]; static const int STEP_Y[6]; static const int STEP_Z[6]; + + static const std::wstring NAMES[]; }; \ No newline at end of file diff --git a/Minecraft.World/Util/FoodConstants.cpp b/Minecraft.World/Util/FoodConstants.cpp index 633c7ff75..0b011df5a 100644 --- a/Minecraft.World/Util/FoodConstants.cpp +++ b/Minecraft.World/Util/FoodConstants.cpp @@ -27,6 +27,7 @@ const float FoodConstants::FOOD_SATURATION_MAX = 1.0f; const float FoodConstants::FOOD_SATURATION_SUPERNATURAL = 1.2f; // some exhaustion guidelines +const float FoodConstants::EXHAUSTION_HEAL = 3.0f; const float FoodConstants::EXHAUSTION_JUMP = .2f; const float FoodConstants::EXHAUSTION_SPRINT_JUMP = FoodConstants::EXHAUSTION_JUMP * 4; diff --git a/Minecraft.World/Util/FoodConstants.h b/Minecraft.World/Util/FoodConstants.h index 7fc8bb8e6..0434069a3 100644 --- a/Minecraft.World/Util/FoodConstants.h +++ b/Minecraft.World/Util/FoodConstants.h @@ -25,6 +25,7 @@ public: static const float FOOD_SATURATION_SUPERNATURAL; // some exhaustion guidelines + static const float EXHAUSTION_HEAL; static const float EXHAUSTION_JUMP; static const float EXHAUSTION_SPRINT_JUMP; static const float EXHAUSTION_MINE; diff --git a/Minecraft.World/Util/HashExtension.h b/Minecraft.World/Util/HashExtension.h index 49fd13277..d9a40d799 100644 --- a/Minecraft.World/Util/HashExtension.h +++ b/Minecraft.World/Util/HashExtension.h @@ -7,8 +7,8 @@ namespace tr1 { template class hash > { public: - size_t operator()(const std::shared_ptr& key) const { - return (size_t)key.get(); + std::size_t operator()(const std::shared_ptr& key) const { + return (std::size_t)key.get(); } }; } // namespace tr1 diff --git a/Minecraft.World/Util/HitResult.cpp b/Minecraft.World/Util/HitResult.cpp index 0b868d1ad..dfa52bf72 100644 --- a/Minecraft.World/Util/HitResult.cpp +++ b/Minecraft.World/Util/HitResult.cpp @@ -4,7 +4,7 @@ #include "HitResult.h" HitResult::HitResult(int x, int y, int z, int f, Vec3* pos) { - this->type = TILE; + type = TILE; this->x = x; this->y = y; this->z = z; @@ -15,7 +15,7 @@ HitResult::HitResult(int x, int y, int z, int f, Vec3* pos) { } HitResult::HitResult(std::shared_ptr entity) { - this->type = ENTITY; + type = ENTITY; this->entity = entity; pos = Vec3::newTemp(entity->x, entity->y, entity->z); diff --git a/Minecraft.World/Util/HtmlString.cpp b/Minecraft.World/Util/HtmlString.cpp new file mode 100644 index 000000000..8e0d06b95 --- /dev/null +++ b/Minecraft.World/Util/HtmlString.cpp @@ -0,0 +1,52 @@ +#include "../Platform/stdafx.h" +#include "HtmlString.h" +#include + +HtmlString::HtmlString(std::wstring text, eMinecraftColour hexColor, + bool italics, bool indent) { + this->text = escapeXML(text); + this->color = hexColor; + this->italics = italics; + this->indent = indent; +} + +std::wstring HtmlString::ToString() { + std::wstringstream ss; + + if (indent) { + ss << L"  "; + } + + if (italics) { + ss << ""; + } + + eMinecraftColour color = + this->color == eMinecraftColour_NOT_SET ? eHTMLColor_7 : this->color; + + ss << L"" << text << ""; + + if (italics) { + ss << ""; + } + + return ss.str(); +} + +std::wstring HtmlString::Compose(std::vector* strings) { + if (strings == NULL) return L""; + + std::wstringstream ss; + + for (int i = 0; i < strings->size(); i++) { + ss << strings->at(i).ToString(); + + // Add a break if there's another line + if (i + 1 < strings->size()) { + ss << L"
"; + } + } + + return ss.str(); +} \ No newline at end of file diff --git a/Minecraft.World/Util/HtmlString.h b/Minecraft.World/Util/HtmlString.h new file mode 100644 index 000000000..83e67244a --- /dev/null +++ b/Minecraft.World/Util/HtmlString.h @@ -0,0 +1,17 @@ +#pragma once + +// 4J: Simple std::string wrapper that includes basic formatting information +class HtmlString { +public: + std::wstring text; // Text content of std::string + eMinecraftColour color; // Hex color + bool italics; // Show text in italics + bool indent; // Indent text + + HtmlString(std::wstring text, + eMinecraftColour color = eMinecraftColour_NOT_SET, + bool italics = false, bool indent = false); + std::wstring ToString(); + + static std::wstring Compose(std::vector* strings); +}; \ No newline at end of file diff --git a/Minecraft.World/Util/JavaMath.cpp b/Minecraft.World/Util/JavaMath.cpp index 80c212733..d83332c8e 100644 --- a/Minecraft.World/Util/JavaMath.cpp +++ b/Minecraft.World/Util/JavaMath.cpp @@ -71,4 +71,4 @@ double Math::wrapDegrees(double input) { if (input >= 180.0) input -= 360.0; if (input < -180.0) input += 360.0; return input; -} +} \ No newline at end of file diff --git a/Minecraft.World/Util/Language.h b/Minecraft.World/Util/Language.h index e47f8deb5..68afb12a7 100644 --- a/Minecraft.World/Util/Language.h +++ b/Minecraft.World/Util/Language.h @@ -3,7 +3,6 @@ class Language { private: static Language* singleton; - std::unordered_map translateTable; public: Language(); @@ -12,4 +11,4 @@ public: std::wstring getElement(const std::wstring& elementId, va_list args); std::wstring getElementName(const std::wstring& elementId); std::wstring getElementDescription(const std::wstring& elementId); -}; +}; \ No newline at end of file diff --git a/Minecraft.World/Util/Mth.cpp b/Minecraft.World/Util/Mth.cpp index 5a080a71c..cff6d8a96 100644 --- a/Minecraft.World/Util/Mth.cpp +++ b/Minecraft.World/Util/Mth.cpp @@ -1,12 +1,13 @@ #include "../Platform/stdafx.h" #include "Mth.h" #include "Random.h" +#include "StringHelpers.h" const int Mth::BIG_ENOUGH_INT = 1024; const float Mth::BIG_ENOUGH_FLOAT = BIG_ENOUGH_INT; -const float Mth::RAD_TO_GRAD = PI / 180.0f; const float Mth::DEGRAD = PI / 180.0f; const float Mth::RADDEG = 180.0f / PI; +const float Mth::RAD_TO_GRAD = PI / 180.0f; float* Mth::_sin = NULL; @@ -118,6 +119,16 @@ int Mth::nextInt(Random* random, int minInclusive, int maxInclusive) { return random->nextInt(maxInclusive - minInclusive + 1) + minInclusive; } +float Mth::nextFloat(Random* random, float min, float max) { + if (min >= max) return min; + return (random->nextFloat() * (max - min)) + min; +} + +double Mth::nextDouble(Random* random, double min, double max) { + if (min >= max) return min; + return (random->nextDouble() * (max - min)) + min; +} + float Mth::wrapDegrees(float input) { // input %= 360; while (input >= 180) { @@ -140,7 +151,62 @@ double Mth::wrapDegrees(double input) { return input; } +int Mth::getInt(const std::wstring& input, int def) { + int result = def; + + result = _fromString(input); + + return result; +} + +int Mth::getInt(const std::wstring& input, int def, int min) { + int result = def; + + result = _fromString(input); + + if (result < min) result = min; + return result; +} + +double Mth::getDouble(const std::wstring& input, double def) { + double result = def; + + result = _fromString(input); + + return result; +} + +double Mth::getDouble(const std::wstring& input, double def, double min) { + double result = def; + + result = _fromString(input); + + if (result < min) result = min; + return result; +} + +// 4J Changed this to remove the use of the actuall UUID type +std::wstring Mth::createInsecureUUID(Random* random) { + wchar_t output[33]; + output[32] = 0; + int64_t high = (random->nextLong() & ~UUID_VERSION) | UUID_VERSION_TYPE_4; + int64_t low = (random->nextLong() & ~UUID_VARIANT) | UUID_VARIANT_2; + for (int i = 0; i < 16; i++) { + wchar_t nybbleHigh = high & 0xf; + wchar_t nybbleLow = low & 0xf; + nybbleHigh = + (nybbleHigh > 9) ? (nybbleHigh + (L'a' - 10)) : (nybbleHigh + L'0'); + nybbleLow = + (nybbleLow > 9) ? (nybbleLow + (L'a' - 10)) : (nybbleLow + L'0'); + high >>= 4; + low >>= 4; + output[31 - i] = nybbleLow; + output[15 - i] = nybbleHigh; + } + return std::wstring(output); +} + // 4J Added bool Mth::almostEquals(double double1, double double2, double precision) { return (std::abs(double1 - double2) <= precision); -} +} \ No newline at end of file diff --git a/Minecraft.World/Util/Mth.h b/Minecraft.World/Util/Mth.h index 3802ef3be..c26851814 100644 --- a/Minecraft.World/Util/Mth.h +++ b/Minecraft.World/Util/Mth.h @@ -5,12 +5,15 @@ private: static const int BIG_ENOUGH_INT; static const float BIG_ENOUGH_FLOAT; -public: - static const float RAD_TO_GRAD; - public: static const float DEGRAD; static const float RADDEG; + static const float RAD_TO_GRAD; + + static const int64_t UUID_VERSION = 0x000000000000f000L; + static const int64_t UUID_VERSION_TYPE_4 = 0x0000000000004000L; + static const int64_t UUID_VARIANT = 0xc000000000000000L; + static const int64_t UUID_VARIANT_2 = 0x8000000000000000L; private: static float* _sin; @@ -37,8 +40,15 @@ public: static double asbMax(double a, double b); static int intFloorDiv(int a, int b); static int nextInt(Random* random, int minInclusive, int maxInclusive); + static float nextFloat(Random* random, float min, float max); + static double nextDouble(Random* random, double min, double max); static float wrapDegrees(float input); static double wrapDegrees(double input); + static std::wstring createInsecureUUID(Random* random); + static int getInt(const std::wstring& input, int def); + static int getInt(const std::wstring& input, int def, int min); + static double getDouble(const std::wstring& input, double def); + static double getDouble(const std::wstring& input, double def, double min); // 4J Added static bool almostEquals(double double1, double double2, double precision); diff --git a/Minecraft.World/Util/ParticleTypes.h b/Minecraft.World/Util/ParticleTypes.h index eebf07048..f04288336 100644 --- a/Minecraft.World/Util/ParticleTypes.h +++ b/Minecraft.World/Util/ParticleTypes.h @@ -1,6 +1,6 @@ #pragma once -// 4J-PB added to avoid string compares on adding particles +// 4J-PB added to avoid std::string compares on adding particles enum ePARTICLE_TYPE { eParticleType_bubble, eParticleType_smoke, @@ -27,7 +27,9 @@ enum ePARTICLE_TYPE { eParticleType_largeexplode, eParticleType_townaura, eParticleType_spell, + eParticleType_witchMagic, eParticleType_mobSpell, + eParticleType_mobSpellAmbient, eParticleType_instantSpell, eParticleType_magicCrit, eParticleType_dripWater, @@ -38,6 +40,7 @@ enum ePARTICLE_TYPE { // particle but are actually end related entities eParticleType_angryVillager, eParticleType_happyVillager, + eParticleType_fireworksspark, // 4J-JEV: In the java, the particle name was used to sneak parameters in // for the Terrain and IconCrack particle constructors. diff --git a/Minecraft.World/Util/Pos.cpp b/Minecraft.World/Util/Pos.cpp index 931bf3e41..2775cecfa 100644 --- a/Minecraft.World/Util/Pos.cpp +++ b/Minecraft.World/Util/Pos.cpp @@ -11,9 +11,9 @@ Pos::Pos(int x, int y, int z) { } Pos::Pos(Pos* position) { - this->x = position->x; - this->y = position->y; - this->z = position->z; + x = position->x; + y = position->y; + z = position->z; } //@Override @@ -54,9 +54,9 @@ void Pos::set(int x, int y, int z) { } void Pos::set(Pos* pos) { - this->x = pos->x; - this->y = pos->y; - this->z = pos->z; + x = pos->x; + y = pos->y; + z = pos->z; } Pos* Pos::above() { return new Pos(x, y + 1, z); } @@ -90,54 +90,56 @@ void Pos::move(int x, int y, int z) { } void Pos::move(Pos pos) { - this->x += pos.x; - this->y += pos.y; - this->z += pos.z; + x += pos.x; + y += pos.y; + z += pos.z; } -void Pos::moveX(int steps) { this->x += steps; } +void Pos::moveX(int steps) { x += steps; } -void Pos::moveY(int steps) { this->y += steps; } +void Pos::moveY(int steps) { y += steps; } -void Pos::moveZ(int steps) { this->z += steps; } +void Pos::moveZ(int steps) { z += steps; } -void Pos::moveUp(int steps) { this->y += steps; } +void Pos::moveUp(int steps) { y += steps; } -void Pos::moveUp() { this->y++; } +void Pos::moveUp() { y++; } -void Pos::moveDown(int steps) { this->y -= steps; } +void Pos::moveDown(int steps) { y -= steps; } -void Pos::moveDown() { this->y--; } +void Pos::moveDown() { y--; } -void Pos::moveEast(int steps) { this->x += steps; } +void Pos::moveEast(int steps) { x += steps; } -void Pos::moveEast() { this->x++; } +void Pos::moveEast() { x++; } -void Pos::moveWest(int steps) { this->x -= steps; } +void Pos::moveWest(int steps) { x -= steps; } -void Pos::moveWest() { this->x--; } +void Pos::moveWest() { x--; } -void Pos::moveNorth(int steps) { this->z -= steps; } +void Pos::moveNorth(int steps) { z -= steps; } -void Pos::moveNorth() { this->z--; } +void Pos::moveNorth() { z--; } -void Pos::moveSouth(int steps) { this->z += steps; } +void Pos::moveSouth(int steps) { z += steps; } -void Pos::moveSouth() { this->z++; } +void Pos::moveSouth() { z++; } double Pos::dist(int x, int y, int z) { - int dx = this->x - x; - int dy = this->y - y; - int dz = this->z - z; + double dx = this->x - x; + double dy = this->y - y; + double dz = this->z - z; - return sqrt((double)dx * dx + dy * dy + dz * dz); + return sqrt(dx * dx + dy * dy + dz * dz); } double Pos::dist(Pos* pos) { return dist(pos->x, pos->y, pos->z); } float Pos::distSqr(int x, int y, int z) { - int dx = this->x - x; - int dy = this->y - y; - int dz = this->z - z; + float dx = this->x - x; + float dy = this->y - y; + float dz = this->z - z; return dx * dx + dy * dy + dz * dz; -} \ No newline at end of file +} + +float Pos::distSqr(Pos* pos) { return distSqr(pos->x, pos->y, pos->z); } \ No newline at end of file diff --git a/Minecraft.World/Util/Pos.h b/Minecraft.World/Util/Pos.h index d7287aea1..0d9de3e25 100644 --- a/Minecraft.World/Util/Pos.h +++ b/Minecraft.World/Util/Pos.h @@ -22,75 +22,44 @@ public: bool equals(void* other); int hashCode(); - int compareTo(Pos* pos); - Pos* offset(int x, int y, int z); - void set(int x, int y, int z); - void set(Pos* pos); Pos* above(); - Pos* above(int steps); - Pos* below(); - Pos* below(int steps); - Pos* north(); - Pos* north(int steps); - Pos* south(); - Pos* south(int steps); - Pos* west(); - Pos* west(int steps); - Pos* east(); - Pos* east(int steps); void move(int x, int y, int z); - void move(Pos pos); - void moveX(int steps); - void moveY(int steps); - void moveZ(int steps); - void moveUp(int steps); - void moveUp(); - void moveDown(int steps); - void moveDown(); - void moveEast(int steps); - void moveEast(); - void moveWest(int steps); - void moveWest(); - void moveNorth(int steps); - void moveNorth(); - void moveSouth(int steps); - void moveSouth(); double dist(int x, int y, int z); - double dist(Pos* pos); float distSqr(int x, int y, int z); + float distSqr(Pos* pos); }; \ No newline at end of file diff --git a/Minecraft.World/Util/SharedConstants.cpp b/Minecraft.World/Util/SharedConstants.cpp index 497160a5f..cd2b1f128 100644 --- a/Minecraft.World/Util/SharedConstants.cpp +++ b/Minecraft.World/Util/SharedConstants.cpp @@ -3,7 +3,7 @@ #include "../IO/Streams/InputOutputStream.h" #include "SharedConstants.h" -const std::wstring SharedConstants::VERSION_STRING = L"1.2.3"; +const std::wstring SharedConstants::VERSION_STRING = L"1.6.4"; const bool SharedConstants::TEXTURE_LIGHTING = true; std::wstring SharedConstants::readAcceptableChars() { @@ -43,8 +43,7 @@ bool SharedConstants::isAllowedChatCharacter(char ch) { return true; } -std::wstring SharedConstants::acceptableLetters = - SharedConstants::readAcceptableChars(); +std::wstring SharedConstants::acceptableLetters; void SharedConstants::staticCtor() { acceptableLetters = readAcceptableChars(); diff --git a/Minecraft.World/Util/SharedConstants.h b/Minecraft.World/Util/SharedConstants.h index 9c364c19c..94c0e1dc4 100644 --- a/Minecraft.World/Util/SharedConstants.h +++ b/Minecraft.World/Util/SharedConstants.h @@ -6,14 +6,16 @@ class SharedConstants { public: static void staticCtor(); static const std::wstring VERSION_STRING; - static const int NETWORK_PROTOCOL_VERSION = 39; + static const int NETWORK_PROTOCOL_VERSION = 78; + static const bool INGAME_DEBUG_OUTPUT = false; // NOT texture resolution. How many sub-blocks each block face is made up // of. 4J Added for texture packs static const int WORLD_RESOLUTION = 16; static bool isAllowedChatCharacter(char ch); - // why private?????????? + +private: static std::wstring readAcceptableChars(); public: diff --git a/Minecraft.World/Util/SoundTypes.h b/Minecraft.World/Util/SoundTypes.h index 8d95728b4..bbe203f4e 100644 --- a/Minecraft.World/Util/SoundTypes.h +++ b/Minecraft.World/Util/SoundTypes.h @@ -56,7 +56,7 @@ enum eSOUND_TYPE { eSoundType_MOB_CAT_PURR, eSoundType_MOB_CAT_PURREOW, eSoundType_MOB_CAT_MEOW, - eSoundType_MOB_CAT_HITT, + eSoundType_MOB_CAT_HIT, // eSoundType_MOB_IRONGOLEM_THROW, // eSoundType_MOB_IRONGOLEM_HIT, // eSoundType_MOB_IRONGOLEM_DEATH, @@ -84,7 +84,7 @@ enum eSOUND_TYPE { eSoundType_AMBIENT_CAVE_CAVE, #ifdef _XBOX eSoundType_AMBIENT_CAVE_CAVE2, //- fixed version of eSoundType_CAVE_CAVE, - //without the two 192k sounds + // without the two 192k sounds #endif eSoundType_PORTAL_PORTAL, // 4J-PB - adding some that were still text in the code @@ -147,6 +147,71 @@ enum eSOUND_TYPE { eSoundType_DIG_STONE, eSoundType_DIG_WOOD, + // 1.6.4 + eSoundType_FIREWORKS_LAUNCH, + eSoundType_FIREWORKS_BLAST, + eSoundType_FIREWORKS_BLAST_FAR, + eSoundType_FIREWORKS_LARGE_BLAST, + eSoundType_FIREWORKS_LARGE_BLAST_FAR, + eSoundType_FIREWORKS_TWINKLE, + eSoundType_FIREWORKS_TWINKLE_FAR, + + eSoundType_MOB_BAT_IDLE, + eSoundType_MOB_BAT_HURT, + eSoundType_MOB_BAT_DEATH, + eSoundType_MOB_BAT_TAKEOFF, + + eSoundType_MOB_WITHER_SPAWN, + eSoundType_MOB_WITHER_IDLE, //"mob.wither.idle"; + eSoundType_MOB_WITHER_HURT, //"mob.wither.hurt"; + eSoundType_MOB_WITHER_DEATH, //"mob.wither.death"; + eSoundType_MOB_WITHER_SHOOT, //"mob.wither.shoot"; + + eSoundType_MOB_COW_STEP, + eSoundType_MOB_CHICKEN_STEP, + eSoundType_MOB_PIG_STEP, + eSoundType_MOB_ENDERMAN_STARE, + eSoundType_MOB_ENDERMAN_SCREAM, + eSoundType_MOB_SHEEP_SHEAR, + eSoundType_MOB_SHEEP_STEP, + eSoundType_MOB_SKELETON_DEATH, + eSoundType_MOB_SKELETON_STEP, + eSoundType_MOB_SPIDER_STEP, + eSoundType_MOB_WOLF_STEP, + eSoundType_MOB_ZOMBIE_STEP, + eSoundType_LIQUID_SWIM, + eSoundType_MOB_HORSE_LAND, + eSoundType_MOB_HORSE_ARMOR, + eSoundType_MOB_HORSE_LEATHER, + eSoundType_MOB_HORSE_ZOMBIE_DEATH, + eSoundType_MOB_HORSE_SKELETON_DEATH, + eSoundType_MOB_HORSE_DONKEY_DEATH, + eSoundType_MOB_HORSE_DEATH, + eSoundType_MOB_HORSE_ZOMBIE_HIT, + eSoundType_MOB_HORSE_SKELETON_HIT, + eSoundType_MOB_HORSE_DONKEY_HIT, + eSoundType_MOB_HORSE_HIT, + eSoundType_MOB_HORSE_ZOMBIE_IDLE, + eSoundType_MOB_HORSE_SKELETON_IDLE, + eSoundType_MOB_HORSE_DONKEY_IDLE, + eSoundType_MOB_HORSE_IDLE, + eSoundType_MOB_HORSE_DONKEY_ANGRY, + eSoundType_MOB_HORSE_ANGRY, + eSoundType_MOB_HORSE_GALLOP, + eSoundType_MOB_HORSE_BREATHE, + eSoundType_MOB_HORSE_WOOD, + eSoundType_MOB_HORSE_SOFT, + eSoundType_MOB_HORSE_JUMP, + eSoundType_MOB_WITCH_IDLE, + eSoundType_MOB_WITCH_HURT, + eSoundType_MOB_WITCH_DEATH, + eSoundType_MOB_SLIME_BIG, + eSoundType_MOB_SLIME_SMALL, + eSoundType_EATING, + eSoundType_RANDOM_LEVELUP, + + eSoundType_FIRE_NEWIGNITE, + eSoundType_MAX }; diff --git a/Minecraft.World/Util/Vec3.cpp b/Minecraft.World/Util/Vec3.cpp index bc9f5266c..4e42b99a3 100644 --- a/Minecraft.World/Util/Vec3.cpp +++ b/Minecraft.World/Util/Vec3.cpp @@ -172,9 +172,9 @@ void Vec3::xRot(float degs) { double yy = y * _cos + z * _sin; double zz = z * _cos - y * _sin; - this->x = xx; - this->y = yy; - this->z = zz; + x = xx; + y = yy; + z = zz; } void Vec3::yRot(float degs) { @@ -186,9 +186,9 @@ void Vec3::yRot(float degs) { double yy = y; double zz = z * _cos - x * _sin; - this->x = xx; - this->y = yy; - this->z = zz; + x = xx; + y = yy; + z = zz; } void Vec3::zRot(float degs) { @@ -200,9 +200,9 @@ void Vec3::zRot(float degs) { double yy = y * _cos - x * _sin; double zz = z; - this->x = xx; - this->y = yy; - this->z = zz; + x = xx; + y = yy; + z = zz; } // Returns 0 if this point is within the box @@ -229,3 +229,24 @@ double Vec3::distanceTo(AABB* box) { return sqrt(xd * xd + yd * yd + zd * zd); } + +Vec3* Vec3::closestPointOnLine(Vec3* p1, Vec3* p2) { + Vec3* diff = newTemp(x - p1->x, y - p1->y, z - p1->z); + Vec3* dir = newTemp(p2->x - p1->x, p2->y - p1->y, p2->z - p1->z); + float dot1 = diff->dot(dir); + if (dot1 <= 0.0f) return p1; + + float dot2 = dir->dot(dir); + + if (dot2 <= dot1) return p2; + + float t = dot1 / dot2; + return newTemp(p1->x + t * dir->x, p1->y + t * dir->y, p1->z + t * dir->z); +} + +double Vec3::distanceFromLine(Vec3* p1, Vec3* p2) { + Vec3* closestPoint = closestPointOnLine(p1, p2); + Vec3* diff = + newTemp(x - closestPoint->x, y - closestPoint->y, z - closestPoint->z); + return diff->length(); +} diff --git a/Minecraft.World/Util/Vec3.h b/Minecraft.World/Util/Vec3.h index 7a81f818d..bc1239d81 100644 --- a/Minecraft.World/Util/Vec3.h +++ b/Minecraft.World/Util/Vec3.h @@ -57,4 +57,7 @@ public: // 4J Added double distanceTo(AABB* box); -}; + + Vec3* closestPointOnLine(Vec3* p1, Vec3* p2); + double distanceFromLine(Vec3* p1, Vec3* p2); +}; \ No newline at end of file diff --git a/Minecraft.World/Util/WeighedTreasure.cpp b/Minecraft.World/Util/WeighedTreasure.cpp index 1011567f5..8b1a98b86 100644 --- a/Minecraft.World/Util/WeighedTreasure.cpp +++ b/Minecraft.World/Util/WeighedTreasure.cpp @@ -22,7 +22,7 @@ WeighedTreasure::WeighedTreasure(std::shared_ptr item, } void WeighedTreasure::addChestItems(Random* random, WeighedTreasureArray items, - std::shared_ptr dest, + std::shared_ptr dest, int numRolls) { for (int r = 0; r < numRolls; r++) { WeighedTreasure* treasure = diff --git a/Minecraft.World/Util/WeighedTreasure.h b/Minecraft.World/Util/WeighedTreasure.h index 2205fd65d..5bc65fcc7 100644 --- a/Minecraft.World/Util/WeighedTreasure.h +++ b/Minecraft.World/Util/WeighedTreasure.h @@ -15,8 +15,7 @@ public: int maxCount, int weight); static void addChestItems(Random* random, WeighedTreasureArray items, - std::shared_ptr dest, - int numRolls); + std::shared_ptr dest, int numRolls); static void addDispenserItems(Random* random, WeighedTreasureArray items, std::shared_ptr dest, int numRolls);