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