Cuberite
A lightweight, fast and extensible game server for Minecraft
PalettedBlockArea.cpp
Go to the documentation of this file.
1 #include "Globals.h"
2 #include "PalettedBlockArea.h"
3 
4 
5 
6 
7 
9 {
10  // Nothing needed yet
11 }
12 
13 
14 
15 
16 
17 PalettedBlockArea PalettedBlockArea::createFilled(Vector3i aSize, const AString & aBlockTypeName, const BlockState & aBlockState)
18 {
19  ASSERT(aSize.x > 0);
20  ASSERT(aSize.y > 0);
21  ASSERT(aSize.z > 0);
22 
24  auto numBlocks = static_cast<UInt64>(aSize.x) * static_cast<UInt64>(aSize.y) * static_cast<UInt64>(aSize.z);
25  if (numBlocks >= std::numeric_limits<UInt32>::max())
26  {
27  // We use 32-bit indices in some functions (for ARM speed), so we need the entire area to fit into UInt32
28  throw std::runtime_error("Size is too large");
29  }
30  res.mSize = aSize;
31  res.mBlocks.resize(static_cast<size_t>(numBlocks));
32  res.fill(aBlockTypeName, aBlockState);
33  return res;
34 }
35 
36 
37 
38 
39 
41 {
42  return cCuboid(Vector3i(), mSize);
43 }
44 
45 
46 
47 
48 
49 void PalettedBlockArea::setBlock(Vector3i aPos, const AString & aBlockTypeName, const BlockState & aBlockState)
50 {
51  setBlock(aPos, paletteIndex(aBlockTypeName, aBlockState));
52 }
53 
54 
55 
56 
57 
58 void PalettedBlockArea::setBlock(Vector3i aPos, UInt32 aPaletteIndex)
59 {
60  ASSERT(isPositionValid(aPos));
61  ASSERT(aPaletteIndex < mPalette.count());
62 
63  auto idx = positionToIndex(aPos);
64  mBlocks[idx] = aPaletteIndex;
65 }
66 
67 
68 
69 
70 
71 UInt32 PalettedBlockArea::paletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState)
72 {
73  return mPalette.index(aBlockTypeName, aBlockState);
74 }
75 
76 
77 
78 
79 
80 std::pair<UInt32, bool> PalettedBlockArea::maybePaletteIndex(const AString & aBlockTypeName, const BlockState & aBlockState) const
81 {
82  return mPalette.maybeIndex(aBlockTypeName, aBlockState);
83 }
84 
85 
86 
87 
88 
90 {
91  auto idx = positionToIndex(aPos);
92  return mBlocks[idx];
93 }
94 
95 
96 
97 
98 
99 const std::pair<AString, BlockState> & PalettedBlockArea::block(Vector3i aPos) const
100 {
101  return paletteEntry(blockPaletteIndex(aPos));
102 }
103 
104 
105 
106 
107 
108 const std::pair<AString, BlockState> & PalettedBlockArea::paletteEntry(UInt32 aPaletteIndex) const
109 {
110  return mPalette.entry(aPaletteIndex);
111 }
112 
113 
114 
115 
116 
118 {
119  return (
120  (aPos.x >= 0) && (aPos.y >= 0) && (aPos.z >= 0) && // Non-negative coords
121  (aPos.x < mSize.x) && (aPos.y < mSize.y) && (aPos.z < mSize.z) // Fit into size
122  );
123 }
124 
125 
126 
127 
128 
129 void PalettedBlockArea::fill(const AString & aBlockTypeName, const BlockState & aBlockState)
130 {
131  BlockTypePalette btp;
132  auto idx = btp.index(aBlockTypeName, aBlockState);
133  std::swap(mPalette, btp);
134  std::fill(mBlocks.begin(), mBlocks.end(), idx);
135 }
136 
137 
138 
139 
140 
141 void PalettedBlockArea::paste(const PalettedBlockArea & aSrc, const cCuboid & aSrcCuboid, Vector3i aDstOrigin)
142 {
143  // Clamp the src cuboid, first by src itself, then by this PBA's coord range:
144  cCuboid srcCuboid(aSrcCuboid);
145  srcCuboid.Sort();
146  srcCuboid.Clamp(aSrc.whole());
147  Vector3i maxSize = mSize - aDstOrigin;
148  srcCuboid.ClampSize(maxSize);
149  Vector3i dstOrigin(aDstOrigin);
150 
151  // If any aDstOrigin coord is lower than 0, adjust the coord and src cuboid size:
152  if (dstOrigin.x < 0)
153  {
154  srcCuboid.p1.x -= dstOrigin.x;
155  if (srcCuboid.p1.x >= srcCuboid.p2.x)
156  {
157  return;
158  }
159  dstOrigin.x = 0;
160  }
161  if (dstOrigin.y < 0)
162  {
163  srcCuboid.p1.y -= dstOrigin.y;
164  if (srcCuboid.p1.y >= srcCuboid.p2.y)
165  {
166  return;
167  }
168  dstOrigin.y = 0;
169  }
170  if (dstOrigin.z < 0)
171  {
172  srcCuboid.p1.z -= dstOrigin.z;
173  if (srcCuboid.p1.z >= srcCuboid.p2.z)
174  {
175  return;
176  }
177  dstOrigin.z = 0;
178  }
179 
180  // Create a transform map from aSrc's palette to our palette:
181  auto paletteTransform = mPalette.createTransformMapAddMissing(aSrc.mPalette);
182 
183  // Copy the data:
184  UInt32 srcStrideY = static_cast<UInt32>(aSrc.size().x * aSrc.size().z);
185  UInt32 srcStrideZ = static_cast<UInt32>(aSrc.size().x);
186  UInt32 dstStrideY = static_cast<UInt32>(mSize.x * mSize.z);
187  UInt32 dstStrideZ = static_cast<UInt32>(mSize.x);
188  UInt32 minX = static_cast<UInt32>(srcCuboid.p1.x);
189  UInt32 maxX = static_cast<UInt32>(srcCuboid.p2.x);
190  UInt32 minY = static_cast<UInt32>(srcCuboid.p1.y);
191  UInt32 maxY = static_cast<UInt32>(srcCuboid.p2.y);
192  UInt32 minZ = static_cast<UInt32>(srcCuboid.p1.z);
193  UInt32 maxZ = static_cast<UInt32>(srcCuboid.p2.z);
194  UInt32 dstX = static_cast<UInt32>(dstOrigin.x);
195  UInt32 dstY = static_cast<UInt32>(dstOrigin.y);
196  UInt32 dstZ = static_cast<UInt32>(dstOrigin.z);
197  for (UInt32 y = minY; y < maxY; ++y)
198  {
199  UInt32 srcOfsY = y * srcStrideY;
200  UInt32 dstOfsY = (y - minY + dstY) * dstStrideY;
201  for (UInt32 z = minZ; z < maxZ; ++z)
202  {
203  UInt32 srcOfs = srcOfsY + z * srcStrideZ + minX;
204  UInt32 dstOfs = dstOfsY + (z - minZ + dstZ) * dstStrideZ + dstX;
205  for (UInt32 x = minX; x < maxX; ++x)
206  {
207  mBlocks[dstOfs] = paletteTransform[aSrc.mBlocks[srcOfs]];
208  srcOfs += 1;
209  dstOfs += 1;
210  }
211  }
212  }
213 }
214 
215 
216 
217 
218 
219 void PalettedBlockArea::crop(const cCuboid & aArea)
220 {
221  cCuboid area(aArea);
222  area.Clamp(whole());
223 
224  // Copy the data:
225  UInt32 srcStrideY = static_cast<UInt32>(size().x * size().z);
226  UInt32 srcStrideZ = static_cast<UInt32>(size().x);
227  UInt32 dstStrideY = static_cast<UInt32>(area.DifX() * area.DifZ());
228  UInt32 dstStrideZ = static_cast<UInt32>(area.DifZ());
229  UInt32 minX = static_cast<UInt32>(area.p1.x);
230  UInt32 maxX = static_cast<UInt32>(area.p2.x);
231  UInt32 minY = static_cast<UInt32>(area.p1.y);
232  UInt32 maxY = static_cast<UInt32>(area.p2.y);
233  UInt32 minZ = static_cast<UInt32>(area.p1.z);
234  UInt32 maxZ = static_cast<UInt32>(area.p2.z);
235  for (UInt32 y = minY; y < maxY; ++y)
236  {
237  UInt32 srcOfsY = (y - minY) * srcStrideY;
238  UInt32 dstOfsY = y * dstStrideY;
239  for (UInt32 z = minZ; z < maxZ; ++z)
240  {
241  UInt32 srcOfs = srcOfsY + (z - minZ) * srcStrideZ + minX;
242  UInt32 dstOfs = dstOfsY + z * dstStrideZ;
243  for (UInt32 x = minX; x < maxX; ++x)
244  {
245  mBlocks[dstOfs] = mBlocks[srcOfs];
246  srcOfs += 1;
247  dstOfs += 1;
248  }
249  }
250  }
251 }
252 
253 
254 
255 
256 
258 {
259  ASSERT(isPositionValid(aPos));
260  return static_cast<UInt32>(aPos.x + aPos.z * mSize.x + aPos.y * mSize.x * mSize.z);
261 }
unsigned int UInt32
Definition: Globals.h:157
unsigned long long UInt64
Definition: Globals.h:156
#define ASSERT(x)
Definition: Globals.h:276
std::string AString
Definition: StringUtils.h:11
Vector3< int > Vector3i
Definition: Vector3.h:487
Represents the state of a single block (previously known as "block meta").
Definition: BlockState.h:20
Holds a palette that maps between block type + state and numbers.
std::map< UInt32, UInt32 > createTransformMapAddMissing(const BlockTypePalette &aFrom)
Returns an index-transform map from aFrom to this (this.entry(idx) == aFrom.entry(res[idx])).
std::pair< UInt32, bool > maybeIndex(const AString &aBlockTypeName, const BlockState &aBlockState) const
Returns the <index, true> of the specified block type name and state, if it exists.
UInt32 count() const
Returns the total number of entries in the palette.
UInt32 index(const AString &aBlockTypeName, const BlockState &aBlockState)
Returns the index of the specified block type name and state.
const std::pair< AString, BlockState > & entry(UInt32 aIndex) const
Returns the blockspec represented by the specified palette index.
Definition: Cuboid.h:10
void ClampSize(Vector3i a_MaxSize)
Clamps this cuboid's p2 so that the cuboid's size doesn't exceed the specified max size.
Definition: Cuboid.cpp:141
Vector3i p2
Definition: Cuboid.h:13
int DifX(void) const
Definition: Cuboid.h:33
void Clamp(const cCuboid &a_Limits)
Clamps this cuboid, so that it doesn't reach outside of a_Limits in any direction.
Definition: Cuboid.cpp:124
int DifZ(void) const
Definition: Cuboid.h:35
void Sort(void)
Definition: Cuboid.cpp:23
Vector3i p1
Definition: Cuboid.h:13
Represents an area of blocks that are represented using a palette.
void setBlock(Vector3i aPos, const AString &aBlockTypeName, const BlockState &aBlockState)
Sets a single block using its full blockspec.
std::pair< UInt32, bool > maybePaletteIndex(const AString &aBlockTypeName, const BlockState &aBlockState) const
Returns the <index, true> into the palette that is used by the specified full blockspec.
const std::pair< AString, BlockState > & block(Vector3i aPos) const
Returns the full blockspec of the block at the specified position.
void crop(const cCuboid &aArea)
Crops this PBA by the specified coords.
Vector3i mSize
The size (dimensions) of the area.
std::vector< UInt32 > mBlocks
The blocks contained in the area, stored as indices into mPalette.
cCuboid whole() const
Returns a cCuboid that encompasses the entire PBA.
void fill(const AString &aBlockTypeName, const BlockState &aBlockState)
Fills the entire PBA with a single block of the specified type.
BlockTypePalette mPalette
The palette used in the area.
PalettedBlockArea()
Creates a new uninitialized instance (all sizes zero).
const Vector3i & size() const
Returns the actual size of the area in all 3 axes.
UInt32 paletteIndex(const AString &aBlockTypeName, const BlockState &aBlockState)
Returns the index into the palette that is used by the specified full blockspec.
UInt32 blockPaletteIndex(Vector3i aPos) const
Returns the index into the palette for the block at the specified pos.
bool isPositionValid(Vector3i aPos) const
Returns true if the specified position is within the size bounds of the area.
void paste(const PalettedBlockArea &aSrc, const cCuboid &aSrcCuboid, Vector3i aDstOrigin=Vector3i())
Pastes (copies verbatim) a cCuboid out of the src PBA into this PBA.
UInt32 positionToIndex(Vector3i aPos) const
Converts the position to index in mBlocks.
const std::pair< AString, BlockState > & paletteEntry(UInt32 aPaletteIndex) const
Returns the blockspec represented by the specified palette index.
static PalettedBlockArea createFilled(Vector3i aSize, const AString &aBlockTypeName, const BlockState &aBlockState)
Creates a new PBA of the specified size filled with the specified block.
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17