summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/Generating/CompoGen.cpp98
-rw-r--r--source/Generating/CompoGen.h28
-rw-r--r--source/Generating/ComposableGenerator.cpp4
-rw-r--r--source/Protocol/Protocol125.cpp4
-rw-r--r--source/Protocol/Protocol132.cpp2
-rw-r--r--source/World.cpp16
-rw-r--r--source/World.h20
7 files changed, 164 insertions, 8 deletions
diff --git a/source/Generating/CompoGen.cpp b/source/Generating/CompoGen.cpp
index 53d10c674..e1d620ab3 100644
--- a/source/Generating/CompoGen.cpp
+++ b/source/Generating/CompoGen.cpp
@@ -425,3 +425,101 @@ void cCompoGenBiomal::FillColumnPattern(int a_RelX, int a_RelZ, int a_Height, cC
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cCompoGenNether:
+
+cCompoGenNether::cCompoGenNether(int a_Seed) :
+ m_Noise1(a_Seed + 10),
+ m_Noise2(a_Seed * a_Seed * 10 + a_Seed * 1000 + 6000),
+ m_Threshold(0)
+{
+}
+
+
+
+
+
+void cCompoGenNether::ComposeTerrain(
+ int a_ChunkX, int a_ChunkZ,
+ cChunkDef::BlockTypes & a_BlockTypes, // BlockTypes to be generated
+ cChunkDef::BlockNibbles & a_BlockMeta, // BlockMetas to be generated
+ const cChunkDef::HeightMap & a_HeightMap, // The height map to fit
+ const cChunkDef::BiomeMap & a_BiomeMap, // Biomes to adhere to
+ cEntityList & a_Entities, // Entitites may be generated along with the terrain
+ cBlockEntityList & a_BlockEntities // Block entitites may be generated (chests / furnaces / ...)
+)
+{
+ HEIGHTTYPE MaxHeight = 0;
+ for (int i = 0; i < ARRAYCOUNT(a_HeightMap); i++)
+ {
+ if (a_HeightMap[i] > MaxHeight)
+ {
+ MaxHeight = a_HeightMap[i];
+ }
+ }
+
+ const int SEGMENT_HEIGHT = 8;
+ const int INTERPOL_X = 16; // Must be a divisor of 16
+ const int INTERPOL_Z = 16; // Must be a divisor of 16
+ // Interpolate the chunk in 16 * SEGMENT_HEIGHT * 16 "segments", each 8 blocks high and each linearly interpolated separately.
+ // Have two buffers, one for the lowest floor and one for the highest floor, so that Y-interpolation can be done between them
+ // Then swap the buffers and use the previously-top one as the current-bottom, without recalculating it.
+
+ int FloorBuf1[17 * 17];
+ int FloorBuf2[17 * 17];
+ int * FloorHi = FloorBuf1;
+ int * FloorLo = FloorBuf2;
+ int BaseX = a_ChunkX * cChunkDef::Width;
+ int BaseZ = a_ChunkZ * cChunkDef::Width;
+
+ // Interpolate the lowest floor:
+ for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
+ {
+ FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
+ m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) *
+ m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) /
+ 256;
+ } // for x, z - FloorLo[]
+ IntArrayLinearInterpolate2D(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z);
+
+ // Interpolate segments:
+ for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
+ {
+ // First update the high floor:
+ for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
+ {
+ FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
+ m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) *
+ m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
+ 256;
+ } // for x, z - FloorLo[]
+ IntArrayLinearInterpolate2D(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z);
+
+ // Interpolate between FloorLo and FloorHi:
+ for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
+ {
+ int Lo = FloorLo[x + 17 * z] / 256;
+ int Hi = FloorHi[x + 17 * z] / 256;
+ for (int y = 0; y < SEGMENT_HEIGHT; y++)
+ {
+ int Val = Lo + (Hi - Lo) * y / SEGMENT_HEIGHT;
+ cChunkDef::SetBlock(a_BlockTypes, x, y + Segment, z, (Val < m_Threshold) ? E_BLOCK_NETHERRACK : E_BLOCK_AIR);
+ }
+ }
+
+ // Swap the floors:
+ std::swap(FloorLo, FloorHi);
+ }
+
+ // Bedrock at the bottom and at the top:
+ for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
+ {
+ cChunkDef::SetBlock(a_BlockTypes, x, 0, z, E_BLOCK_BEDROCK);
+ cChunkDef::SetBlock(a_BlockTypes, x, cChunkDef::GetHeight(a_HeightMap, x, z), z, E_BLOCK_BEDROCK);
+ }
+}
+
+
+
+
diff --git a/source/Generating/CompoGen.h b/source/Generating/CompoGen.h
index 39f57735f..e92ba505c 100644
--- a/source/Generating/CompoGen.h
+++ b/source/Generating/CompoGen.h
@@ -152,3 +152,31 @@ protected:
+
+class cCompoGenNether :
+ public cTerrainCompositionGen
+{
+public:
+ cCompoGenNether(int a_Seed);
+
+protected:
+ cNoise m_Noise1;
+ cNoise m_Noise2;
+
+ int m_Threshold;
+
+ // cTerrainCompositionGen overrides:
+ virtual void ComposeTerrain(
+ int a_ChunkX, int a_ChunkZ,
+ cChunkDef::BlockTypes & a_BlockTypes, // BlockTypes to be generated
+ cChunkDef::BlockNibbles & a_BlockMeta, // BlockMetas to be generated
+ const cChunkDef::HeightMap & a_HeightMap, // The height map to fit
+ const cChunkDef::BiomeMap & a_BiomeMap, // Biomes to adhere to
+ cEntityList & a_Entities, // Entitites may be generated along with the terrain
+ cBlockEntityList & a_BlockEntities // Block entitites may be generated (chests / furnaces / ...)
+ ) override;
+} ;
+
+
+
+
diff --git a/source/Generating/ComposableGenerator.cpp b/source/Generating/ComposableGenerator.cpp
index 793d6a449..0cd6bfb4f 100644
--- a/source/Generating/ComposableGenerator.cpp
+++ b/source/Generating/ComposableGenerator.cpp
@@ -283,6 +283,10 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
BlockBeachBottom, BlockSea
);
}
+ else if (NoCaseCompare(CompoGenName, "nether") == 0)
+ {
+ m_CompositionGen = new cCompoGenNether(m_ChunkGenerator.GetSeed());
+ }
else
{
if (NoCaseCompare(CompoGenName, "biomal") != 0)
diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp
index 0b4b0f942..9514fb278 100644
--- a/source/Protocol/Protocol125.cpp
+++ b/source/Protocol/Protocol125.cpp
@@ -461,7 +461,7 @@ void cProtocol125::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
WriteString(""); // Username, not used
WriteString("default"); // Level type
WriteInt ((int)a_Player.GetGameMode());
- WriteInt (0); // TODO: Dimension (Nether / Overworld / End)
+ WriteInt ((int)(a_World.GetDimension()));
WriteByte (2); // TODO: Difficulty
WriteByte (0); // Unused
WriteByte (60); // Client list width or something
@@ -600,7 +600,7 @@ void cProtocol125::SendRespawn(void)
{
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_RESPAWN);
- WriteInt (0); // TODO: Dimension; 0 = Overworld
+ WriteInt ((int)(m_Client->GetPlayer()->GetWorld()->GetDimension()));
WriteByte (2); // TODO: Difficulty; 2 = Normal
WriteByte ((char)m_Client->GetPlayer()->GetGameMode());
WriteShort (256); // Current world height
diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp
index 0c928bde1..e051bcfa1 100644
--- a/source/Protocol/Protocol132.cpp
+++ b/source/Protocol/Protocol132.cpp
@@ -326,7 +326,7 @@ void cProtocol132::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
WriteInt (a_Player.GetUniqueID()); // EntityID of the player
WriteString("default"); // Level type
WriteByte ((int)a_Player.GetGameMode());
- WriteByte (0); // TODO: Dimension (Nether / Overworld / End)
+ WriteByte ((Byte)(a_World.GetDimension()));
WriteByte (2); // TODO: Difficulty
WriteByte (0); // Unused, used to be world height
WriteByte (8); // Client list width or something
diff --git a/source/World.cpp b/source/World.cpp
index 6ff9395c1..70b70d1f1 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -201,6 +201,22 @@ cWorld::cWorld(const AString & a_WorldName) :
cIniFile IniFile(m_IniFileName);
IniFile.ReadFile();
+ m_Dimension = (eDimension)(IniFile.GetValueSetI("General", "Dimension", 0));
+ switch (m_Dimension)
+ {
+ case dimNether:
+ case dimOverworld:
+ case dimEnd:
+ {
+ break;
+ }
+ default:
+ {
+ LOGWARNING("Unknown dimension: %d. Setting to Overworld (0)", m_Dimension);
+ m_Dimension = dimOverworld;
+ break;
+ }
+ } // switch (m_Dimension)
m_SpawnX = IniFile.GetValueSetF("SpawnPosition", "X", m_SpawnX);
m_SpawnY = IniFile.GetValueSetF("SpawnPosition", "Y", m_SpawnY);
m_SpawnZ = IniFile.GetValueSetF("SpawnPosition", "Z", m_SpawnZ);
diff --git a/source/World.h b/source/World.h
index 781dc3e8c..2e8572b00 100644
--- a/source/World.h
+++ b/source/World.h
@@ -54,12 +54,17 @@ typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
-
-class cWorld // tolua_export
-{ // tolua_export
+// tolua_begin
+class cWorld
+{
public:
- // tolua_begin
+ enum eDimension
+ {
+ dimNether = -1,
+ dimOverworld = 0,
+ dimEnd = 1,
+ } ;
static const char * GetClassStatic(void)
{
@@ -92,6 +97,8 @@ public:
eGameMode GetGameMode(void) const { return m_GameMode; }
bool IsPVPEnabled(void) const { return m_bEnabledPVP; }
bool IsDeepSnowEnabled(void) const { return m_IsDeepSnowEnabled; }
+
+ eDimension GetDimension(void) const { return m_Dimension; }
int GetHeight(int a_BlockX, int a_BlockZ);
@@ -459,7 +466,10 @@ private:
friend class cRoot;
- // This random generator is to be used only in the Tick() method, and thus only in the World-Tick-thread (MTRand is not exactly thread-safe)
+ /// The dimension of the world, used by the client to provide correct lighting scheme
+ eDimension m_Dimension;
+
+ /// This random generator is to be used only in the Tick() method, and thus only in the World-Tick-thread (MTRand is not exactly thread-safe)
MTRand m_TickRand;
double m_SpawnX;