Cuberite
A lightweight, fast and extensible game server for Minecraft
ManualBindings_BlockArea.cpp
Go to the documentation of this file.
1 // ManualBindings_BlockArea.cpp
2 
3 // Implements the manual bindings for functions in the cBlockArea class
4 
5 #include "Globals.h"
6 #include "tolua++/include/tolua++.h"
7 #include "../BlockArea.h"
8 #include "../World.h"
9 #include "ManualBindings.h"
10 #include "LuaState.h"
11 #include "PluginLua.h"
12 #include "../WorldStorage/SchematicFileSerializer.h"
13 
14 
15 
16 
17 
26 static int readCuboidOverloadParams(cLuaState & a_LuaState, int a_StartParam, cCuboid & a_Cuboid)
27 {
28  if (a_LuaState.IsParamNumber(a_StartParam))
29  {
30  // Assume the 6-number version:
31  if (!a_LuaState.GetStackValues(a_StartParam, a_Cuboid.p1.x, a_Cuboid.p2.x, a_Cuboid.p1.y, a_Cuboid.p2.y, a_Cuboid.p1.z, a_Cuboid.p2.z))
32  {
33  return a_LuaState.ApiParamError("Cannot read the bounds parameters, expected 6 numbers.");
34  }
35  return a_StartParam + 6;
36  }
37  else if (a_LuaState.IsParamUserType(a_StartParam, "cCuboid"))
38  {
39  // Assume the cCuboid version:
40  cCuboid * c;
41  if (!a_LuaState.GetStackValues(a_StartParam, c))
42  {
43  return a_LuaState.ApiParamError("Cannot read the bounds parameter, expected a cCuboid instance.");
44  }
45  a_Cuboid = *c;
46  return a_StartParam + 1;
47  }
48  else
49  {
50  // Assume the 2-Vector3i version:
51  Vector3i * p1;
52  Vector3i * p2;
53  if (!a_LuaState.GetStackValues(a_StartParam, p1, p2))
54  {
55  return a_LuaState.ApiParamError("Cannot read the bounds parameter, expected two Vector3i instances.");
56  }
57  a_Cuboid.p1 = *p1;
58  a_Cuboid.p2 = *p2;
59  return a_StartParam + 2;
60  }
61 }
62 
63 
64 
65 
66 
74 static int readVector3iOverloadParams(cLuaState & a_LuaState, int a_StartParam, Vector3i & a_Coords, const char * a_ParamName)
75 {
76  if (a_LuaState.IsParamNumber(a_StartParam))
77  {
78  // Assume the 3-number version:
79  if (!a_LuaState.GetStackValues(a_StartParam, a_Coords.x, a_Coords.y, a_Coords.z))
80  {
81  return a_LuaState.ApiParamError("Cannot read the %s, expected 3 numbers.", a_ParamName);
82  }
83  return a_StartParam + 3;
84  }
85  else
86  {
87  // Assume the Vector3i version:
88  Vector3i * c;
89  if (!a_LuaState.GetStackValues(a_StartParam, c))
90  {
91  return a_LuaState.ApiParamError("Cannot read the %s, expected a Vector3i instance.", a_ParamName);
92  }
93  a_Coords = *c;
94  return a_StartParam + 1;
95  }
96 }
97 
98 
99 
100 
101 
103 static int tolua_cBlockArea_Create(lua_State * a_LuaState)
104 {
105  cLuaState L(a_LuaState);
106  if (!L.CheckParamSelf("cBlockArea"))
107  {
108  return 0;
109  }
110  cBlockArea * self = nullptr;
111  if (!L.GetStackValues(1, self))
112  {
113  return L.ApiParamError("Cannot read self.");
114  }
115  if (self == nullptr)
116  {
117  return L.ApiParamError("Invalid 'self', must not be nil.");
118  }
119 
121  Vector3i size;
122  auto dataTypesIdx = readVector3iOverloadParams(L, 2, size, "size");
123  L.GetStackValue(dataTypesIdx, dataTypes);
125  {
126  return L.ApiParamError("Invalid combination of baDataTypes specified (%d).", dataTypes);
127  }
128 
129  // Create the area:
130  if ((size.x <= 0) || (size.y <= 0) || (size.z <= 0))
131  {
132  return L.FApiParamError("Invalid sizes, must be greater than zero, got {0}", size);
133  }
134  ASSERT(self != nullptr);
135  self->Create(size, dataTypes);
136  return 0;
137 }
138 
139 
140 
141 
142 
144 static int tolua_cBlockArea_FillRelCuboid(lua_State * a_LuaState)
145 {
146  // Check the common params:
147  cLuaState L(a_LuaState);
148  if (!L.CheckParamSelf("cBlockArea"))
149  {
150  return 0;
151  }
152 
153  // Get the common params:
154  cBlockArea * self = nullptr;
155  if (!L.GetStackValues(1, self))
156  {
157  return L.ApiParamError("Cannot read self.");
158  }
159  if (self == nullptr)
160  {
161  return L.ApiParamError("Invalid 'self', must not be nil.");
162  }
163 
164  // Check and get the overloaded params:
165  cCuboid bounds;
166  auto nextIdx = readCuboidOverloadParams(L, 2, bounds);
168  BLOCKTYPE blockType;
169  NIBBLETYPE blockMeta = 0, blockLight = 0, blockSkyLight = 0x0f;
170  if (!L.GetStackValues(nextIdx, dataTypes, blockType))
171  {
172  return L.ApiParamError("Cannot read the datatypes or block type params");
173  }
174  L.GetStackValues(nextIdx + 2, blockMeta, blockLight, blockSkyLight); // These values are optional
176  {
177  return L.ApiParamError("Invalid baDataTypes combination (%d).", dataTypes);
178  }
179 
180  // Check the coords, shift if needed:
181  bounds.Sort();
182  bounds.ClampX(0, self->GetSizeX());
183  bounds.ClampY(0, self->GetSizeY());
184  bounds.ClampZ(0, self->GetSizeZ());
185 
186  // Do the actual Fill:
187  self->FillRelCuboid(bounds, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
188  return 0;
189 }
190 
191 
192 
193 
194 
195 static int tolua_cBlockArea_GetBlockTypeMeta(lua_State * a_LuaState)
196 {
197  // function cBlockArea::GetBlockTypeMeta()
198 
199  cLuaState L(a_LuaState);
200  if (!L.CheckParamSelf("cBlockArea"))
201  {
202  return 0;
203  }
204 
205  cBlockArea * self;
206  if (!L.GetStackValues(1, self))
207  {
208  return L.ApiParamError("Cannot read 'self'");
209  }
210  if (self == nullptr)
211  {
212  return L.ApiParamError("Invalid 'self', must not be nil.");
213  }
214 
215  Vector3i coords;
216  readVector3iOverloadParams(L, 2, coords, "coords");
217  if (!self->IsValidCoords(coords))
218  {
219  return L.FApiParamError("Coords ({0}) out of range ({1} - {2}).",
220  coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1}
221  );
222  }
223  BLOCKTYPE blockType;
224  NIBBLETYPE blockMeta;
225  self->GetBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta);
226  L.Push(blockType, blockMeta);
227  return 2;
228 }
229 
230 
231 
232 
233 
234 static int tolua_cBlockArea_GetCoordRange(lua_State * a_LuaState)
235 {
236  // function cBlockArea::GetCoordRange()
237  // Returns all three sizes of the area, each minus one, so that they represent the maximum coord value
238  // Exported manually because there's no direct C++ equivalent,
239  // plus tolua would generate extra input params for the outputs
240 
241  cLuaState L(a_LuaState);
242  if (!L.CheckParamSelf("cBlockArea"))
243  {
244  return 0;
245  }
246 
247  cBlockArea * self;
248  if (!L.GetStackValues(1, self))
249  {
250  return L.ApiParamError("Cannot read the 'self' parameter.");
251  }
252  if (self == nullptr)
253  {
254  return L.ApiParamError("Invalid 'self', must not be nil.");
255  }
256 
257  L.Push(self->GetSizeX() - 1, self->GetSizeY() - 1, self->GetSizeZ() - 1);
258  return 3;
259 }
260 
261 
262 
263 
264 
265 static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * a_LuaState)
266 {
267  // function cBlockArea::GetNonAirCropRelCoords()
268  // Exported manually because tolua would generate extra input params for the outputs
269 
270  cLuaState L(a_LuaState);
271  if (!L.CheckParamSelf("cBlockArea"))
272  {
273  return 0;
274  }
275 
276  cBlockArea * self = nullptr;
277  BLOCKTYPE ignoreBlockType = E_BLOCK_AIR;
278  if (!L.GetStackValues(1, self, ignoreBlockType))
279  {
280  return L.ApiParamError("Cannot read params");
281  }
282  if (self == nullptr)
283  {
284  return L.ApiParamError("Invalid 'self', must not be nil");
285  }
286  if (!self->HasBlockTypes())
287  {
288  return L.ApiParamError("The area doesn't contain baTypes datatype");
289  }
290 
291  // Calculate the crop coords:
292  int minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ;
293  self->GetNonAirCropRelCoords(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ, ignoreBlockType);
294 
295  // Push the six crop coords:
296  L.Push(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ);
297  return 6;
298 }
299 
300 
301 
302 
303 
304 static int tolua_cBlockArea_GetOrigin(lua_State * a_LuaState)
305 {
306  // function cBlockArea::GetOrigin()
307  // Returns all three coords of the origin point
308  // Exported manually because there's no direct C++ equivalent,
309  // plus tolua would generate extra input params for the outputs
310 
311  cLuaState L(a_LuaState);
312  if (!L.CheckParamSelf("cBlockArea"))
313  {
314  return 0;
315  }
316 
317  cBlockArea * self;
318  if (!L.GetStackValues(1, self))
319  {
320  return L.ApiParamError("Cannot read the 'self' parameter.");
321  }
322  if (self == nullptr)
323  {
324  return L.ApiParamError("Invalid 'self', must not be nil.");
325  }
326 
327  // Push the three origin coords:
328  L.Push(self->GetOriginX(), self->GetOriginY(), self->GetOriginZ());
329  return 3;
330 }
331 
332 
333 
334 
335 
336 static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * a_LuaState)
337 {
338  // function cBlockArea::GetRelBlockTypeMeta()
339  // Exported manually because tolua generates extra input params for the outputs
340 
341  cLuaState L(a_LuaState);
342  if (!L.CheckParamSelf("cBlockArea"))
343  {
344  return 0;
345  }
346 
347  cBlockArea * self;
348  if (!L.GetStackValues(1, self))
349  {
350  return L.ApiParamError("Cannot read the 'self' parameter.");
351  }
352  if (self == nullptr)
353  {
354  return L.ApiParamError("Invalid 'self', must not be nil.");
355  }
356  if (!self->HasBlockTypes())
357  {
358  return L.ApiParamError("The area doesn't contain baTypes datatype");
359  }
360  if (!self->HasBlockMetas())
361  {
362  return L.ApiParamError("The area doesn't contain baMetas datatype");
363  }
364 
365  Vector3i coords;
366  readVector3iOverloadParams(L, 2, coords, "coords");
367  if (!self->IsValidRelCoords(coords))
368  {
369  return L.FApiParamError("The coords ({0}) are out of range (max {1}).",
370  coords, self->GetSize() - Vector3i{1, 1, 1}
371  );
372  }
373  BLOCKTYPE blockType;
374  NIBBLETYPE blockMeta;
375  self->GetRelBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta);
376  L.Push(blockType, blockMeta);
377  return 2;
378 }
379 
380 
381 
382 
383 
384 static int tolua_cBlockArea_GetSize(lua_State * a_LuaState)
385 {
386  // function cBlockArea::GetSize()
387  // Returns all three sizes of the area
388  // Exported manually because there's no direct C++ equivalent,
389  // plus tolua would generate extra input params for the outputs
390 
391  cLuaState L(a_LuaState);
392  if (!L.CheckParamSelf("cBlockArea"))
393  {
394  return 0;
395  }
396 
397  cBlockArea * self;
398  if (!L.GetStackValues(1, self))
399  {
400  return L.ApiParamError("Cannot read the 'self' parameter.");
401  }
402  if (self == nullptr)
403  {
404  return L.ApiParamError("Invalid 'self', must not be nil.");
405  }
406 
407  L.Push(self->GetSizeX(), self->GetSizeY(), self->GetSizeZ());
408  return 3;
409 }
410 
411 
412 
413 
414 
415 static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * a_LuaState)
416 {
417  // function cBlockArea::LoadFromSchematicFile
418  // Exported manually because function has been moved to SchematicFileSerializer.cpp
419  cLuaState L(a_LuaState);
420  if (
421  !L.CheckParamSelf("cBlockArea") ||
422  !L.CheckParamString(2) ||
423  !L.CheckParamEnd(3)
424  )
425  {
426  return 0;
427  }
428  cBlockArea * self;
429  AString fileName;
430  if (!L.GetStackValues(1, self, fileName))
431  {
432  return L.ApiParamError("Cannot read the parameters.");
433  }
434  if (self == nullptr)
435  {
436  return L.ApiParamError("Invalid 'self', must not be nil.");
437  }
438 
440  return 1;
441 }
442 
443 
444 
445 
446 
447 static int tolua_cBlockArea_LoadFromSchematicString(lua_State * a_LuaState)
448 {
449  // function cBlockArea::LoadFromSchematicString
450  // Exported manually because function has been moved to SchematicFileSerializer.cpp
451  cLuaState L(a_LuaState);
452  if (
453  !L.CheckParamSelf("cBlockArea") ||
454  !L.CheckParamString(2) ||
455  !L.CheckParamEnd(3)
456  )
457  {
458  return 0;
459  }
460  cBlockArea * self;
461  AString data;
462  if (!L.GetStackValues(1, self, data))
463  {
464  return L.ApiParamError("Cannot read the parameters.");
465  }
466  if (self == nullptr)
467  {
468  return L.ApiParamError("Invalid 'self', must not be nil.");
469  }
470 
472  return 1;
473 }
474 
475 
476 
477 
478 
480 static int tolua_cBlockArea_Read(lua_State * a_LuaState)
481 {
482  // Check the common params:
483  cLuaState L(a_LuaState);
484  if (
485  !L.CheckParamSelf("cBlockArea") ||
486  !L.CheckParamUserType(2, "cWorld")
487  )
488  {
489  return 0;
490  }
491 
492  // Get the common params:
493  cBlockArea * self = nullptr;
494  cWorld * world = nullptr;
495  if (!L.GetStackValues(1, self, world))
496  {
497  return L.ApiParamError("Cannot read self or world.");
498  }
499  if (world == nullptr)
500  {
501  return L.ApiParamError("Invalid world instance. The world must be not nil.");
502  }
503 
504  // Check and get the overloaded params:
505  cCuboid bounds;
507  auto dataTypesIdx = readCuboidOverloadParams(L, 3, bounds);
508  L.GetStackValues(dataTypesIdx, dataTypes);
510  {
511  return L.ApiParamError("Invalid baDataTypes combination (%d).", dataTypes);
512  }
513 
514  // Check the coords, shift if needed:
515  bounds.Sort();
516  if (bounds.p1.y < 0)
517  {
518  FLOGWARNING("cBlockArea:Read(): MinBlockY less than zero, adjusting to zero. Coords: {0} - {1}",
519  bounds.p1, bounds.p2
520  );
521  L.LogStackTrace();
522  bounds.p1.y = 0;
523  }
524  else if (bounds.p1.y >= cChunkDef::Height)
525  {
526  FLOGWARNING("cBlockArea:Read(): MinBlockY more than chunk height, adjusting to chunk height. Coords: {0} - {1}",
527  bounds.p1, bounds.p2
528  );
529  L.LogStackTrace();
530  bounds.p1.y = cChunkDef::Height - 1;
531  }
532  if (bounds.p2.y < 0)
533  {
534  FLOGWARNING("cBlockArea:Read(): MaxBlockY less than zero, adjusting to zero. Coords: {0} - {1}",
535  bounds.p1, bounds.p2
536  );
537  L.LogStackTrace();
538  bounds.p2.y = 0;
539  }
540  else if (bounds.p2.y > cChunkDef::Height)
541  {
542  FLOGWARNING("cBlockArea:Read(): MaxBlockY more than chunk height, adjusting to chunk height. Coords: {0} - {1}",
543  bounds.p1, bounds.p2
544  );
545  L.LogStackTrace();
546  bounds.p2.y = cChunkDef::Height;
547  }
548 
549  // Do the actual read:
550  L.Push(self->Read(*world, bounds, dataTypes));
551  return 1;
552 }
553 
554 
555 
556 
557 
560 static int tolua_cBlockArea_RelLine(lua_State * a_LuaState)
561 {
562  // Check the common params:
563  cLuaState L(a_LuaState);
564  if (!L.CheckParamSelf("cBlockArea"))
565  {
566  return 0;
567  }
568 
569  // Get the common params:
570  cBlockArea * self = nullptr;
571  if (!L.GetStackValues(1, self))
572  {
573  return L.ApiParamError("Cannot read self.");
574  }
575 
576  // Check and get the overloaded params:
577  Vector3i p1;
578  auto idx = readVector3iOverloadParams(L, 2, p1, "start coords");
579  Vector3i p2;
580  idx = readVector3iOverloadParams(L, idx, p2, "end coords");
582  BLOCKTYPE blockType;
583  NIBBLETYPE blockMeta, blockLight, blockSkyLight;
584  L.GetStackValues(idx, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
586  {
587  return L.ApiParamError("Invalid baDataTypes combination (%d).", dataTypes);
588  }
589  if ((self->GetDataTypes() & dataTypes) != dataTypes)
590  {
591  return L.ApiParamError("Requested datatypes not present in the cBlockArea. Got only 0x%02x, requested 0x%02x",
592  self->GetDataTypes(), dataTypes
593  );
594  }
595 
596  // Draw the line:
597  self->RelLine(p1, p2, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
598  return 0;
599 }
600 
601 
602 
603 
604 
605 static int tolua_cBlockArea_SaveToSchematicFile(lua_State * a_LuaState)
606 {
607  // function cBlockArea::SaveToSchematicFile
608  // Exported manually because function has been moved to SchematicFileSerializer.cpp
609  cLuaState L(a_LuaState);
610  if (
611  !L.CheckParamSelf("cBlockArea") ||
612  !L.CheckParamString(2) ||
613  !L.CheckParamEnd(3)
614  )
615  {
616  return 0;
617  }
618  cBlockArea * self;
619  AString fileName;
620  if (!L.GetStackValues(1, self, fileName))
621  {
622  return L.ApiParamError("Cannot read the parameters.");
623  }
624  if (self == nullptr)
625  {
626  return L.ApiParamError("Invalid 'self', must not be nil.");
627  }
628 
630  return 1;
631 }
632 
633 
634 
635 
636 
637 static int tolua_cBlockArea_SaveToSchematicString(lua_State * a_LuaState)
638 {
639  // function cBlockArea::SaveToSchematicString
640  // Exported manually because function has been moved to SchematicFileSerializer.cpp
641  cLuaState L(a_LuaState);
642  if (
643  !L.CheckParamSelf("cBlockArea") ||
644  !L.CheckParamEnd(2)
645  )
646  {
647  return 0;
648  }
649  cBlockArea * self;
650  if (!L.GetStackValues(1, self))
651  {
652  return L.ApiParamError("Cannot read the 'self' parameter.");
653  }
654  if (self == nullptr)
655  {
656  return L.ApiParamError("Invalid 'self', must not be nil.");
657  }
658 
659  AString data;
661  {
662  L.Push(data);
663  return 1;
664  }
665  return 0;
666 }
667 
668 
669 
670 
671 
673 static int tolua_cBlockArea_Write(lua_State * a_LuaState)
674 {
675  // Check the common params:
676  cLuaState L(a_LuaState);
677  if (
678  !L.CheckParamSelf("cBlockArea") ||
679  !L.CheckParamUserType(2, "cWorld")
680  )
681  {
682  return 0;
683  }
684 
685  // Get the common params:
686  cBlockArea * self = nullptr;
687  cWorld * world = nullptr;
688  if (!L.GetStackValues(1, self, world))
689  {
690  return L.ApiParamError("Cannot read self or world.");
691  }
692  if (world == nullptr)
693  {
694  return L.ApiParamError("Invalid world instance. The world must be not nil.");
695  }
696 
697  // Check and get the overloaded params:
698  Vector3i coords;
699  int dataTypes = 0;
700  auto dataTypesIdx = readVector3iOverloadParams(L, 3, coords, "coords");
701  auto HasDataTypes = L.GetStackValues(dataTypesIdx, dataTypes);
702 
703  // Check the dataType parameter validity:
704  if (HasDataTypes)
705  {
707  {
708  return L.ApiParamError("Invalid datatype combination (%d).", dataTypes);
709  }
710  if ((self->GetDataTypes() & dataTypes) != dataTypes)
711  {
712  return L.ApiParamError("Requesting datatypes not present in the cBlockArea. Got only 0x%02x, requested 0x%02x",
713  self->GetDataTypes(), dataTypes
714  );
715  }
716  }
717 
718  // Check and adjust the coord params:
719  // TODO: Should we report this as a failure? Because the result is definitely not what the plugin assumed
720  // ... Or should we silently clone-crop-write the cBlockArea so that the API call does what would be naturally expected?
721  // ... Or should we change the cBlockArea::Write() to allow out-of-range Y coords and do the cropping there?
722  // ... NOTE: We already support auto-crop in cBlockArea::Merge() itself
723  if (coords.y < 0)
724  {
725  LOGWARNING("cBlockArea:Write(): MinBlockY less than zero, adjusting to zero");
726  L.LogStackTrace();
727  coords.y = 0;
728  }
729  else if (coords.y > cChunkDef::Height - self->GetSizeY())
730  {
731  LOGWARNING("cBlockArea:Write(): MinBlockY + m_SizeY more than chunk height, adjusting to chunk height");
732  L.LogStackTrace();
733  coords.y = cChunkDef::Height - self->GetSizeY();
734  }
735 
736  // Do the actual write:
737  if (HasDataTypes)
738  {
739  L.Push(self->Write(*world, coords, dataTypes));
740  }
741  else
742  {
743  L.Push(self->Write(*world, coords));
744  }
745  return 1;
746 }
747 
748 
749 
750 
751 
757 template <
758  typename DataType,
759  int DataTypeFlag,
760  DataType (cBlockArea::*Fn)(int, int, int) const
761 >
762 static int GetBlock(lua_State * a_LuaState)
763 {
764  // Check the common params:
765  cLuaState L(a_LuaState);
766  if (!L.CheckParamSelf("cBlockArea"))
767  {
768  return 0;
769  }
770 
771  // Read the common params:
772  cBlockArea * self;
773  if (!L.GetStackValues(1, self))
774  {
775  return L.ApiParamError("Cannot read the 'self' param.");
776  }
777 
778  // Check the datatype's presence:
779  if ((self->GetDataTypes() & DataTypeFlag) == 0)
780  {
781  return L.ApiParamError("The area doesn't contain the datatype (%d).", DataTypeFlag);
782  }
783 
784  // Read the overloaded params:
785  Vector3i coords;
786  readVector3iOverloadParams(L, 2, coords, "coords");
787  if (!self->IsValidCoords(coords))
788  {
789  return L.FApiParamError("The coords ({0}) are out of range ({1} - {2}).",
790  coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1}
791  );
792  }
793 
794  // Get the block info:
795  L.Push((self->*Fn)(coords.x, coords.y, coords.z));
796  return 1;
797 }
798 
799 
800 
801 
802 
808 template <
809  typename DataType,
810  int DataTypeFlag,
811  DataType (cBlockArea::*Fn)(int, int, int) const
812 >
813 static int GetRelBlock(lua_State * a_LuaState)
814 {
815  // Check the common params:
816  cLuaState L(a_LuaState);
817  if (!L.CheckParamSelf("cBlockArea"))
818  {
819  return 0;
820  }
821 
822  // Read the common params:
823  cBlockArea * self;
824  if (!L.GetStackValues(1, self))
825  {
826  return L.ApiParamError("Cannot read the 'self' param.");
827  }
828 
829  // Check the datatype's presence:
830  if ((self->GetDataTypes() & DataTypeFlag) == 0)
831  {
832  return L.ApiParamError("The area doesn't contain the datatype (%d).", DataTypeFlag);
833  }
834 
835  // Read the overloaded params:
836  Vector3i coords;
837  readVector3iOverloadParams(L, 2, coords, "coords");
838  if (!self->IsValidRelCoords(coords))
839  {
840  return L.ApiParamError("The coords ({0}) are out of range ({1}).",
841  coords, self->GetSize()
842  );
843  }
844 
845  // Get the block info:
846  L.Push((self->*Fn)(coords.x, coords.y, coords.z));
847  return 1;
848 }
849 
850 
851 
852 
853 
859 template <
860  typename DataType,
861  int DataTypeFlag,
862  void (cBlockArea::*Fn)(int, int, int, DataType)
863 >
864 static int SetBlock(lua_State * a_LuaState)
865 {
866  // Check the common params:
867  cLuaState L(a_LuaState);
868  if (!L.CheckParamSelf("cBlockArea"))
869  {
870  return 0;
871  }
872 
873  // Read the common params:
874  cBlockArea * self;
875  if (!L.GetStackValues(1, self))
876  {
877  return L.ApiParamError("Cannot read the 'self' param.");
878  }
879 
880  // Check the datatype's presence:
881  if ((self->GetDataTypes() & DataTypeFlag) == 0)
882  {
883  return L.ApiParamError("The area doesn't contain the datatype (%d).", DataTypeFlag);
884  }
885 
886  // Read the overloaded params:
887  Vector3i coords;
888  auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
889  if (!self->IsValidCoords(coords))
890  {
891  return L.FApiParamError("The coords ({0}) are out of range ({1} - {2}).",
892  coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1}
893  );
894  }
895  DataType data;
896  L.GetStackValues(idx, data);
897 
898  // Set the block info:
899  (self->*Fn)(coords.x, coords.y, coords.z, data);
900  return 0;
901 }
902 
903 
904 
905 
906 
912 template <
913  typename DataType,
914  int DataTypeFlag,
915  void (cBlockArea::*Fn)(int, int, int, DataType)
916 >
917 static int SetRelBlock(lua_State * a_LuaState)
918 {
919  // Check the common params:
920  cLuaState L(a_LuaState);
921  if (!L.CheckParamSelf("cBlockArea"))
922  {
923  return 0;
924  }
925 
926  // Read the common params:
927  cBlockArea * self;
928  if (!L.GetStackValues(1, self))
929  {
930  return L.ApiParamError("Cannot read the 'self' param.");
931  }
932 
933  // Check the datatype's presence:
934  if ((self->GetDataTypes() & DataTypeFlag) == 0)
935  {
936  return L.ApiParamError("The area doesn't contain the datatype (%d).", DataTypeFlag);
937  }
938 
939  // Read the overloaded params:
940  Vector3i coords;
941  auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
942  if (!self->IsValidRelCoords(coords))
943  {
944  return L.FApiParamError("The coords ({0}) are out of range ({1}).",
945  coords, self->GetSize()
946  );
947  }
948  DataType data;
949  L.GetStackValues(idx, data);
950 
951  // Set the block info:
952  (self->*Fn)(coords.x, coords.y, coords.z, data);
953  return 0;
954 }
955 
956 
957 
958 
959 
960 static int tolua_cBlockArea_SetBlockTypeMeta(lua_State * a_LuaState)
961 {
962  // Check the common params:
963  cLuaState L(a_LuaState);
964  if (!L.CheckParamSelf("cBlockArea"))
965  {
966  return 0;
967  }
968 
969  // Read the common params:
970  cBlockArea * self;
971  if (!L.GetStackValues(1, self))
972  {
973  return L.ApiParamError("Cannot read the 'self' param.");
974  }
975 
976  // Check if block types and metas are present:
977  if (!self->HasBlockTypes() || !self->HasBlockMetas())
978  {
979  return L.ApiParamError("The area doesn't contain the datatypes baTypes and baMetas.");
980  }
981 
982  // Read the overloaded params:
983  Vector3i coords;
984  auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
985  if (!self->IsValidCoords(coords))
986  {
987  return L.FApiParamError("The coords ({0}) are out of range ({1} - {2}).",
988  coords, self->GetOrigin(), self->GetOrigin() + self->GetSize() - Vector3i{1, 1, 1}
989  );
990  }
991 
992  BLOCKTYPE block;
993  NIBBLETYPE meta;
994  if (!L.GetStackValues(idx, block, meta))
995  {
996  return L.ApiParamError("Bad number for block type or meta type.");
997  }
998 
999  // Set block type and meta:
1000  self->SetBlockTypeMeta(coords.x, coords.y, coords.z, block, meta);
1001  return 0;
1002 }
1003 
1004 
1005 
1006 
1007 
1008 static int tolua_cBlockArea_SetRelBlockTypeMeta(lua_State * a_LuaState)
1009 {
1010  // Check the common params:
1011  cLuaState L(a_LuaState);
1012  if (!L.CheckParamSelf("cBlockArea"))
1013  {
1014  return 0;
1015  }
1016 
1017  // Read the common params:
1018  cBlockArea * self;
1019  if (!L.GetStackValues(1, self))
1020  {
1021  return L.ApiParamError("Cannot read the 'self' param.");
1022  }
1023 
1024  // Check if block types and metas are present:
1025  if (!self->HasBlockTypes() || !self->HasBlockMetas())
1026  {
1027  return L.ApiParamError("The area doesn't contain the baTypes or baMetas datatypes (0x%02x).", self->GetDataTypes());
1028  }
1029 
1030  // Read the overloaded params:
1031  Vector3i coords;
1032  auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
1033  if (!self->IsValidRelCoords(coords))
1034  {
1035  return L.FApiParamError("The coords ({0}) are out of range ({1}).",
1036  coords, self->GetSize()
1037  );
1038  }
1039 
1040  BLOCKTYPE block;
1041  NIBBLETYPE meta;
1042  if (!L.GetStackValues(idx, block, meta))
1043  {
1044  return L.ApiParamError("Bad number for block type or meta type.");
1045  }
1046 
1047  // Set block type and meta:
1048  self->SetRelBlockTypeMeta(coords.x, coords.y, coords.z, block, meta);
1049  return 0;
1050 }
1051 
1052 
1053 
1054 
1055 
1056 void cManualBindings::BindBlockArea(lua_State * a_LuaState)
1057 {
1058  tolua_beginmodule(a_LuaState, nullptr);
1059  tolua_beginmodule(a_LuaState, "cBlockArea");
1060  tolua_function(a_LuaState, "Create", tolua_cBlockArea_Create);
1061  tolua_function(a_LuaState, "DoWithBlockEntityAt", DoWithXYZ<cBlockArea, cBlockEntity, &cBlockArea::DoWithBlockEntityAt, &cBlockArea::IsValidCoords>);
1062  tolua_function(a_LuaState, "DoWithBlockEntityRelAt", DoWithXYZ<cBlockArea, cBlockEntity, &cBlockArea::DoWithBlockEntityRelAt, &cBlockArea::IsValidRelCoords>);
1063  tolua_function(a_LuaState, "FillRelCuboid", tolua_cBlockArea_FillRelCuboid);
1064  tolua_function(a_LuaState, "ForEachBlockEntity", ForEach< cBlockArea, cBlockEntity, &cBlockArea::ForEachBlockEntity>);
1065  tolua_function(a_LuaState, "GetBlockLight", GetBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::GetRelBlockLight>);
1066  tolua_function(a_LuaState, "GetBlockMeta", GetBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::GetRelBlockMeta>);
1067  tolua_function(a_LuaState, "GetBlockSkyLight", GetBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::GetRelBlockSkyLight>);
1068  tolua_function(a_LuaState, "GetBlockType", GetBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::GetRelBlockType>);
1069  tolua_function(a_LuaState, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
1070  tolua_function(a_LuaState, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
1071  tolua_function(a_LuaState, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords);
1072  tolua_function(a_LuaState, "GetOrigin", tolua_cBlockArea_GetOrigin);
1073  tolua_function(a_LuaState, "GetRelBlockLight", GetRelBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::GetRelBlockLight>);
1074  tolua_function(a_LuaState, "GetRelBlockMeta", GetRelBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::GetRelBlockMeta>);
1075  tolua_function(a_LuaState, "GetRelBlockSkyLight", GetRelBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::GetRelBlockSkyLight>);
1076  tolua_function(a_LuaState, "GetRelBlockType", GetRelBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::GetRelBlockType>);
1077  tolua_function(a_LuaState, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
1078  tolua_function(a_LuaState, "GetSize", tolua_cBlockArea_GetSize);
1079  tolua_function(a_LuaState, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
1080  tolua_function(a_LuaState, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString);
1081  tolua_function(a_LuaState, "Read", tolua_cBlockArea_Read);
1082  tolua_function(a_LuaState, "RelLine", tolua_cBlockArea_RelLine);
1083  tolua_function(a_LuaState, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
1084  tolua_function(a_LuaState, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
1085  tolua_function(a_LuaState, "SetBlockType", SetBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::SetRelBlockType>);
1086  tolua_function(a_LuaState, "SetBlockMeta", SetBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::SetRelBlockMeta>);
1087  tolua_function(a_LuaState, "SetBlockLight", SetBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::SetRelBlockLight>);
1088  tolua_function(a_LuaState, "SetBlockSkyLight", SetBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::SetRelBlockSkyLight>);
1089  tolua_function(a_LuaState, "SetBlockTypeMeta", tolua_cBlockArea_SetBlockTypeMeta);
1090  tolua_function(a_LuaState, "SetRelBlockType", SetRelBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::SetRelBlockType>);
1091  tolua_function(a_LuaState, "SetRelBlockMeta", SetRelBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::SetRelBlockMeta>);
1092  tolua_function(a_LuaState, "SetRelBlockLight", SetRelBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::SetRelBlockLight>);
1093  tolua_function(a_LuaState, "SetRelBlockSkyLight", SetRelBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::SetRelBlockSkyLight>);
1094  tolua_function(a_LuaState, "SetRelBlockTypeMeta", tolua_cBlockArea_SetRelBlockTypeMeta);
1095  tolua_function(a_LuaState, "Write", tolua_cBlockArea_Write);
1096  tolua_endmodule(a_LuaState);
1097  tolua_endmodule(a_LuaState);
1098 }
1099 
1100 
1101 
1102 
void Sort(void)
Definition: Cuboid.cpp:23
bool CheckParamString(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are strings; also logs warning if not...
Definition: LuaState.cpp:1717
static int tolua_cBlockArea_LoadFromSchematicFile(lua_State *a_LuaState)
static int tolua_cBlockArea_SetBlockTypeMeta(lua_State *a_LuaState)
T x
Definition: Vector3.h:17
static int readCuboidOverloadParams(cLuaState &a_LuaState, int a_StartParam, cCuboid &a_Cuboid)
Reads params that together form a Cuboid.
static int tolua_cBlockArea_GetSize(lua_State *a_LuaState)
static bool SaveToSchematicString(const cBlockArea &a_BlockArea, AString &a_Out)
Saves the area into a string containing the .schematic file data.
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
int FApiParamError(const char *a_MsgFormat, const Args &...a_Args)
Formats and prints the message using python-style format specifiers, but prefixed with the current fu...
Definition: LuaState.h:841
static bool LoadFromSchematicFile(cBlockArea &a_BlockArea, const AString &a_FileName)
Loads an area from a .schematic file.
Vector3i p1
Definition: Cuboid.h:13
static int tolua_cBlockArea_SetRelBlockTypeMeta(lua_State *a_LuaState)
static int tolua_cBlockArea_Create(lua_State *a_LuaState)
Binding for the cBlockArea::Create() functions.
bool CheckParamSelf(const char *a_SelfClassName)
Returns true if the first parameter is an instance of the expected class name.
Definition: LuaState.cpp:1880
void LogStackTrace(int a_StartingDepth=0)
Logs all items in the current stack trace to the server console.
Definition: LuaState.cpp:1980
bool GetStackValue(int a_StackPos, AString &a_Value)
Definition: LuaState.cpp:1105
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
static int tolua_cBlockArea_GetBlockTypeMeta(lua_State *a_LuaState)
Encapsulates a Lua state and provides some syntactic sugar for common operations. ...
Definition: LuaState.h:57
static int tolua_cBlockArea_GetCoordRange(lua_State *a_LuaState)
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
bool CheckParamUserType(int a_StartParam, const char *a_UserType, int a_EndParam=-1)
Returns true if the specified parameters on the stack are of the specified usertype; also logs warnin...
Definition: LuaState.cpp:1582
static int SetBlock(lua_State *a_LuaState)
Templated bindings for the SetBlock___() functions.
bool CheckParamEnd(int a_Param)
Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters) ...
Definition: LuaState.cpp:1860
static int tolua_cBlockArea_RelLine(lua_State *a_LuaState)
Bindings for the cBlockArea:RelLine() functions.
static int tolua_cBlockArea_Write(lua_State *a_LuaState)
Bindings for the cBlockArea:Write() functions.
Definition: World.h:65
static bool SaveToSchematicFile(const cBlockArea &a_BlockArea, const AString &a_FileName)
Saves the area into a .schematic file.
static int tolua_cBlockArea_GetOrigin(lua_State *a_LuaState)
void ClampX(int a_MinX, int a_MaxX)
Clamps both X coords to the specified range.
Definition: Cuboid.cpp:163
static int readVector3iOverloadParams(cLuaState &a_LuaState, int a_StartParam, Vector3i &a_Coords, const char *a_ParamName)
Reads params that together form a Vector3i.
#define ASSERT(x)
Definition: Globals.h:335
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
Definition: Cuboid.h:9
static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State *a_LuaState)
void FLOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:138
static int tolua_cBlockArea_Read(lua_State *a_LuaState)
Bindings for the cBlockArea:Read() functions.
static bool LoadFromSchematicString(cBlockArea &a_BlockArea, const AString &a_SchematicData)
Loads an area from a string containing the .schematic file data.
std::string AString
Definition: StringUtils.h:13
void ClampZ(int a_MinZ, int a_MaxZ)
Clamps both Z coords to the specified range.
Definition: Cuboid.cpp:183
static int tolua_cBlockArea_SaveToSchematicFile(lua_State *a_LuaState)
bool IsParamNumber(int a_Param)
Definition: LuaState.cpp:1942
static int tolua_cBlockArea_FillRelCuboid(lua_State *a_LuaState)
Bindings for the cBlockArea:FillRelCuboid() functions.
static int GetBlock(lua_State *a_LuaState)
Templated bindings for the GetBlock___() functions.
static int tolua_cBlockArea_SaveToSchematicString(lua_State *a_LuaState)
bool IsParamUserType(int a_Param, AString a_UserType)
Definition: LuaState.cpp:1930
static int tolua_cBlockArea_LoadFromSchematicString(lua_State *a_LuaState)
void ClampY(int a_MinY, int a_MaxY)
Clamps both Y coords to the specified range.
Definition: Cuboid.cpp:173
bool GetStackValues(int a_StartStackPos, Arg1 &&a_Arg1, Args &&...args)
Retrieves a list of values from the Lua stack, starting at the specified index.
Definition: LuaState.h:759
static bool IsValidDataTypeCombination(int a_DataTypes)
Returns true if the datatype combination is valid.
Definition: BlockArea.cpp:302
void Push(Arg1 &&a_Arg1, Arg2 &&a_Arg2, Args &&...a_Args)
Pushes multiple arguments onto the Lua stack.
Definition: LuaState.h:605
Vector3i p2
Definition: Cuboid.h:13
static int SetRelBlock(lua_State *a_LuaState)
Templated bindings for the SetRelBlock___() functions.
static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State *a_LuaState)
static int GetRelBlock(lua_State *a_LuaState)
Templated bindings for the GetRelBlock___() functions.
int ApiParamError(fmt::StringRef a_Msg)
Prints the message, prefixed with the current function name, then logs the stack contents and raises ...
Definition: LuaState.cpp:2007