diff options
author | madmaxoft <github@xoft.cz> | 2013-11-13 11:08:51 +0100 |
---|---|---|
committer | madmaxoft <github@xoft.cz> | 2013-11-13 11:08:51 +0100 |
commit | 293051eca89351181f11443e1785617ab58459c8 (patch) | |
tree | 50c637b3c2ac3f1848610623156ce96be1b91be5 /source | |
parent | cWindow: Fixed item dupe glitch with painting (#278) (diff) | |
parent | Bundled fixes [SEE DESC] (diff) | |
download | cuberite-293051eca89351181f11443e1785617ab58459c8.tar cuberite-293051eca89351181f11443e1785617ab58459c8.tar.gz cuberite-293051eca89351181f11443e1785617ab58459c8.tar.bz2 cuberite-293051eca89351181f11443e1785617ab58459c8.tar.lz cuberite-293051eca89351181f11443e1785617ab58459c8.tar.xz cuberite-293051eca89351181f11443e1785617ab58459c8.tar.zst cuberite-293051eca89351181f11443e1785617ab58459c8.zip |
Diffstat (limited to 'source')
-rw-r--r-- | source/BlockEntities/DropSpenserEntity.cpp | 2 | ||||
-rw-r--r-- | source/BlockEntities/JukeboxEntity.cpp | 6 | ||||
-rw-r--r-- | source/BoundingBox.cpp | 4 | ||||
-rw-r--r-- | source/Chunk.cpp | 13 | ||||
-rw-r--r-- | source/ChunkMap.cpp | 2 | ||||
-rw-r--r-- | source/ClientHandle.cpp | 4 | ||||
-rw-r--r-- | source/Entities/Pickup.cpp | 7 | ||||
-rw-r--r-- | source/Entities/ProjectileEntity.cpp | 110 | ||||
-rw-r--r-- | source/Entities/ProjectileEntity.h | 14 | ||||
-rw-r--r-- | source/Items/ItemBow.h | 2 | ||||
-rw-r--r-- | source/Mobs/Horse.cpp | 8 | ||||
-rw-r--r-- | source/Mobs/Monster.cpp | 95 | ||||
-rw-r--r-- | source/Mobs/Monster.h | 7 | ||||
-rw-r--r-- | source/Protocol/Protocol132.cpp | 6 | ||||
-rw-r--r-- | source/Protocol/Protocol14x.cpp | 6 | ||||
-rw-r--r-- | source/Protocol/Protocol17x.cpp | 52 | ||||
-rw-r--r-- | source/Simulator/FloodyFluidSimulator.cpp | 8 | ||||
-rw-r--r-- | source/World.cpp | 9 |
18 files changed, 264 insertions, 91 deletions
diff --git a/source/BlockEntities/DropSpenserEntity.cpp b/source/BlockEntities/DropSpenserEntity.cpp index 25def9999..823ed598f 100644 --- a/source/BlockEntities/DropSpenserEntity.cpp +++ b/source/BlockEntities/DropSpenserEntity.cpp @@ -96,7 +96,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk) case E_META_DROPSPENSER_FACING_ZM: SmokeDir = 1; break; case E_META_DROPSPENSER_FACING_ZP: SmokeDir = 7; break; } - m_World->BroadcastSoundParticleEffect(2000, m_PosX * 8, m_PosY * 8, m_PosZ * 8, SmokeDir); + m_World->BroadcastSoundParticleEffect(2000, m_PosX, m_PosY, m_PosZ, SmokeDir); m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.0f); // Update the UI window, if open: diff --git a/source/BlockEntities/JukeboxEntity.cpp b/source/BlockEntities/JukeboxEntity.cpp index ec6d13282..1288719f6 100644 --- a/source/BlockEntities/JukeboxEntity.cpp +++ b/source/BlockEntities/JukeboxEntity.cpp @@ -57,7 +57,7 @@ void cJukeboxEntity::UsedBy(cPlayer * a_Player) void cJukeboxEntity::PlayRecord( void ) { - m_World->BroadcastSoundParticleEffect(1005, m_PosX * 8, m_PosY * 8, m_PosZ * 8, m_Record); + m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, m_Record); } @@ -68,8 +68,8 @@ void cJukeboxEntity::EjectRecord( void ) { cItems Drops; Drops.push_back(cItem(m_Record, 1, 0)); - m_World->SpawnItemPickups(Drops, m_PosX, m_PosY+1, m_PosZ); - m_World->BroadcastSoundParticleEffect(1005, m_PosX * 8, m_PosY * 8, m_PosZ * 8, 0); + m_World->SpawnItemPickups(Drops, m_PosX + 0.5, m_PosY + 1, m_PosZ + 0.5, 8); + m_World->BroadcastSoundParticleEffect(1005, m_PosX, m_PosY, m_PosZ, 0); } diff --git a/source/BoundingBox.cpp b/source/BoundingBox.cpp index d8a1bc679..02602992e 100644 --- a/source/BoundingBox.cpp +++ b/source/BoundingBox.cpp @@ -243,11 +243,11 @@ bool cBoundingBox::CalcLineIntersection(const Vector3d & a_Min, const Vector3d & { // The starting point is inside the bounding box. a_LineCoeff = 0; - a_Face = BLOCK_FACE_YM; // Make it look as the top face was hit, although none really are. + a_Face = BLOCK_FACE_NONE; // No faces hit return true; } - char Face = 0; + char Face = BLOCK_FACE_NONE; double Coeff = Vector3d::NO_INTERSECTION; // Check each individual bbox face for intersection with the line, remember the one with the lowest coeff diff --git a/source/Chunk.cpp b/source/Chunk.cpp index be75eae41..cfdcc783c 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -1679,9 +1679,9 @@ void cChunk::CollectPickupsByPlayer(cPlayer * a_Player) for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr) { - if (!(*itr)->IsPickup()) + if ((!(*itr)->IsPickup()) && (!(*itr)->IsProjectile())) { - continue; // Only pickups + continue; // Only pickups and projectiles } float DiffX = (float)((*itr)->GetPosX() - PosX ); float DiffY = (float)((*itr)->GetPosY() - PosY ); @@ -1695,7 +1695,14 @@ void cChunk::CollectPickupsByPlayer(cPlayer * a_Player) ); */ MarkDirty(); - (reinterpret_cast<cPickup *>(*itr))->CollectedBy( a_Player ); + if ((*itr)->IsPickup()) + { + (reinterpret_cast<cPickup *>(*itr))->CollectedBy(a_Player); + } + else + { + (reinterpret_cast<cProjectileEntity *>(*itr))->CollectedBy(a_Player); + } } else if (SqrDist < 5 * 5) { diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index d9de24cff..73a16dbb4 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -613,7 +613,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S cCSLock Lock(m_CSLayers); int ChunkX, ChunkZ; - cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ); + cChunkDef::BlockToChunk(a_SrcX, a_SrcZ, ChunkX, ChunkZ); cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); if (Chunk == NULL) { diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 3548b4035..f8fd4a8b7 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -729,7 +729,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo if (a_OldBlock == E_BLOCK_AIR) { - LOGD("Digged air? wtf?"); + LOGD("Dug air - what the function?"); return; } @@ -738,7 +738,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo // The ItemHandler is also responsible for spawning the pickups BlockHandler(a_OldBlock)->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ); - World->BroadcastSoundParticleEffect(2001, a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, a_OldBlock, this); + World->BroadcastSoundParticleEffect(2001, a_BlockX, a_BlockY, a_BlockZ, a_OldBlock, this); World->DigBlock(a_BlockX, a_BlockY, a_BlockZ); cRoot::Get()->GetPluginManager()->CallHookPlayerBrokenBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta); diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp index bc8abd204..f8aae9703 100644 --- a/source/Entities/Pickup.cpp +++ b/source/Entities/Pickup.cpp @@ -31,8 +31,9 @@ cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_It , m_bCollected( false ) , m_bIsPlayerCreated( IsPlayerCreated ) { - m_MaxHealth = 5; - m_Health = 5; + SetGravity(-10.5f); + SetMaxHealth(5); + SetHealth(5); SetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ); } @@ -145,6 +146,8 @@ bool cPickup::CollectedBy(cPlayer * a_Dest) { m_Item.m_ItemCount -= NumAdded; m_World->BroadcastCollectPickup(*this, *a_Dest); + // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) + m_World->BroadcastSoundEffect("random.pop",(int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); if (m_Item.m_ItemCount == 0) { // All of the pickup has been collected, schedule the pickup for destroying diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 1d5532718..c63b9523b 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -371,6 +371,16 @@ void cProjectileEntity::SpawnOn(cClientHandle & a_Client) +void cProjectileEntity::CollectedBy(cPlayer * a_Dest) +{ + // Overriden in arrow + UNUSED(a_Dest); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cArrowEntity: @@ -378,7 +388,10 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5), m_PickupState(psNoPickup), m_DamageCoeff(2), - m_IsCritical(false) + m_IsCritical(false), + m_Timer(0), + m_bIsCollected(false), + m_HitBlockPos(Vector3i(0, 0, 0)) { SetSpeed(a_Speed); SetMass(0.1); @@ -398,7 +411,10 @@ cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) : super(pkArrow, &a_Player, a_Player.GetThrowStartPos(), a_Player.GetThrowSpeed(a_Force * 1.5 * 20), 0.5, 0.5), m_PickupState(psInSurvivalOrCreative), m_DamageCoeff(2), - m_IsCritical((a_Force >= 1)) + m_IsCritical((a_Force >= 1)), + m_Timer(0), + m_bIsCollected(false), + m_HitBlockPos(0, 0, 0) { } @@ -424,7 +440,31 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) { + if (a_HitFace == BLOCK_FACE_NONE) + { + return; + } + super::OnHitSolidBlock(a_HitPos, a_HitFace); + int a_X = (int)a_HitPos.x, a_Y = (int)a_HitPos.y, a_Z = (int)a_HitPos.z; + + if (a_HitFace != BLOCK_FACE_YP) + { + AddFaceDirection(a_X, a_Y, a_Z, a_HitFace); + } + else if (a_HitFace == BLOCK_FACE_YP) // These conditions because xoft got a little confused on block face directions, so AddFace works with all but YP & YM + { + a_Y--; + } + else + { + a_Y++; + } + + m_HitBlockPos = Vector3i(a_X, a_Y, a_Z); + + // Broadcast arrow hit sound + m_World->BroadcastSoundEffect("random.bowhit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); // Broadcast the position and speed packets before teleporting: BroadcastMovementUpdate(); @@ -439,7 +479,7 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) { - if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer()) + if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer() && !a_EntityHit.IsBoat()) { // Not an entity that interacts with an arrow return; @@ -452,6 +492,9 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) } a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1); + // Broadcast successful hit sound + m_World->BroadcastSoundEffect("random.successful_hit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + Destroy(); } @@ -459,6 +502,67 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) +void cArrowEntity::CollectedBy(cPlayer * a_Dest) +{ + if ((m_IsInGround) && (!m_bIsCollected) && (CanPickup(*a_Dest))) + { + int NumAdded = a_Dest->GetInventory().AddItem(E_ITEM_ARROW); + if (NumAdded > 0) // Only play effects if there was space in inventory + { + m_World->BroadcastCollectPickup((const cPickup &)*this, *a_Dest); + // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;) + m_World->BroadcastSoundEffect("random.pop", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + m_bIsCollected = true; + } + } +} + + + + + +void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + m_Timer += a_Dt; + + if (m_bIsCollected) + { + if (m_Timer > 500.f) // 0.5 seconds + { + Destroy(); + return; + } + } + else if (m_Timer > 1000 * 60 * 5) // 5 minutes + { + Destroy(); + return; + } + + if (m_IsInGround) + { + int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width; + int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width; + cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ); + + if (Chunk == NULL) + { + // Inside an unloaded chunk, abort + return; + } + + if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed? + { + m_IsInGround = false; // Yes, begin simulating physics again + } + } +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cThrownEggEntity: diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 547aa174e..28dd76935 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -53,6 +53,9 @@ public: /// Called by the physics blocktracer when the entity hits another entity virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) {} + /// Called by Chunk when the projectile is eligible for player collection + virtual void CollectedBy(cPlayer * a_Dest); + // tolua_begin /// Returns the kind of the projectile (fast class identification) @@ -153,9 +156,20 @@ protected: /// If true, the arrow deals more damage bool m_IsCritical; + /// Timer for pickup collection animation or five minute timeout + float m_Timer; + + /// If true, the arrow is in the process of being collected - don't go to anyone else + bool m_bIsCollected; + + /// Stores the block position that arrow is lodged into, sets m_IsInGround to false if it becomes air + Vector3i m_HitBlockPos; + // cProjectileEntity overrides: virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override; virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override; + virtual void CollectedBy(cPlayer * a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; // tolua_begin } ; diff --git a/source/Items/ItemBow.h b/source/Items/ItemBow.h index 7bce127b1..79520c074 100644 --- a/source/Items/ItemBow.h +++ b/source/Items/ItemBow.h @@ -36,6 +36,7 @@ public: { return false; } + a_Player->StartChargingBow(); return true; } @@ -71,6 +72,7 @@ public: return; } a_Player->GetWorld()->BroadcastSpawnEntity(*Arrow); + a_Player->GetWorld()->BroadcastSoundEffect("random.bow", (int)a_Player->GetPosX() * 8, (int)a_Player->GetPosY() * 8, (int)a_Player->GetPosZ() * 8, 0.5, Force); if (!a_Player->IsGameModeCreative()) { diff --git a/source/Mobs/Horse.cpp b/source/Mobs/Horse.cpp index d18887ea4..bb9a4e3f6 100644 --- a/source/Mobs/Horse.cpp +++ b/source/Mobs/Horse.cpp @@ -55,10 +55,10 @@ void cHorse::Tick(float a_Dt, cChunk & a_Chunk) { if (m_World->GetTickRandomNumber(50) == 25) { - m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 0); - m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 2); - m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 6); - m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 8); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 0); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 2); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 6); + m_World->BroadcastSoundParticleEffect(2000, (int)GetPosX(), (int)GetPosY(), (int)GetPosZ(), 8); m_Attachee->Detach(); m_bIsRearing = true; diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp index 9d2be1e29..8a5717e27 100644 --- a/source/Mobs/Monster.cpp +++ b/source/Mobs/Monster.cpp @@ -622,65 +622,78 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) -cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType, int a_Size) +cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) { cFastRandom Random; - cMonster * toReturn = NULL; - // unspecified size get rand[1,3] for Monsters that need size + // Create the mob entity switch (a_MobType) { case mtMagmaCube: case mtSlime: { - if (a_Size == -1) + toReturn = new cSlime (Random.NextInt(2) + 1); + break; + } + case mtSkeleton: + { + // TODO: Actual detection of spawning in Nether + toReturn = new cSkeleton(Random.NextInt(1) == 0 ? false : true); + break; + } + case mtVillager: + { + int VillagerType = Random.NextInt(6); + if (VillagerType == 6) { - a_Size = Random.NextInt(2, a_MobType) + 1; + // Give farmers a better chance of spawning + VillagerType = 0; } - if ((a_Size <= 0) || (a_Size >= 4)) + + toReturn = new cVillager((cVillager::eVillagerType)VillagerType); + break; + } + case mtHorse: + { + // Horses take a type (species), a colour, and a style (dots, stripes, etc.) + int HorseType = Random.NextInt(7); + int HorseColor = Random.NextInt(6); + int HorseStyle = Random.NextInt(6); + int HorseTameTimes = Random.NextInt(6) + 1; + + if ((HorseType == 5) || (HorseType == 6) || (HorseType == 7)) { - ASSERT(!"Random for size was supposed to pick in [1..3] and picked outside"); - a_Size = 1; + // Increase chances of normal horse (zero) + HorseType = 0; } + + toReturn = new cHorse(HorseType, HorseColor, HorseStyle, HorseTameTimes); break; } - default: break; - } // switch (a_MobType) - // Create the mob entity - switch (a_MobType) - { - case mtMagmaCube: toReturn = new cMagmaCube(a_Size); break; - case mtSlime: toReturn = new cSlime(a_Size); break; - case mtBat: toReturn = new cBat(); break; - case mtBlaze: toReturn = new cBlaze(); break; - case mtCaveSpider: toReturn = new cCavespider(); break; - case mtChicken: toReturn = new cChicken(); break; - case mtCow: toReturn = new cCow(); break; - case mtCreeper: toReturn = new cCreeper(); break; - case mtEnderman: toReturn = new cEnderman(); break; - case mtGhast: toReturn = new cGhast(); break; - // TODO: - // case cMonster::mtHorse: toReturn = new cHorse(); break; - case mtMooshroom: toReturn = new cMooshroom(); break; - case mtOcelot: toReturn = new cOcelot(); break; - case mtPig: toReturn = new cPig(); break; - // TODO: Implement sheep color - case mtSheep: toReturn = new cSheep(0); break; - case mtSilverfish: toReturn = new cSilverfish(); break; - // TODO: Implement wither skeleton geration - case mtSkeleton: toReturn = new cSkeleton(false); break; - case mtSpider: toReturn = new cSpider(); break; - case mtSquid: toReturn = new cSquid(); break; - case mtVillager: toReturn = new cVillager(cVillager::vtFarmer); break; - case mtWitch: toReturn = new cWitch(); break; - case mtWolf: toReturn = new cWolf(); break; - case mtZombie: toReturn = new cZombie(false); break; - case mtZombiePigman: toReturn = new cZombiePigman(); break; + case mtBat: toReturn = new cBat(); break; + case mtBlaze: toReturn = new cBlaze(); break; + case mtCaveSpider: toReturn = new cCavespider(); break; + case mtChicken: toReturn = new cChicken(); break; + case mtCow: toReturn = new cCow(); break; + case mtCreeper: toReturn = new cCreeper(); break; + case mtEnderman: toReturn = new cEnderman(); break; + case mtGhast: toReturn = new cGhast(); break; + case mtMooshroom: toReturn = new cMooshroom(); break; + case mtOcelot: toReturn = new cOcelot(); break; + case mtPig: toReturn = new cPig(); break; + case mtSheep: toReturn = new cSheep (Random.NextInt(15)); break; // Colour parameter + case mtSilverfish: toReturn = new cSilverfish(); break; + case mtSpider: toReturn = new cSpider(); break; + case mtSquid: toReturn = new cSquid(); break; + case mtWitch: toReturn = new cWitch(); break; + case mtWolf: toReturn = new cWolf(); break; + case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter + case mtZombiePigman: toReturn = new cZombiePigman(); break; default: { - ASSERT(!"Unhandled Mob type"); + ASSERT(!"Unhandled mob type whilst trying to spawn mob!"); } } return toReturn; diff --git a/source/Mobs/Monster.h b/source/Mobs/Monster.h index a0002bf4f..29a705d11 100644 --- a/source/Mobs/Monster.h +++ b/source/Mobs/Monster.h @@ -153,12 +153,9 @@ public: /** Creates a new object of the specified mob. a_MobType is the type of the mob to be created - a_Size is the size (for mobs with size) - if a_Size is let to -1 for entities that need size, size will be random - asserts and returns null if mob type is not specified - asserts if invalid size for mobs that need size + Asserts and returns null if mob type is not specified */ - static cMonster * NewMonsterFromType(eType a_MobType, int a_Size = -1); + static cMonster * NewMonsterFromType(eType a_MobType); protected: diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp index 53159a3b3..22eac4312 100644 --- a/source/Protocol/Protocol132.cpp +++ b/source/Protocol/Protocol132.cpp @@ -392,9 +392,9 @@ void cProtocol132::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src cCSLock Lock(m_CSPacket); WriteByte(PACKET_SOUND_PARTICLE_EFFECT); WriteInt (a_EffectID); - WriteInt (a_SrcX / 8); - WriteByte(a_SrcY / 8); - WriteInt (a_SrcZ / 8); + WriteInt (a_SrcX); + WriteByte(a_SrcY); + WriteInt (a_SrcZ); WriteInt (a_Data); Flush(); } diff --git a/source/Protocol/Protocol14x.cpp b/source/Protocol/Protocol14x.cpp index ba9d7c01a..d2582458b 100644 --- a/source/Protocol/Protocol14x.cpp +++ b/source/Protocol/Protocol14x.cpp @@ -109,9 +109,9 @@ void cProtocol142::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src cCSLock Lock(m_CSPacket); WriteByte(PACKET_SOUND_PARTICLE_EFFECT); WriteInt (a_EffectID); - WriteInt (a_SrcX / 8); - WriteByte(a_SrcY / 8); - WriteInt (a_SrcZ / 8); + WriteInt (a_SrcX); + WriteByte(a_SrcY); + WriteInt (a_SrcZ); WriteInt (a_Data); WriteBool(0); Flush(); diff --git a/source/Protocol/Protocol17x.cpp b/source/Protocol/Protocol17x.cpp index 78a55ccc0..628b8e071 100644 --- a/source/Protocol/Protocol17x.cpp +++ b/source/Protocol/Protocol17x.cpp @@ -17,6 +17,7 @@ Implements the 1.7.x protocol classes: #include "../World.h" #include "../WorldStorage/FastNBT.h" #include "../StringCompression.h" +#include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" #include "../Entities/Pickup.h" #include "../Entities/Player.h" @@ -215,7 +216,7 @@ void cProtocol172::SendDestroyEntity(const cEntity & a_Entity) void cProtocol172::SendDisconnect(const AString & a_Reason) { cPacketizer Pkt(*this, 0x40); - Pkt.WriteString(EscapeString(a_Reason)); + Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Reason).c_str())); } @@ -615,9 +616,9 @@ void cProtocol172::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src { cPacketizer Pkt(*this, 0x28); // Effect packet Pkt.WriteInt(a_EffectID); - Pkt.WriteInt(a_SrcX / 8); - Pkt.WriteByte(a_SrcY / 8); - Pkt.WriteInt(a_SrcZ / 8); + Pkt.WriteInt(a_SrcX); + Pkt.WriteByte(a_SrcY); + Pkt.WriteInt(a_SrcZ); Pkt.WriteInt(a_Data); Pkt.WriteBool(false); } @@ -819,9 +820,13 @@ void cProtocol172::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bloc void cProtocol172::SendWeather(eWeather a_Weather) { - cPacketizer Pkt(*this, 0x2b); // Change Game State packet - Pkt.WriteByte((a_Weather == wSunny) ? 2 : 1); // begin rain / end rain - Pkt.WriteFloat(0); // unused + { + cPacketizer Pkt(*this, 0x2b); // Change Game State packet + Pkt.WriteByte((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain + Pkt.WriteFloat(0); // Unused for weather + } + + // TODO: Fade effect, somehow } @@ -1664,12 +1669,43 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) WriteItem(((const cPickup &)a_Entity).GetItem()); break; } + case cEntity::etMinecart: + { + WriteByte(0x51); + + // The following expression makes Minecarts shake more with less health or higher damage taken + // It gets half the maximum health, and takes it away from the current health minus the half health: + /* Health: 5 | 3 - (5 - 3) = 1 (shake power) + Health: 3 | 3 - (3 - 3) = 3 + Health: 1 | 3 - (1 - 3) = 5 + */ + WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4); + WriteByte(0x52); + WriteInt(1); // Shaking direction, doesn't seem to affect anything + WriteByte(0x73); + WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer + + if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace) + { + WriteByte(0x10); + WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); + } + break; + } + case cEntity::etProjectile: + { + if (((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow) + { + WriteByte(0x10); + WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); + } + break; + } case cEntity::etMonster: { WriteMobMetadata((const cMonster &)a_Entity); break; } - // TODO: Other types } } diff --git a/source/Simulator/FloodyFluidSimulator.cpp b/source/Simulator/FloodyFluidSimulator.cpp index 9374bbab3..d204a1f8b 100644 --- a/source/Simulator/FloodyFluidSimulator.cpp +++ b/source/Simulator/FloodyFluidSimulator.cpp @@ -224,9 +224,7 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i ItemTypeToString(NewBlock).c_str() ); a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); - - // TODO: Sound effect - + m_World.BroadcastSoundEffect("random.fizz", a_RelX * 8, a_RelY * 8, a_RelZ * 8, 0.5f, 1.5f); return; } } @@ -240,9 +238,7 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str() ); a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); - - // TODO: Sound effect - + m_World.BroadcastSoundEffect("random.fizz", a_RelX * 8, a_RelY * 8, a_RelZ * 8, 0.5f, 1.5f); return; } } diff --git a/source/World.cpp b/source/World.cpp index c6bc47be5..0f9df8a62 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1512,7 +1512,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) { float SpeedX = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500)); - float SpeedY = 1; + float SpeedY = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500)); float SpeedZ = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500)); cPickup * Pickup = new cPickup( @@ -2563,15 +2563,16 @@ bool cWorld::IsBlockDirectlyWatered(int a_BlockX, int a_BlockY, int a_BlockZ) int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) { cMonster * Monster = NULL; - - int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep - bool SkType = GetDimension() == dimNether ; // Skeleton Monster = cMonster::NewMonsterFromType(a_MonsterType); if (Monster != NULL) { Monster->SetPosition(a_PosX, a_PosY, a_PosZ); } + + // Because it's logical that ALL mob spawns need spawn effects, not just spawners + BroadcastSoundParticleEffect(2004, (int)a_PosX, (int)a_PosY, (int)a_PosZ, 0); + return SpawnMobFinalize(Monster); } |