Added water and lava springs.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1269 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
e18e539ad2
commit
ff403fdbf0
|
@ -576,6 +576,14 @@
|
||||||
RelativePath="..\source\Piston.h"
|
RelativePath="..\source\Piston.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\ProbabDistrib.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\ProbabDistrib.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\source\ReferenceManager.cpp"
|
RelativePath="..\source\ReferenceManager.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
** Lua binding: AllToLua
|
** Lua binding: AllToLua
|
||||||
** Generated automatically by tolua++-1.0.92 on 03/09/13 15:33:58.
|
** Generated automatically by tolua++-1.0.92 on 03/14/13 10:02:26.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
@ -9999,6 +9999,38 @@ static int tolua_AllToLua_cWorld_IsDeepSnowEnabled00(lua_State* tolua_S)
|
||||||
}
|
}
|
||||||
#endif //#ifndef TOLUA_DISABLE
|
#endif //#ifndef TOLUA_DISABLE
|
||||||
|
|
||||||
|
/* method: GetDimension of class cWorld */
|
||||||
|
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetDimension00
|
||||||
|
static int tolua_AllToLua_cWorld_GetDimension00(lua_State* tolua_S)
|
||||||
|
{
|
||||||
|
#ifndef TOLUA_RELEASE
|
||||||
|
tolua_Error tolua_err;
|
||||||
|
if (
|
||||||
|
!tolua_isusertype(tolua_S,1,"const cWorld",0,&tolua_err) ||
|
||||||
|
!tolua_isnoobj(tolua_S,2,&tolua_err)
|
||||||
|
)
|
||||||
|
goto tolua_lerror;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const cWorld* self = (const cWorld*) tolua_tousertype(tolua_S,1,0);
|
||||||
|
#ifndef TOLUA_RELEASE
|
||||||
|
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetDimension'", NULL);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
cWorld::eDimension tolua_ret = (cWorld::eDimension) self->GetDimension();
|
||||||
|
tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
#ifndef TOLUA_RELEASE
|
||||||
|
tolua_lerror:
|
||||||
|
tolua_error(tolua_S,"#ferror in function 'GetDimension'.",&tolua_err);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif //#ifndef TOLUA_DISABLE
|
||||||
|
|
||||||
/* method: GetHeight of class cWorld */
|
/* method: GetHeight of class cWorld */
|
||||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetHeight00
|
#ifndef TOLUA_DISABLE_tolua_AllToLua_cWorld_GetHeight00
|
||||||
static int tolua_AllToLua_cWorld_GetHeight00(lua_State* tolua_S)
|
static int tolua_AllToLua_cWorld_GetHeight00(lua_State* tolua_S)
|
||||||
|
@ -22059,6 +22091,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||||
tolua_endmodule(tolua_S);
|
tolua_endmodule(tolua_S);
|
||||||
tolua_cclass(tolua_S,"cWorld","cWorld","",NULL);
|
tolua_cclass(tolua_S,"cWorld","cWorld","",NULL);
|
||||||
tolua_beginmodule(tolua_S,"cWorld");
|
tolua_beginmodule(tolua_S,"cWorld");
|
||||||
|
tolua_constant(tolua_S,"dimNether",cWorld::dimNether);
|
||||||
|
tolua_constant(tolua_S,"dimOverworld",cWorld::dimOverworld);
|
||||||
|
tolua_constant(tolua_S,"dimEnd",cWorld::dimEnd);
|
||||||
tolua_function(tolua_S,"GetClassStatic",tolua_AllToLua_cWorld_GetClassStatic00);
|
tolua_function(tolua_S,"GetClassStatic",tolua_AllToLua_cWorld_GetClassStatic00);
|
||||||
tolua_function(tolua_S,"GetTime",tolua_AllToLua_cWorld_GetTime00);
|
tolua_function(tolua_S,"GetTime",tolua_AllToLua_cWorld_GetTime00);
|
||||||
tolua_function(tolua_S,"GetWorldAge",tolua_AllToLua_cWorld_GetWorldAge00);
|
tolua_function(tolua_S,"GetWorldAge",tolua_AllToLua_cWorld_GetWorldAge00);
|
||||||
|
@ -22068,6 +22103,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
||||||
tolua_function(tolua_S,"GetGameMode",tolua_AllToLua_cWorld_GetGameMode00);
|
tolua_function(tolua_S,"GetGameMode",tolua_AllToLua_cWorld_GetGameMode00);
|
||||||
tolua_function(tolua_S,"IsPVPEnabled",tolua_AllToLua_cWorld_IsPVPEnabled00);
|
tolua_function(tolua_S,"IsPVPEnabled",tolua_AllToLua_cWorld_IsPVPEnabled00);
|
||||||
tolua_function(tolua_S,"IsDeepSnowEnabled",tolua_AllToLua_cWorld_IsDeepSnowEnabled00);
|
tolua_function(tolua_S,"IsDeepSnowEnabled",tolua_AllToLua_cWorld_IsDeepSnowEnabled00);
|
||||||
|
tolua_function(tolua_S,"GetDimension",tolua_AllToLua_cWorld_GetDimension00);
|
||||||
tolua_function(tolua_S,"GetHeight",tolua_AllToLua_cWorld_GetHeight00);
|
tolua_function(tolua_S,"GetHeight",tolua_AllToLua_cWorld_GetHeight00);
|
||||||
tolua_function(tolua_S,"UnloadUnusedChunks",tolua_AllToLua_cWorld_UnloadUnusedChunks00);
|
tolua_function(tolua_S,"UnloadUnusedChunks",tolua_AllToLua_cWorld_UnloadUnusedChunks00);
|
||||||
tolua_function(tolua_S,"GetMaxPlayers",tolua_AllToLua_cWorld_GetMaxPlayers00);
|
tolua_function(tolua_S,"GetMaxPlayers",tolua_AllToLua_cWorld_GetMaxPlayers00);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
** Lua binding: AllToLua
|
** Lua binding: AllToLua
|
||||||
** Generated automatically by tolua++-1.0.92 on 03/09/13 15:33:59.
|
** Generated automatically by tolua++-1.0.92 on 03/14/13 10:02:26.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Exported function */
|
/* Exported function */
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
|
cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
|
||||||
super(a_ChunkGenerator),
|
super(a_ChunkGenerator),
|
||||||
m_BiomeGen(NULL),
|
m_BiomeGen(NULL),
|
||||||
|
@ -308,7 +313,7 @@ void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile)
|
||||||
AString Structures = a_IniFile.GetValueSet("Generator", "Structures", "Ravines,WormNestCaves,OreNests,Trees");
|
AString Structures = a_IniFile.GetValueSet("Generator", "Structures", "Ravines,WormNestCaves,OreNests,Trees");
|
||||||
|
|
||||||
int Seed = m_ChunkGenerator.GetSeed();
|
int Seed = m_ChunkGenerator.GetSeed();
|
||||||
AStringVector Str = StringSplit(Structures, ",");
|
AStringVector Str = StringSplitAndTrim(Structures, ",");
|
||||||
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
|
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
|
||||||
{
|
{
|
||||||
if (NoCaseCompare(*itr, "trees") == 0)
|
if (NoCaseCompare(*itr, "trees") == 0)
|
||||||
|
@ -355,13 +360,14 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||||
int Seed = m_ChunkGenerator.GetSeed();
|
int Seed = m_ChunkGenerator.GetSeed();
|
||||||
AString Structures = a_IniFile.GetValueSet("Generator", "Finishers", "SprinkleFoliage,Ice,Snow,Lilypads,BottomLava,DeadBushes,PreSimulator");
|
AString Structures = a_IniFile.GetValueSet("Generator", "Finishers", "SprinkleFoliage,Ice,Snow,Lilypads,BottomLava,DeadBushes,PreSimulator");
|
||||||
|
|
||||||
AStringVector Str = StringSplit(Structures, ",");
|
AStringVector Str = StringSplitAndTrim(Structures, ",");
|
||||||
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
|
for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr)
|
||||||
{
|
{
|
||||||
// Finishers, alpha-sorted:
|
// Finishers, alpha-sorted:
|
||||||
if (NoCaseCompare(*itr, "BottomLava") == 0)
|
if (NoCaseCompare(*itr, "BottomLava") == 0)
|
||||||
{
|
{
|
||||||
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", 10);
|
int DefaultBottomLavaLevel = (m_World->GetDimension() == cWorld::dimNether) ? 30 : 10;
|
||||||
|
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel);
|
||||||
m_FinishGens.push_back(new cFinishGenBottomLava(BottomLavaLevel));
|
m_FinishGens.push_back(new cFinishGenBottomLava(BottomLavaLevel));
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "DeadBushes") == 0)
|
else if (NoCaseCompare(*itr, "DeadBushes") == 0)
|
||||||
|
@ -372,6 +378,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||||
{
|
{
|
||||||
m_FinishGens.push_back(new cFinishGenIce);
|
m_FinishGens.push_back(new cFinishGenIce);
|
||||||
}
|
}
|
||||||
|
else if (NoCaseCompare(*itr, "LavaSprings") == 0)
|
||||||
|
{
|
||||||
|
m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_LAVA, a_IniFile, *m_World));
|
||||||
|
}
|
||||||
else if (NoCaseCompare(*itr, "Lilypads") == 0)
|
else if (NoCaseCompare(*itr, "Lilypads") == 0)
|
||||||
{
|
{
|
||||||
m_FinishGens.push_back(new cFinishGenLilypads(Seed));
|
m_FinishGens.push_back(new cFinishGenLilypads(Seed));
|
||||||
|
@ -388,6 +398,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||||
{
|
{
|
||||||
m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed));
|
m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed));
|
||||||
}
|
}
|
||||||
|
else if (NoCaseCompare(*itr, "WaterSprings") == 0)
|
||||||
|
{
|
||||||
|
m_FinishGens.push_back(new cFinishGenFluidSprings(Seed, E_BLOCK_WATER, a_IniFile, *m_World));
|
||||||
|
}
|
||||||
} // for itr - Str[]
|
} // for itr - Str[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,18 @@
|
||||||
#include "../Noise.h"
|
#include "../Noise.h"
|
||||||
#include "../BlockID.h"
|
#include "../BlockID.h"
|
||||||
#include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway()
|
#include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway()
|
||||||
|
#include "../World.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DEF_NETHER_WATER_SPRINGS "0, 0; 255, 0"
|
||||||
|
#define DEF_NETHER_LAVA_SPRINGS "0, 0; 30, 0; 31, 50; 120, 50; 127, 0"
|
||||||
|
#define DEF_OVERWORLD_WATER_SPRINGS "0, 0; 10, 10; 11, 75; 16, 83; 20, 83; 24, 78; 32, 62; 40, 40; 44, 15; 48, 7; 56, 2; 64, 1; 255, 0"
|
||||||
|
#define DEF_OVERWORLD_LAVA_SPRINGS "0, 0; 10, 5; 11, 45; 48, 2; 64, 1; 255, 0"
|
||||||
|
#define DEF_END_WATER_SPRINGS "0, 0; 255, 0"
|
||||||
|
#define DEF_END_LAVA_SPRINGS "0, 0; 255, 0"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -629,3 +641,166 @@ void cFinishGenDeadBushes::GenFinish(
|
||||||
} // for i
|
} // for i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cFinishGenFluidSprings:
|
||||||
|
|
||||||
|
cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, const cWorld & a_World) :
|
||||||
|
m_Noise(a_Seed + a_Fluid * 100), // Need to take fluid into account, otherwise water and lava springs generate next to each other
|
||||||
|
m_HeightDistribution(255),
|
||||||
|
m_Fluid(a_Fluid)
|
||||||
|
{
|
||||||
|
bool IsWater = (a_Fluid == E_BLOCK_WATER);
|
||||||
|
AString SectionName = IsWater ? "WaterSprings" : "LavaSprings";
|
||||||
|
AString DefaultHeightDistribution;
|
||||||
|
int DefaultChance;
|
||||||
|
switch (a_World.GetDimension())
|
||||||
|
{
|
||||||
|
case cWorld::dimNether:
|
||||||
|
{
|
||||||
|
DefaultHeightDistribution = IsWater ? DEF_NETHER_WATER_SPRINGS : DEF_NETHER_LAVA_SPRINGS;
|
||||||
|
DefaultChance = IsWater ? 0 : 15;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case cWorld::dimOverworld:
|
||||||
|
{
|
||||||
|
DefaultHeightDistribution = IsWater ? DEF_OVERWORLD_WATER_SPRINGS : DEF_OVERWORLD_LAVA_SPRINGS;
|
||||||
|
DefaultChance = IsWater ? 24 : 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case cWorld::dimEnd:
|
||||||
|
{
|
||||||
|
DefaultHeightDistribution = IsWater ? DEF_END_WATER_SPRINGS : DEF_END_LAVA_SPRINGS;
|
||||||
|
DefaultChance = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ASSERT(!"Unhandled world dimension");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // switch (dimension)
|
||||||
|
AString HeightDistribution = a_IniFile.GetValueSet(SectionName, "HeightDistribution", DefaultHeightDistribution);
|
||||||
|
m_HeightDistribution.SetDefString(HeightDistribution);
|
||||||
|
m_Chance = a_IniFile.GetValueSetI(SectionName, "Chance", DefaultChance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cFinishGenFluidSprings::GenFinish(
|
||||||
|
int a_ChunkX, int a_ChunkZ,
|
||||||
|
cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
|
||||||
|
cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
|
||||||
|
cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
|
||||||
|
const cChunkDef::BiomeMap & a_BiomeMap, // Biomes to adhere to
|
||||||
|
cEntityList & a_Entities, // Entities may be added or deleted
|
||||||
|
cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ChanceRnd = (m_Noise.IntNoise3DInt(128 * a_ChunkX, 512, 256 * a_ChunkZ) / 13) % 100;
|
||||||
|
if (ChanceRnd > m_Chance)
|
||||||
|
{
|
||||||
|
// Not in this chunk
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the height at which to try:
|
||||||
|
int Height = m_Noise.IntNoise3DInt(128 * a_ChunkX, 512, 256 * a_ChunkZ) / 11;
|
||||||
|
Height %= m_HeightDistribution.GetSum();
|
||||||
|
Height = m_HeightDistribution.MapValue(Height);
|
||||||
|
|
||||||
|
// Try adding the spring at the height, if unsuccessful, move lower:
|
||||||
|
for (int y = Height; y > 1; y--)
|
||||||
|
{
|
||||||
|
// TODO: randomize the order in which the coords are being checked
|
||||||
|
for (int z = 1; z < cChunkDef::Width - 1; z++)
|
||||||
|
{
|
||||||
|
for (int x = 1; x < cChunkDef::Width - 1; x++)
|
||||||
|
{
|
||||||
|
switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z))
|
||||||
|
{
|
||||||
|
case E_BLOCK_NETHERRACK:
|
||||||
|
{
|
||||||
|
if (m_Fluid != E_BLOCK_LAVA)
|
||||||
|
{
|
||||||
|
// Only lava springs in the netherrack
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// fallthrough:
|
||||||
|
}
|
||||||
|
case E_BLOCK_STONE:
|
||||||
|
{
|
||||||
|
if (TryPlaceSpring(a_BlockTypes, a_BlockMeta, x, y, z))
|
||||||
|
{
|
||||||
|
// Succeeded, bail out
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // switch (BlockType)
|
||||||
|
} // for x
|
||||||
|
} // for y
|
||||||
|
} // for y
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cFinishGenFluidSprings::TryPlaceSpring(
|
||||||
|
cChunkDef::BlockTypes & a_BlockTypes,
|
||||||
|
cChunkDef::BlockNibbles & a_BlockMetas,
|
||||||
|
int x, int y, int z
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air
|
||||||
|
// Also, its neighbor on top of it must be non-air
|
||||||
|
if (cChunkDef::GetBlock(a_BlockTypes, x, y + 1, z) == E_BLOCK_AIR)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
} Coords[] =
|
||||||
|
{
|
||||||
|
{-1, 0, 0},
|
||||||
|
{ 1, 0, 0},
|
||||||
|
{ 0, -1, 0},
|
||||||
|
{ 0, 0, -1},
|
||||||
|
{ 0, 0, 1},
|
||||||
|
} ;
|
||||||
|
int NumAirNeighbors = 0;
|
||||||
|
for (int i = 0; i < ARRAYCOUNT(Coords); i++)
|
||||||
|
{
|
||||||
|
switch (cChunkDef::GetBlock(a_BlockTypes, x + Coords[i].x, y + Coords[i].y, z + Coords[i].z))
|
||||||
|
{
|
||||||
|
case E_BLOCK_AIR:
|
||||||
|
{
|
||||||
|
NumAirNeighbors += 1;
|
||||||
|
if (NumAirNeighbors > 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NumAirNeighbors == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has exactly one air neighbor, place a spring:
|
||||||
|
cChunkDef::SetBlock(a_BlockTypes, x, y, z, m_Fluid);
|
||||||
|
cChunkDef::SetNibble(a_BlockMetas, x, y, z, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "ComposableGenerator.h"
|
#include "ComposableGenerator.h"
|
||||||
#include "../Noise.h"
|
#include "../Noise.h"
|
||||||
|
#include "../ProbabDistrib.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -223,3 +224,39 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cFinishGenFluidSprings :
|
||||||
|
public cFinishGen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, const cWorld & a_World);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
cNoise m_Noise;
|
||||||
|
cProbabDistrib m_HeightDistribution;
|
||||||
|
BLOCKTYPE m_Fluid;
|
||||||
|
int m_Chance; ///< Chance, [0..100], that a spring will be generated in a chunk
|
||||||
|
|
||||||
|
// cFinishGen override:
|
||||||
|
virtual void GenFinish(
|
||||||
|
int a_ChunkX, int a_ChunkZ,
|
||||||
|
cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
|
||||||
|
cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
|
||||||
|
cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
|
||||||
|
const cChunkDef::BiomeMap & a_BiomeMap, // Biomes to adhere to
|
||||||
|
cEntityList & a_Entities, // Entities may be added or deleted
|
||||||
|
cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
|
||||||
|
) override;
|
||||||
|
|
||||||
|
/// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful
|
||||||
|
bool TryPlaceSpring(
|
||||||
|
cChunkDef::BlockTypes & a_BlockTypes,
|
||||||
|
cChunkDef::BlockNibbles & a_BlockMetas,
|
||||||
|
int x, int y, int z
|
||||||
|
);
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ void cListenThread::SetReuseAddr(bool a_Reuse)
|
||||||
|
|
||||||
bool cListenThread::CreateSockets(const AString & a_PortsString)
|
bool cListenThread::CreateSockets(const AString & a_PortsString)
|
||||||
{
|
{
|
||||||
AStringVector Ports = StringSplit(a_PortsString, ",");
|
AStringVector Ports = StringSplitAndTrim(a_PortsString, ",");
|
||||||
|
|
||||||
if (Ports.empty())
|
if (Ports.empty())
|
||||||
{
|
{
|
||||||
|
@ -119,10 +119,10 @@ bool cListenThread::CreateSockets(const AString & a_PortsString)
|
||||||
|
|
||||||
for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
|
for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
int Port = atoi(Trim(*itr).c_str());
|
int Port = atoi(itr->c_str());
|
||||||
if ((Port <= 0) || (Port > 65535))
|
if ((Port <= 0) || (Port > 65535))
|
||||||
{
|
{
|
||||||
LOGWARNING("Invalid port specified: \"%s\".", Trim(*itr).c_str());
|
LOGWARNING("Invalid port specified: \"%s\".", itr->c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_Sockets.push_back(cSocket::CreateSocket(m_Family));
|
m_Sockets.push_back(cSocket::CreateSocket(m_Family));
|
||||||
|
|
141
source/ProbabDistrib.cpp
Normal file
141
source/ProbabDistrib.cpp
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
|
||||||
|
// ProbabDistrib.cpp
|
||||||
|
|
||||||
|
// Implements the cProbabDistrib class representing a discrete probability distribution curve and random generator
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ProbabDistrib.h"
|
||||||
|
#include "MersenneTwister.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cProbabDistrib::cProbabDistrib(int a_MaxValue) :
|
||||||
|
m_MaxValue(a_MaxValue),
|
||||||
|
m_Sum(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProbabDistrib::SetPoints(const cProbabDistrib::cPoints & a_Points)
|
||||||
|
{
|
||||||
|
ASSERT(!a_Points.empty());
|
||||||
|
m_Sum = 0;
|
||||||
|
m_Cumulative.clear();
|
||||||
|
m_Cumulative.reserve(a_Points.size() + 1);
|
||||||
|
int ProbSum = 0;
|
||||||
|
int LastProb = 0;
|
||||||
|
int LastValue = 0;
|
||||||
|
if (a_Points[0].m_Value != 0)
|
||||||
|
{
|
||||||
|
m_Cumulative.push_back(cPoint(0, 0)); // Always push in the [0, 0] point for easier search algorithm bounds
|
||||||
|
}
|
||||||
|
for (cPoints::const_iterator itr = a_Points.begin(), end = a_Points.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (itr->m_Value == LastValue)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the current trapezoid to the sum:
|
||||||
|
ProbSum += (LastProb + itr->m_Probability) * (itr->m_Value - LastValue) / 2;
|
||||||
|
LastProb = itr->m_Probability;
|
||||||
|
LastValue = itr->m_Value;
|
||||||
|
m_Cumulative.push_back(cPoint(itr->m_Value, ProbSum));
|
||||||
|
} // for itr - a_Points[]
|
||||||
|
if (LastValue != m_MaxValue)
|
||||||
|
{
|
||||||
|
m_Cumulative.push_back(cPoint(m_MaxValue, 0)); // Always push in the last point for easier search algorithm bounds
|
||||||
|
}
|
||||||
|
m_Sum = ProbSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cProbabDistrib::SetDefString(const AString & a_DefString)
|
||||||
|
{
|
||||||
|
AStringVector Points = StringSplitAndTrim(a_DefString, ";");
|
||||||
|
if (Points.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cPoints Pts;
|
||||||
|
for (AStringVector::const_iterator itr = Points.begin(), end = Points.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
AStringVector Split = StringSplitAndTrim(*itr, ",");
|
||||||
|
if (Split.size() != 2)
|
||||||
|
{
|
||||||
|
// Bad format
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int Value = atoi(Split[0].c_str());
|
||||||
|
int Prob = atoi(Split[1].c_str());
|
||||||
|
if (
|
||||||
|
((Value == 0) && (Split[0] != "0")) ||
|
||||||
|
((Prob == 0) && (Split[1] != "0"))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Number parse error
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Pts.push_back(cPoint(Value, Prob));
|
||||||
|
} // for itr - Points[]
|
||||||
|
|
||||||
|
SetPoints(Pts);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cProbabDistrib::Random(MTRand & a_Rand) const
|
||||||
|
{
|
||||||
|
int v = a_Rand.randInt(m_Sum);
|
||||||
|
return MapValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cProbabDistrib::MapValue(int a_OrigValue) const
|
||||||
|
{
|
||||||
|
ASSERT(a_OrigValue >= 0);
|
||||||
|
ASSERT(a_OrigValue < m_Sum);
|
||||||
|
|
||||||
|
// Binary search through m_Cumulative for placement:
|
||||||
|
size_t Lo = 0;
|
||||||
|
size_t Hi = m_Cumulative.size() - 1;
|
||||||
|
while (Hi - Lo > 1)
|
||||||
|
{
|
||||||
|
int Mid = (Lo + Hi) / 2;
|
||||||
|
int MidProbab = m_Cumulative[Mid].m_Probability;
|
||||||
|
if (MidProbab < a_OrigValue)
|
||||||
|
{
|
||||||
|
Lo = Mid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Hi = Mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(Hi - Lo == 1);
|
||||||
|
|
||||||
|
// Linearly interpolate between Lo and Hi:
|
||||||
|
int ProbDif = m_Cumulative[Hi].m_Probability - m_Cumulative[Lo].m_Probability;
|
||||||
|
int ValueDif = m_Cumulative[Hi].m_Value - m_Cumulative[Lo].m_Value;
|
||||||
|
return m_Cumulative[Lo].m_Value + (a_OrigValue - m_Cumulative[Lo].m_Probability) * ValueDif / ProbDif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
74
source/ProbabDistrib.h
Normal file
74
source/ProbabDistrib.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
// ProbabDistrib.h
|
||||||
|
|
||||||
|
// Declares the cProbabDistrib class representing a discrete probability distribution curve and random generator
|
||||||
|
|
||||||
|
/*
|
||||||
|
Usage:
|
||||||
|
1, Create a cProbabDistrib instance
|
||||||
|
2, Initialize the distribution either programmatically, using the SetPoints() function, or using a definition string
|
||||||
|
3, Ask for random numbers in that probability distribution using the Random() function
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd:
|
||||||
|
class MTRand;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cProbabDistrib
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class cPoint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int m_Value;
|
||||||
|
int m_Probability;
|
||||||
|
|
||||||
|
cPoint(int a_Value, int a_Probability) :
|
||||||
|
m_Value(a_Value),
|
||||||
|
m_Probability(a_Probability)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
typedef std::vector<cPoint> cPoints;
|
||||||
|
|
||||||
|
|
||||||
|
cProbabDistrib(int a_MaxValue);
|
||||||
|
|
||||||
|
/// Sets the distribution curve using an array of [value, probability] points, linearly interpolated. a_Points must not be empty.
|
||||||
|
void SetPoints(const cPoints & a_Points);
|
||||||
|
|
||||||
|
/// Sets the distribution curve using a definition string; returns true on successful parse
|
||||||
|
bool SetDefString(const AString & a_DefString);
|
||||||
|
|
||||||
|
/// Gets a random value from a_Rand, shapes it into the distribution curve and returns the value.
|
||||||
|
int Random(MTRand & a_Rand) const;
|
||||||
|
|
||||||
|
/// Maps value in range [0, m_Sum] into the range [0, m_MaxValue] using the stored probability
|
||||||
|
int MapValue(int a_OrigValue) const;
|
||||||
|
|
||||||
|
int GetSum(void) const { return m_Sum; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int m_MaxValue;
|
||||||
|
cPoints m_Cumulative; ///< Cumulative probability of the values, sorted, for fast bsearch lookup
|
||||||
|
int m_Sum; ///< Sum of all the probabilities across all values in the domain; -1 if not set
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,26 @@ AStringVector StringSplit(const AString & str, const AString & delim)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AStringVector StringSplitAndTrim(const AString & str, const AString & delim)
|
||||||
|
{
|
||||||
|
AStringVector results;
|
||||||
|
size_t cutAt = 0;
|
||||||
|
size_t Prev = 0;
|
||||||
|
while ((cutAt = str.find_first_of(delim, Prev)) != str.npos)
|
||||||
|
{
|
||||||
|
results.push_back(TrimString(str.substr(Prev, cutAt - Prev)));
|
||||||
|
Prev = cutAt + delim.length();
|
||||||
|
}
|
||||||
|
if (Prev < str.length())
|
||||||
|
{
|
||||||
|
results.push_back(TrimString(str.substr(Prev)));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString TrimString(const AString & str)
|
AString TrimString(const AString & str)
|
||||||
{
|
{
|
||||||
size_t len = str.length();
|
size_t len = str.length();
|
||||||
|
@ -506,7 +526,11 @@ AString & CreateHexDump(AString & a_Out, const void * a_Data, int a_Size, int a_
|
||||||
k = a_LineLength;
|
k = a_LineLength;
|
||||||
}
|
}
|
||||||
memset(line, ' ', sizeof(line));
|
memset(line, ' ', sizeof(line));
|
||||||
|
#ifdef _MSC_VER // MSVC provides a "secure" version of sprintf()
|
||||||
|
line[sprintf_s(line, sizeof(line), "%08x:", i)] = 32; // Remove the terminating NULL that sprintf puts there
|
||||||
|
#else
|
||||||
line[sprintf(line, "%08x:", i)] = 32; // Remove the terminating NULL that sprintf puts there
|
line[sprintf(line, "%08x:", i)] = 32; // Remove the terminating NULL that sprintf puts there
|
||||||
|
#endif
|
||||||
p = line + 10;
|
p = line + 10;
|
||||||
q = p + 2 + a_LineLength * 3 + 1;
|
q = p + 2 + a_LineLength * 3 + 1;
|
||||||
for (int j = 0; j < k; j++)
|
for (int j = 0; j < k; j++)
|
||||||
|
|
|
@ -36,6 +36,9 @@ extern AString & AppendPrintf (AString & str, const char * format, ...);
|
||||||
/// Split the string at delimiters, return as a stringvector
|
/// Split the string at delimiters, return as a stringvector
|
||||||
extern AStringVector StringSplit(const AString & str, const AString & delim);
|
extern AStringVector StringSplit(const AString & str, const AString & delim);
|
||||||
|
|
||||||
|
/// Split the string at delimiters and trim each value, return as a stringvector
|
||||||
|
extern AStringVector StringSplitAndTrim(const AString & str, const AString & delim);
|
||||||
|
|
||||||
/// Trime whitespace at both ends of the string
|
/// Trime whitespace at both ends of the string
|
||||||
extern AString TrimString(const AString & str);
|
extern AString TrimString(const AString & str);
|
||||||
|
|
||||||
|
@ -63,9 +66,6 @@ extern AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AStr
|
||||||
/// Creates a nicely formatted HEX dump of the given memory block. Max a_BytesPerLine is 120
|
/// Creates a nicely formatted HEX dump of the given memory block. Max a_BytesPerLine is 120
|
||||||
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, int a_Size, int a_BytesPerLine);
|
extern AString & CreateHexDump(AString & a_Out, const void * a_Data, int a_Size, int a_BytesPerLine);
|
||||||
|
|
||||||
/// Removes whitespace at the beginning and left of the string
|
|
||||||
extern AString Trim(const AString & a_Text);
|
|
||||||
|
|
||||||
// If you have any other string helper functions, declare them here
|
// If you have any other string helper functions, declare them here
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user