summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft <github@xoft.cz>2014-03-09 22:04:29 +0100
committermadmaxoft <github@xoft.cz>2014-03-09 22:04:29 +0100
commit0e985293b50ec89a163f40222825b3c147135b9a (patch)
tree6a94d8e56f0db696246fdee73673f963c82aa5db
parentHardened cCuboid with asserts for its assumptions. (diff)
downloadcuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar.gz
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar.bz2
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar.lz
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar.xz
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.tar.zst
cuberite-0e985293b50ec89a163f40222825b3c147135b9a.zip
-rw-r--r--src/Generating/ComposableGenerator.cpp5
-rw-r--r--src/Generating/POCPieceGenerator.cpp265
-rw-r--r--src/Generating/POCPieceGenerator.h54
-rw-r--r--src/Generating/PieceGenerator.cpp31
-rw-r--r--src/Generating/PieceGenerator.h10
5 files changed, 359 insertions, 6 deletions
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index e96e9a645..6c00b5905 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -22,6 +22,7 @@
#include "EndGen.h"
#include "MineShafts.h"
#include "Noise3DGenerator.h"
+#include "POCPieceGenerator.h"
#include "Ravines.h"
@@ -364,6 +365,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
m_FinishGens.push_back(new cStructGenOreNests(Seed));
}
+ else if (NoCaseCompare(*itr, "POCPieces") == 0)
+ {
+ m_FinishGens.push_back(new cPOCPieceGenerator(Seed));
+ }
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
{
m_FinishGens.push_back(new cFinishGenPreSimulator);
diff --git a/src/Generating/POCPieceGenerator.cpp b/src/Generating/POCPieceGenerator.cpp
new file mode 100644
index 000000000..9edfcc64f
--- /dev/null
+++ b/src/Generating/POCPieceGenerator.cpp
@@ -0,0 +1,265 @@
+
+// POCPieceGenerator.cpp
+
+// Implements the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
+// The generator generates a maze of rooms at {0, 100, 0}
+
+#include "Globals.h"
+#include "POCPieceGenerator.h"
+#include "ChunkDesc.h"
+
+
+
+
+
+/** POC pieces are simple boxes that have connectors in the middle of their walls.
+Each wall has one connector, there are 3 connector types that get assigned semi-randomly.
+The piece also knows how to imprint itself in a cChunkDesc, each piece has a different color glass
+and each connector is uses a different color wool frame. */
+class cPOCPiece :
+ public cPiece
+{
+public:
+ cPOCPiece(int a_Size) :
+ m_Size(a_Size)
+ {
+ m_Connectors.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM));
+ m_Connectors.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP));
+ m_Connectors.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM));
+ m_Connectors.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP));
+ }
+
+
+ /** Imprints the piece in the specified chunk. Assumes they intersect. */
+ void ImprintInChunk(cChunkDesc & a_ChunkDesc, const Vector3i & a_Pos, int a_NumCCWRotations)
+ {
+ int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ Vector3i Min = a_Pos;
+ Min.Move(-BlockX, 0, -BlockZ);
+ Vector3i Max = Min;
+ Max.Move(m_Size - 1, 2, m_Size - 1);
+ ASSERT(Min.x < cChunkDef::Width);
+ ASSERT(Min.z < cChunkDef::Width);
+ ASSERT(Max.x >= 0);
+ ASSERT(Max.z >= 0);
+ if (Min.x >= 0)
+ {
+ // Draw the XM wall:
+ a_ChunkDesc.FillRelCuboid(Min.x, Min.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
+ }
+ if (Min.z >= 0)
+ {
+ // Draw the ZM wall:
+ a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Min.z, Min.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
+ }
+ if (Max.x < cChunkDef::Width)
+ {
+ // Draw the XP wall:
+ a_ChunkDesc.FillRelCuboid(Max.x, Max.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
+ }
+ if (Max.z < cChunkDef::Width)
+ {
+ // Draw the ZP wall:
+ a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Max.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
+ }
+
+ // Draw all the connectors:
+ for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr)
+ {
+ cConnector Conn = cPiece::RotateMoveConnector(*itr, a_NumCCWRotations, a_Pos.x, a_Pos.y, a_Pos.z);
+ Conn.m_Pos.Move(-BlockX, 0, -BlockZ);
+ if (
+ (Conn.m_Pos.x >= 0) && (Conn.m_Pos.x < cChunkDef::Width) &&
+ (Conn.m_Pos.z >= 0) && (Conn.m_Pos.z < cChunkDef::Width)
+ )
+ {
+ a_ChunkDesc.SetBlockTypeMeta(Conn.m_Pos.x, Conn.m_Pos.y, Conn.m_Pos.z, E_BLOCK_WOOL, itr->m_Type % 16);
+ }
+
+ /*
+ // TODO: Frame the connectors
+ switch (itr->m_Direction)
+ {
+ case BLOCK_FACE_XM:
+ case BLOCK_FACE_XP:
+ {
+ // TODO
+ break;
+ }
+
+ case BLOCK_FACE_ZM:
+ case BLOCK_FACE_ZP:
+ {
+ // TODO
+ break;
+ }
+ }
+ */
+ } // for itr - m_Connectors[]
+ }
+
+protected:
+ int m_Size;
+ cConnectors m_Connectors;
+
+ // cPiece overrides:
+ virtual cConnectors GetConnectors(void) const override
+ {
+ return m_Connectors;
+ }
+
+ virtual Vector3i GetSize(void) const override
+ {
+ return Vector3i(m_Size, 3, m_Size);
+ }
+
+ virtual cCuboid GetHitBox(void) const override
+ {
+ return cCuboid(0, 0, 0, m_Size - 1, 2, m_Size - 1);
+ }
+
+ virtual bool CanRotateCCW(int a_NumRotations) const override
+ {
+ return true;
+ }
+};
+
+
+
+
+
+static void DebugPieces(const cPlacedPieces & a_Pieces)
+{
+ size_t idx = 0;
+ for (cPlacedPieces::const_iterator itr = a_Pieces.begin(), end = a_Pieces.end(); itr != end; ++itr, ++idx)
+ {
+ const cCuboid & HitBox = (*itr)->GetHitBox();
+ printf(" %u: %d rotations, {%d - %d, %d - %d}\n",
+ idx, (*itr)->GetNumCCWRotations(),
+ HitBox.p1.x, HitBox.p2.x, HitBox.p1.z, HitBox.p2.z
+ );
+ } // for itr - a_Pieces[]
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cPOCPieceGenerator:
+
+cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) :
+ m_Seed(a_Seed)
+{
+ // Prepare a vector of available pieces:
+ m_AvailPieces.push_back(new cPOCPiece(5));
+ m_AvailPieces.push_back(new cPOCPiece(7));
+ m_AvailPieces.push_back(new cPOCPiece(9));
+
+ // Generate the structure:
+ cBFSPieceGenerator Gen(*this, a_Seed);
+ Gen.PlacePieces(0, 50, 0, 6, m_Pieces);
+
+ // DebugPieces(m_Pieces);
+
+ // Get the smallest cuboid encompassing the entire generated structure:
+ cCuboid Bounds(0, 50, 0, 0, 50, 0);
+ for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
+ {
+ Vector3i MinCoords = (*itr)->GetCoords();
+ Bounds.Engulf(MinCoords);
+ Bounds.Engulf(MinCoords + (*itr)->GetPiece().GetSize());
+ } // for itr - m_Pieces[]
+ m_Bounds = Bounds;
+}
+
+
+
+
+
+cPOCPieceGenerator::~cPOCPieceGenerator()
+{
+ cPieceGenerator::FreePieces(m_Pieces);
+}
+
+
+
+
+
+void cPOCPieceGenerator::GenFinish(cChunkDesc & a_ChunkDesc)
+{
+ int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ if (
+ (BlockX + 16 < m_Bounds.p1.x) || (BlockX > m_Bounds.p2.x) || // X coords out of bounds of the generated structure
+ (BlockZ + 16 < m_Bounds.p1.z) || (BlockZ > m_Bounds.p2.z) // Z coords out of bounds of the generated structure
+ )
+ {
+ return;
+ }
+
+ // Imprint each piece in the chunk:
+ for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
+ {
+ const Vector3i & Pos = (*itr)->GetCoords();
+ Vector3i Size = (*itr)->GetPiece().GetSize();
+ if (((*itr)->GetNumCCWRotations() % 2) == 1)
+ {
+ std::swap(Size.x, Size.z);
+ }
+ if (
+ (Pos.x >= BlockX + 16) || (Pos.x + Size.x - 1 < BlockX) ||
+ (Pos.z >= BlockZ + 16) || (Pos.z + Size.z - 1 < BlockZ)
+ )
+ {
+ // This piece doesn't intersect the chunk
+ continue;
+ }
+
+ ((cPOCPiece &)(*itr)->GetPiece()).ImprintInChunk(a_ChunkDesc, Pos, (*itr)->GetNumCCWRotations());
+ } // for itr - m_Pieces[]
+ a_ChunkDesc.UpdateHeightmap();
+}
+
+
+
+
+
+cPieces cPOCPieceGenerator::GetPiecesWithConnector(int a_ConnectorType)
+{
+ // Each piece has each connector
+ return m_AvailPieces;
+}
+
+
+
+
+
+cPieces cPOCPieceGenerator::GetStartingPieces(void)
+{
+ // Any piece can be a starting piece
+ return m_AvailPieces;
+}
+
+
+
+
+
+void cPOCPieceGenerator::PiecePlaced(const cPiece & a_Piece)
+{
+ UNUSED(a_Piece);
+}
+
+
+
+
+
+void cPOCPieceGenerator::Reset(void)
+{
+ // Nothing needed
+}
+
+
+
+
diff --git a/src/Generating/POCPieceGenerator.h b/src/Generating/POCPieceGenerator.h
new file mode 100644
index 000000000..de3114ce0
--- /dev/null
+++ b/src/Generating/POCPieceGenerator.h
@@ -0,0 +1,54 @@
+
+// POCPieceGenerator.h
+
+// Declares the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
+// The generator generates a maze of rooms at {0, 100, 0}
+
+
+
+
+
+#pragma once
+
+#include "PieceGenerator.h"
+#include "ComposableGenerator.h"
+
+
+
+
+
+class cPOCPieceGenerator :
+ public cFinishGen,
+ protected cPiecePool
+{
+public:
+ cPOCPieceGenerator(int a_Seed);
+ ~cPOCPieceGenerator();
+
+protected:
+ int m_Seed;
+
+ /** The pieces from which the generated structure is built. */
+ cPieces m_AvailPieces;
+
+ /** The placed pieces of the generated structure. */
+ cPlacedPieces m_Pieces;
+
+ /** Bounds of the complete structure, to save on processing outside chunks. */
+ cCuboid m_Bounds;
+
+
+ // cFinishGen overrides:
+ virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
+
+ // cPiecePool overrides:
+ virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
+ virtual cPieces GetStartingPieces(void) override;
+ virtual void PiecePlaced(const cPiece & a_Piece) override;
+ virtual void Reset(void) override;
+} ;
+
+
+
+
+
diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp
index c8e4ec71b..e3de5b951 100644
--- a/src/Generating/PieceGenerator.cpp
+++ b/src/Generating/PieceGenerator.cpp
@@ -11,6 +11,8 @@
+#ifdef SELF_TEST
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Self-test:
@@ -132,6 +134,8 @@ protected:
}
} g_Test;
+#endif // SELF_TEST
+
@@ -287,6 +291,7 @@ cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece
{
m_Depth = (m_Parent == NULL) ? 0 : (m_Parent->GetDepth() + 1);
m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z);
+ m_HitBox.Sort();
}
@@ -375,10 +380,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
/* YM, YP, ZM, ZP, XM, XP
/* YM */ { 0, 0, 0, 0, 0, 0},
/* YP */ { 0, 0, 0, 0, 0, 0},
- /* ZM */ { 0, 0, 0, 2, 1, 3},
- /* ZP */ { 0, 0, 2, 0, 3, 1},
- /* XM */ { 0, 0, 3, 1, 0, 2},
- /* XP */ { 0, 0, 1, 3, 2, 0},
+ /* ZM */ { 0, 0, 2, 0, 1, 3},
+ /* ZP */ { 0, 0, 0, 2, 3, 1},
+ /* XM */ { 0, 0, 3, 1, 2, 0},
+ /* XP */ { 0, 0, 1, 3, 0, 2},
};
// Get a list of available connections:
@@ -389,8 +394,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
Vector3i ConnPos = a_Connector.m_Pos; // The position at which the new connector should be placed - 1 block away from the connector
AddFaceDirection(ConnPos.x, ConnPos.y, ConnPos.z, a_Connector.m_Direction);
+ /*
// DEBUG:
- printf("Placing piece at pos {%d, %d, %d}, direction %s\n", ConnPos.x, ConnPos.y, ConnPos.z, BlockFaceToString(a_Connector.m_Direction).c_str());
+ printf("Placing piece at connector pos {%d, %d, %d}, direction %s\n", ConnPos.x, ConnPos.y, ConnPos.z, BlockFaceToString(a_Connector.m_Direction).c_str());
+ //*/
for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP)
{
@@ -427,11 +434,15 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
cConnection & Conn = Connections[rnd % Connections.size()];
// Place the piece:
+ /*
+ // DEBUG
printf("Chosen connector at {%d, %d, %d}, direction %s, needs %d rotations\n",
Conn.m_Connector.m_Pos.x, Conn.m_Connector.m_Pos.y, Conn.m_Connector.m_Pos.z,
BlockFaceToString(Conn.m_Connector.m_Direction).c_str(),
Conn.m_NumCCWRotations
);
+ //*/
+
Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations);
ConnPos -= NewPos;
cPlacedPiece * PlacedPiece = new cPlacedPiece(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations);
@@ -440,8 +451,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
// Add the new piece's connectors to the list of free connectors:
cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors();
+ /*
// DEBUG:
printf("Adding %u connectors to the pool\n", Connectors.size() - 1);
+ //*/
for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
{
@@ -471,6 +484,7 @@ bool cPieceGenerator::CheckConnection(
{
// For each placed piece, test the hitbox against the new piece:
cCuboid RotatedHitBox = a_Piece.RotateHitBoxToConnector(a_NewConnector, a_ToPos, a_NumCCWRotations);
+ RotatedHitBox.Sort();
for (cPlacedPieces::const_iterator itr = a_OutPieces.begin(), end = a_OutPieces.end(); itr != end; ++itr)
{
if ((*itr)->GetHitBox().DoesIntersect(RotatedHitBox))
@@ -485,6 +499,7 @@ bool cPieceGenerator::CheckConnection(
+//*
// DEBUG:
void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed)
{
@@ -501,6 +516,7 @@ void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors
);
} // for itr - a_ConnectorPool[]
}
+//*/
@@ -553,6 +569,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
// Place the starting piece:
a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockY, a_BlockZ, ConnectorPool));
+ /*
// DEBUG:
printf("Placed the starting piece at {%d, %d, %d}\n", a_BlockX, a_BlockY, a_BlockZ);
cCuboid Hitbox = a_OutPieces[0]->GetHitBox();
@@ -563,6 +580,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
);
DebugConnectorPool(ConnectorPool, 0);
+ //*/
// Place pieces at the available connectors:
/*
@@ -578,6 +596,8 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
{
if (TryPlacePieceAtConnector(*Conn.m_Piece, Conn.m_Connector, a_OutPieces, ConnectorPool))
{
+ /*
+ // DEBUG:
const cPlacedPiece * NewPiece = a_OutPieces.back();
const Vector3i & Coords = NewPiece->GetCoords();
printf("Placed a new piece at {%d, %d, %d}, rotation %d\n", Coords.x, Coords.y, Coords.z, NewPiece->GetNumCCWRotations());
@@ -589,6 +609,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
);
DebugConnectorPool(ConnectorPool, NumProcessed + 1);
+ //*/
}
}
NumProcessed++;
diff --git a/src/Generating/PieceGenerator.h b/src/Generating/PieceGenerator.h
index 310c21fdd..9dd5bcfba 100644
--- a/src/Generating/PieceGenerator.h
+++ b/src/Generating/PieceGenerator.h
@@ -30,6 +30,9 @@ Each uses a slightly different approach to generating:
class cPiece
{
public:
+ // Force a virtual destructor in all descendants
+ virtual ~cPiece() {}
+
struct cConnector
{
/** Position relative to the piece */
@@ -82,9 +85,14 @@ typedef std::vector<cPiece *> cPieces;
+/** This class is an interface that provides pieces for the generator. It can keep track of what pieces were
+placed and adjust the returned piece vectors. */
class cPiecePool
{
public:
+ // Force a virtual destructor in all descendants:
+ virtual ~cPiecePool() {}
+
/** Returns a list of pieces that contain the specified connector type.
The cPiece pointers returned are managed by the pool and the caller doesn't free them. */
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) = 0;
@@ -140,7 +148,7 @@ public:
/** Cleans up all the memory used by the placed pieces.
Call this utility function instead of freeing the items on your own. */
- void FreePieces(cPlacedPieces & a_PlacedPieces);
+ static void FreePieces(cPlacedPieces & a_PlacedPieces);
protected:
/** The type used for storing a connection from one piece to another, while building the piece tree. */