1
0

Suggestions

This commit is contained in:
Tiger Wang 2014-07-21 22:49:06 +01:00
parent 6ab9afd0fd
commit 8050a5b98a
10 changed files with 161 additions and 127 deletions

View File

@ -585,7 +585,7 @@ Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename,
AString Data;
Printf(Data, "%lld", defValue);
AString resultstring = GetValueSet(keyname, valuename, Data);
Int64 result;
Int64 result = defValue;
#ifdef _WIN32
sscanf_s(resultstring.c_str(), "%lld", &result);
#else

View File

@ -924,7 +924,7 @@ extern int StringToMobType(const AString & a_MobString);
extern eDimension StringToDimension(const AString & a_DimensionString);
/** Translates a dimension enum to dimension string.
Takes a string and returns "Overworld" on failure
Takes an eDimension enum value and returns "Overworld" on failure
*/
extern AString DimensionToString(eDimension a_Dimension);

View File

@ -2427,7 +2427,6 @@ bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinCh
{
for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
{
LOG("Request %i %i", x, z);
cChunkPtr Chunk = GetChunkNoLoad(x, ZERO_CHUNK_Y, z);
if ((Chunk == NULL) || (!Chunk->IsValid()))
{

View File

@ -1030,9 +1030,15 @@ void cEntity::DetectPortal()
{
if (GetWorld()->GetDimension() == dimOverworld)
{
if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty()) { return; }
if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty())
{
return;
}
}
else if (GetWorld()->GetLinkedOverworldName().empty())
{
return;
}
else if (GetWorld()->GetLinkedOverworldName().empty()) { return; }
int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
if ((Y > 0) && (Y < cChunkDef::Height))
@ -1041,17 +1047,17 @@ void cEntity::DetectPortal()
{
case E_BLOCK_NETHER_PORTAL:
{
if (m_PortalCooldownData.second)
if (m_PortalCooldownData.m_ShouldPreventTeleportation)
{
return;
}
if (m_PortalCooldownData.first != 80)
if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80)
{
m_PortalCooldownData.first++;
m_PortalCooldownData.m_TicksDelayed++;
return;
}
m_PortalCooldownData.first = 0;
m_PortalCooldownData.m_TicksDelayed = 0;
switch (GetWorld()->GetDimension())
{
@ -1062,13 +1068,13 @@ void cEntity::DetectPortal()
return;
}
m_PortalCooldownData.second = true; // Stop portals from working on respawn
m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
if (IsPlayer())
{
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld);
}
MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
return;
}
@ -1079,14 +1085,14 @@ void cEntity::DetectPortal()
return;
}
m_PortalCooldownData.second = true; // Stop portals from working on respawn
m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
if (IsPlayer())
{
((cPlayer *)this)->AwardAchievement(achEnterPortal);
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
}
MoveToWorld(GetWorld()->GetNetherWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
return;
}
@ -1095,7 +1101,7 @@ void cEntity::DetectPortal()
}
case E_BLOCK_END_PORTAL:
{
if (m_PortalCooldownData.second)
if (m_PortalCooldownData.m_ShouldPreventTeleportation)
{
return;
}
@ -1109,7 +1115,7 @@ void cEntity::DetectPortal()
return;
}
m_PortalCooldownData.second = true; // Stop portals from working on respawn
m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
if (IsPlayer())
{
@ -1117,7 +1123,7 @@ void cEntity::DetectPortal()
Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
Player->GetClientHandle()->SendRespawn(dimOverworld);
}
MoveToWorld(GetWorld()->GetLinkedOverworldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
return;
}
@ -1128,14 +1134,14 @@ void cEntity::DetectPortal()
return;
}
m_PortalCooldownData.second = true; // Stop portals from working on respawn
m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
if (IsPlayer())
{
((cPlayer *)this)->AwardAchievement(achEnterTheEnd);
((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd);
}
MoveToWorld(GetWorld()->GetEndWorldName(), cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
return;
}
@ -1147,34 +1153,20 @@ void cEntity::DetectPortal()
}
// Allow portals to work again
m_PortalCooldownData.second = false;
m_PortalCooldownData.first = 0;
m_PortalCooldownData.m_ShouldPreventTeleportation = false;
m_PortalCooldownData.m_ShouldPreventTeleportation = 0;
}
bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn)
bool cEntity::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
{
UNUSED(a_ShouldSendRespawn);
ASSERT(a_World == NULL);
cWorld * World;
if (a_World == NULL)
{
World = cRoot::Get()->GetWorld(a_WorldName);
if (World == NULL)
{
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str());
return false;
}
}
else
{
World = a_World;
}
if (GetWorld() == World)
if (GetWorld() == a_World)
{
// Don't move to same world
return false;
@ -1185,7 +1177,7 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
GetWorld()->BroadcastDestroyEntity(*this);
// Queue add to new world
World->AddEntity(this);
a_World->AddEntity(this);
return true;
}
@ -1194,6 +1186,22 @@ bool cEntity::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn)
{
cWorld * World = cRoot::Get()->GetWorld(a_WorldName);
if (World == NULL)
{
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str());
return false;
}
return MoveToWorld(World, a_ShouldSendRespawn);
}
void cEntity::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(GetPosY() + 0.1);

View File

@ -382,16 +382,19 @@ public:
/// Teleports to the coordinates specified
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
/** Moves entity to specified world */
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true);
/** Moves entity to specified world, taking a world pointer */
virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true);
/** Moves entity to specified world, taking a world name */
bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true);
// tolua_end
/** Returns if the entity is travelling away from a specified world */
bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); }
bool IsWorldTravellingFrom(cWorld * a_World) const { return m_WorldTravellingFrom == a_World; }
/** Sets the world the entity will be leaving */
void SetWorldTravellingFrom(cWorld * a_World) { (m_WorldTravellingFrom = a_World); }
void SetWorldTravellingFrom(cWorld * a_World) { m_WorldTravellingFrom = a_World; }
/// Updates clients of changes in the entity.
virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL);
@ -538,11 +541,20 @@ protected:
int m_AirLevel;
int m_AirTickTimer;
/** Portal delay timer and cooldown boolean
First value is to delay sending the respawn packet (which triggers the Entering the {Dimension} screen).
Second value is to prevent a teleportation loop by ensuring we do not reenter a portal that we came out of.
/** Structure storing the portal delay timer and cooldown boolean */
struct sPortalCooldownData
{
/** Ticks since entry of portal, used to delay teleportation */
unsigned short m_TicksDelayed;
/** Whether the entity has just exited the portal, and should therefore not be teleported again
This prevents teleportation loops, and is reset when the entity has moved out of the portal
*/
std::pair<unsigned short, bool> m_PortalCooldownData;
bool m_ShouldPreventTeleportation;
};
/** Portal delay timer and cooldown boolean data */
sPortalCooldownData m_PortalCooldownData;
private:
/** Measured in degrees, [-180, +180) */

View File

@ -1611,24 +1611,9 @@ void cPlayer::TossItems(const cItems & a_Items)
bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_ShouldSendRespawn)
bool cPlayer::MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
{
cWorld * World;
if (a_World == NULL)
{
World = cRoot::Get()->GetWorld(a_WorldName);
if (World == NULL)
{
LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str());
return false;
}
}
else
{
World = a_World;
}
if (GetWorld() == World)
if (GetWorld() == a_World)
{
// Don't move to same world
return false;
@ -1637,7 +1622,7 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
// Send the respawn packet:
if (a_ShouldSendRespawn && (m_ClientHandle != NULL))
{
m_ClientHandle->SendRespawn(World->GetDimension());
m_ClientHandle->SendRespawn(a_World->GetDimension());
}
// Remove player from the old world
@ -1645,8 +1630,8 @@ bool cPlayer::MoveToWorld(const AString & a_WorldName, cWorld * a_World, bool a_
GetWorld()->RemovePlayer(this);
// Queue adding player to the new world, including all the necessary adjustments to the object
World->AddPlayer(this);
SetWorld(World);
a_World->AddPlayer(this);
SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
return true;
}

View File

@ -333,7 +333,7 @@ public:
/** Moves the player to the specified world.
Returns true if successful, false on failure (world not found). */
virtual bool MoveToWorld(const AString & a_WorldName, cWorld * a_World = NULL, bool a_ShouldSendRespawn = true) override; // tolua_export
virtual bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) override; // tolua_export
/** Saves all player data, such as inventory, to JSON */
bool SaveToDisk(void);

View File

@ -512,7 +512,7 @@ void cWorld::InitializeSpawn(void)
void cWorld::Start()
void cWorld::Start(void)
{
m_SpawnX = 0;
m_SpawnY = cChunkDef::Height;
@ -594,61 +594,8 @@ void cWorld::Start()
m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll);
m_Weather = (eWeather) Clamp(Weather, (int)wSunny, (int)wStorm);
switch (GetDimension())
{
case dimEnd:
{
IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
IniFile.GetValueSet("Generator", "ConstantBiome", "End");
IniFile.GetValueSet("Generator", "HeightGen", "Biomal");
IniFile.GetValueSet("Generator", "CompositionGen", "End");
break;
}
case dimOverworld:
{
IniFile.GetValueSet("Generator", "BiomeGen", "MultiStepMap");
IniFile.GetValueSet("Generator", "HeightGen", "DistortedHeightmap");
IniFile.GetValueSet("Generator", "CompositionGen", "DistortedHeightmap");
IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
break;
}
case dimNether:
{
IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
IniFile.GetValueSet("Generator", "ConstantBiome", "Nether");
IniFile.GetValueSet("Generator", "HeightGen", "Flat");
IniFile.GetValueSet("Generator", "FlatHeight", "128");
IniFile.GetValueSet("Generator", "CompositionGen", "Nether");
IniFile.GetValueSet("Generator", "Finishers", "WormNestCaves, BottomLava, LavaSprings, NetherClumpFoliage, NetherForts, PreSimulator");
IniFile.GetValueSet("Generator", "BottomLavaHeight", "30");
break;
}
}
// Load allowed mobs:
const char * DefaultMonsters = "";
switch (m_Dimension)
{
case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break;
case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break;
case dimEnd: DefaultMonsters = "enderman"; break;
}
m_bAnimals = IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
AString AllMonsters = IniFile.GetValueSet("Monsters", "Types", DefaultMonsters);
AStringVector SplitList = StringSplitAndTrim(AllMonsters, ",");
for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr)
{
cMonster::eType ToAdd = cMonster::StringToMobType(*itr);
if (ToAdd != cMonster::mtInvalidType)
{
m_AllowedMobs.insert(ToAdd);
LOGD("Allowed mob: %s", itr->c_str());
}
else
{
LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str());
}
}
InitialiseGeneratorDefaults(IniFile);
InitialiseAndLoadMobSpawningValues(IniFile);
m_ChunkMap = new cChunkMap(this);
@ -745,6 +692,82 @@ eWeather cWorld::ChooseNewWeather()
void cWorld::InitialiseGeneratorDefaults(cIniFile & a_IniFile)
{
switch (GetDimension())
{
case dimEnd:
{
a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
a_IniFile.GetValueSet("Generator", "ConstantBiome", "End");
a_IniFile.GetValueSet("Generator", "HeightGen", "Biomal");
a_IniFile.GetValueSet("Generator", "CompositionGen", "End");
break;
}
case dimOverworld:
{
a_IniFile.GetValueSet("Generator", "BiomeGen", "MultiStepMap");
a_IniFile.GetValueSet("Generator", "HeightGen", "DistortedHeightmap");
a_IniFile.GetValueSet("Generator", "CompositionGen", "DistortedHeightmap");
a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
break;
}
case dimNether:
{
a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
a_IniFile.GetValueSet("Generator", "ConstantBiome", "Nether");
a_IniFile.GetValueSet("Generator", "HeightGen", "Flat");
a_IniFile.GetValueSet("Generator", "FlatHeight", "128");
a_IniFile.GetValueSet("Generator", "CompositionGen", "Nether");
a_IniFile.GetValueSet("Generator", "Finishers", "WormNestCaves, BottomLava, LavaSprings, NetherClumpFoliage, NetherForts, PreSimulator");
a_IniFile.GetValueSet("Generator", "BottomLavaHeight", "30");
break;
}
}
}
void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile)
{
AString DefaultMonsters;
switch (m_Dimension)
{
case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break;
case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break;
case dimEnd: DefaultMonsters = "enderman"; break;
}
m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
AString AllMonsters = a_IniFile.GetValueSet("Monsters", "Types", DefaultMonsters);
if (!m_bAnimals)
{
return;
}
AStringVector SplitList = StringSplitAndTrim(AllMonsters, ",");
for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr)
{
cMonster::eType ToAdd = cMonster::StringToMobType(*itr);
if (ToAdd != cMonster::mtInvalidType)
{
m_AllowedMobs.insert(ToAdd);
LOGD("Allowed mob: %s", itr->c_str());
}
else
{
LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str());
}
}
}
void cWorld::Stop(void)
{
// Delete the clients that have been in this world:

View File

@ -1030,6 +1030,13 @@ private:
/** Adds the players queued in the m_PlayersToAdd queue into the m_Players list.
Assumes it is called from the Tick thread. */
void AddQueuedPlayers(void);
/** Sets generator values to dimension specific defaults, if those values do not exist */
void InitialiseGeneratorDefaults(cIniFile & a_IniFile);
/** Sets mob spawning values if nonexistant to their dimension specific defaults */
void InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile);
}; // tolua_export