Cuberite
A lightweight, fast and extensible game server for Minecraft
ManualBindings_World.cpp
Go to the documentation of this file.
1 
2 // ManualBindings_World.cpp
3 
4 // Implements the manual Lua API bindings for the cWorld class
5 
6 #include "Globals.h"
7 #include "tolua++/include/tolua++.h"
8 #include "../World.h"
9 #include "../UUID.h"
10 #include "ManualBindings.h"
11 #include "LuaState.h"
12 #include "PluginLua.h"
13 #include "LuaChunkStay.h"
14 
28 
29 
30 
31 
32 
39 static bool CheckParamVectorOr3Numbers(cLuaState & L, const char * a_VectorName, int a_Index, int & a_NextIndex)
40 {
41  if (L.IsParamUserType(a_Index, a_VectorName))
42  {
43  a_NextIndex = a_Index + 1;
44  return L.CheckParamUserType(a_Index, a_VectorName);
45  }
46 
47  a_NextIndex = a_Index + 3;
48  return L.CheckParamNumber(a_Index, a_Index + 2);
49 }
50 
51 
52 
53 
54 
56 template <typename T>
57 static bool GetStackVectorOr3Numbers(cLuaState & L, int a_Index, Vector3<T> & a_Return)
58 {
59  if (L.GetStackValue(a_Index, a_Return))
60  {
61  return true;
62  }
63  return L.GetStackValues(a_Index, a_Return.x, a_Return.y, a_Return.z);
64 }
65 
66 
67 
68 
69 
71 template <class BlockEntityType, BLOCKTYPE... BlockTypes>
72 static int DoWithBlockEntityAt(lua_State * tolua_S)
73 {
74  cLuaState L(tolua_S);
75  int OffsetIndex;
76 
77  // Check params:
78  if (
79  !L.CheckParamSelf("cWorld") ||
80  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
81  !L.CheckParamFunction(OffsetIndex) ||
82  !L.CheckParamEnd(OffsetIndex + 1)
83  )
84  {
85  return 0;
86  }
87 
88  cWorld * Self = nullptr;
89  Vector3i Position;
90  cLuaState::cRef FnRef;
91 
92  // Get parameters:
93  if (
94  !L.GetStackValues(1, Self) ||
95  !GetStackVectorOr3Numbers(L, 2, Position) ||
96  !L.GetStackValues(OffsetIndex, FnRef)
97  )
98  {
99  return 0;
100  }
101 
102  if (Self == nullptr)
103  {
104  return L.ApiParamError("Invalid 'self'");
105  }
106  if (!FnRef.IsValid())
107  {
108  return L.ApiParamError(fmt::format(FMT_STRING("Expected a valid callback function for parameter {}"), OffsetIndex));
109  }
110 
111  // Call the DoWith function:
112  bool res = Self->DoWithBlockEntityAt(Position, [&L, &FnRef](cBlockEntity & a_BlockEntity)
113  {
114  if constexpr (sizeof...(BlockTypes) != 0)
115  {
116  if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...))
117  {
118  return false;
119  }
120  }
121 
122  bool ret = false;
123  L.Call(FnRef, static_cast<BlockEntityType *>(&a_BlockEntity), cLuaState::Return, ret);
124  return ret;
125  });
126 
127  // Push the result as the return value:
128  L.Push(res);
129  return 1;
130 }
131 
132 
133 
134 
135 
136 template <
137  class Ty1,
138  class Ty2,
139  bool (Ty1::*ForEachFn)(const cBoundingBox &, cFunctionRef<bool(Ty2 &)>)
140 >
141 static int ForEachInBox(lua_State * tolua_S)
142 {
143  // Check params:
144  cLuaState L(tolua_S);
145  if (
146  !L.CheckParamUserType(1, "cWorld") ||
147  !L.CheckParamUserType(2, "cBoundingBox") ||
148  !L.CheckParamFunction(3) ||
149  !L.CheckParamEnd(4)
150  )
151  {
152  return 0;
153  }
154 
155  // Get the params:
156  Ty1 * Self = nullptr;
157  cBoundingBox * Box = nullptr;
158  cLuaState::cRef FnRef;
159  L.GetStackValues(1, Self, Box, FnRef);
160  if ((Self == nullptr) || (Box == nullptr))
161  {
162  return L.ApiParamError(fmt::format(FMT_STRING("Invalid world ({}) or boundingbox ({})"), fmt::ptr(Self), fmt::ptr(Box)));
163  }
164  if (!FnRef.IsValid())
165  {
166  return L.ApiParamError("Expected a valid callback function for parameter #2");
167  }
168 
169  bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item)
170  {
171  bool ret = false;
172  if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret))
173  {
174  LOGWARNING("Failed to call Lua callback");
175  L.LogStackTrace();
176  return true; // Abort enumeration
177  }
178 
179  return ret;
180  }
181  );
182 
183  // Push the result as the return value:
184  L.Push(res);
185  return 1;
186 }
187 
188 
189 
190 
191 
192 template <class BlockEntityType, BLOCKTYPE... BlockTypes>
193 static int ForEachBlockEntityInChunk(lua_State * tolua_S)
194 {
195  // Check params:
196  cLuaState L(tolua_S);
197  if (
198  !L.CheckParamSelf("cWorld") ||
199  !L.CheckParamNumber(2, 3) ||
200  !L.CheckParamFunction(4) ||
201  !L.CheckParamEnd(5)
202  )
203  {
204  return 0;
205  }
206 
207  // Get parameters:
208  cWorld * Self = nullptr;
209  int ChunkX = 0;
210  int ChunkZ = 0;
211  cLuaState::cRef FnRef;
212  L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
213  if (Self == nullptr)
214  {
215  return L.ApiParamError("Error in function call '#funcname#': Invalid 'self'");
216  }
217  if (!FnRef.IsValid())
218  {
219  return L.ApiParamError("Expected a valid callback function for parameter #4");
220  }
221 
222  // Call the ForEach function:
223  bool res = Self->ForEachBlockEntityInChunk(ChunkX, ChunkZ, [&L, &FnRef](cBlockEntity & a_BlockEntity)
224  {
225  if constexpr (sizeof...(BlockTypes) != 0)
226  {
227  if (((a_BlockEntity.GetBlockType() != BlockTypes) && ...))
228  {
229  return false;
230  }
231  }
232 
233  bool ret = false;
234  L.Call(FnRef, static_cast<BlockEntityType *>(&a_BlockEntity), cLuaState::Return, ret);
235  return ret;
236  });
237 
238  // Push the result as the return value:
239  L.Push(res);
240  return 1;
241 }
242 
243 
244 
245 
246 
247 static int tolua_cWorld_BroadcastBlockAction(lua_State * tolua_S)
248 {
249  /* Function signature:
250  void BroadcastBlockAction(number a_BlockX, number a_BlockY, number a_BlockZ, number a_number1, number a_number2, number a_BlockType, cClientHandle a_Exclude)
251  --or--
252  void BroadcastBlockAction(Vector3<int> a_BlockPos, number a_Byte1, number a_Byte2, number a_BlockType, cClientHandle a_Exclude)
253  */
254 
255  cLuaState L(tolua_S);
256  int Byte1Index;
257  if (
258  !L.CheckParamSelf("cWorld") ||
259  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, Byte1Index) ||
260  !L.CheckParamNumber(Byte1Index, Byte1Index + 2)
261  )
262  {
263  return 0;
264  }
265 
266  if (Byte1Index != 3) // Not the vector overload
267  {
268  L.LogStackTrace();
269  LOGWARN("BroadcastBlockAction with 3 position arguments is deprecated, use vector-parametered version instead.");
270  }
271 
272  // Read the params:
273  cWorld * Self;
274  Vector3i BlockPos;
275  Byte Byte1, Byte2;
277  const cClientHandle * Exclude = nullptr;
278 
279  if (
280  !L.GetStackValues(1, Self) ||
281  !GetStackVectorOr3Numbers(L, 2, BlockPos) ||
282  !L.GetStackValues(Byte1Index, Byte1, Byte2, BlockType)
283  )
284  {
285  return 0;
286  }
287 
288  // Optional param
289  L.GetStackValue(Byte1Index + 3, Exclude);
290 
291  Self->BroadcastBlockAction(BlockPos, Byte1, Byte2, BlockType, Exclude);
292  return 0;
293 }
294 
295 
296 
297 
298 
299 static int tolua_cWorld_BroadcastSoundEffect(lua_State * tolua_S)
300 {
301  /* Function signature:
302  void BroadcastSoundEffect(string a_SoundName, number a_X, number a_Y, number a_Z, number a_Volume, number a_Pitch, [cClientHandle * a_Exclude])
303  --or--
304  void BroadcastSoundEffect(string a_SoundName, Vector3d, number a_Volume, number a_Pitch, [cClientHandle a_Exclude])
305  */
306  cLuaState L(tolua_S);
307  int VolumeIndex;
308  if (
309  !L.CheckParamSelf("cWorld") ||
310  !L.CheckParamString(2) ||
311  !CheckParamVectorOr3Numbers(L, "Vector3<double>", 3, VolumeIndex) ||
312  !L.CheckParamNumber(VolumeIndex, VolumeIndex + 1)
313  )
314  {
315  return 0;
316  }
317 
318  if (VolumeIndex != 4) // Not the vector overload
319  {
320  L.LogStackTrace();
321  LOGWARN("BroadcastSoundEffect with 3 position arguments is deprecated, use vector-parametered version instead.");
322  }
323 
324  // Read the params:
325  cWorld * Self;
326  AString SoundName;
327  Vector3d BlockPos;
328  float Volume, Pitch;
329  const cClientHandle * Exclude = nullptr;
330 
331  if (
332  !L.GetStackValues(1, Self, SoundName) ||
333  !GetStackVectorOr3Numbers(L, 3, BlockPos) ||
334  !L.GetStackValues(VolumeIndex, Volume, Pitch)
335  )
336  {
337  return 0;
338  }
339 
340  // Optional param
341  L.GetStackValue(VolumeIndex + 2, Exclude);
342 
343  Self->BroadcastSoundEffect(SoundName, BlockPos, Volume, Pitch, Exclude);
344  return 0;
345 }
346 
347 
348 
349 
350 
351 static int tolua_cWorld_BroadcastSoundParticleEffect(lua_State * tolua_S)
352 {
353  /* Function signature:
354  World:BroadcastSoundParticleEffect(EffectID a_EffectID, Vector3i a_SrcPos, number a_Data, [cClientHandle a_Exclude])
355  --or--
356  void BroadcastSoundParticleEffect(EffectID a_EffectID, number a_SrcX, number a_SrcY, number a_SrcZ, number a_Data, [cClientHandle a_Exclude])
357  */
358  cLuaState L(tolua_S);
359  int DataIndex;
360  if (
361  !L.CheckParamSelf("cWorld") ||
362  !L.CheckParamNumber(2) ||
363  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 3, DataIndex) ||
364  !L.CheckParamNumber(DataIndex)
365  )
366  {
367  return 0;
368  }
369 
370  if (DataIndex != 4) // Not the vector overload
371  {
372  L.LogStackTrace();
373  LOGWARN("BroadcastSoundParticleEffect with 3 position arguments is deprecated, use vector-parametered version instead.");
374  }
375 
376  // Read the params:
377  cWorld * World = nullptr;
378  Int32 EffectId;
379  Vector3i SrcPos;
380  int Data;
381  cClientHandle * ExcludeClient = nullptr;
382 
383  if (
384  !L.GetStackValues(1, World, EffectId) ||
385  !GetStackVectorOr3Numbers(L, 3, SrcPos) ||
386  !L.GetStackValue(DataIndex, Data)
387  )
388  {
389  return 0;
390  }
391 
392  // Optional param
393  L.GetStackValue(DataIndex + 1, ExcludeClient);
394 
395  World->BroadcastSoundParticleEffect(static_cast<EffectID>(EffectId), SrcPos, Data, ExcludeClient);
396  return 0;
397 }
398 
399 
400 
401 
402 
403 static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S)
404 {
405  /* Function signature:
406  World:BroadcastParticleEffect("Name", PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2])
407  --or--
408  World:BroadcastParticleEffect("Name", SrcPos, Offset, ParticleData, ParticleAmount, [ExcludeClient], [OptionalParam1], [OptionalParam2])
409  */
410  cLuaState L(tolua_S);
411  int OffsetIndex, ParticleDataIndex;
412  if (
413  !L.CheckParamSelf("cWorld") ||
414  !L.CheckParamString(2) ||
415  !CheckParamVectorOr3Numbers(L, "Vector3<float>", 3, OffsetIndex) ||
416  !CheckParamVectorOr3Numbers(L, "Vector3<float>", OffsetIndex, ParticleDataIndex)
417  )
418  {
419  return 0;
420  }
421 
422  if ((OffsetIndex != 4) || (ParticleDataIndex != 5)) // Not the vector overload
423  {
424  L.LogStackTrace();
425  LOGWARN("BroadcastParticleEffect with 3 position and 3 offset arguments is deprecated, use vector-parametered version instead.");
426  }
427 
428  // Read the params:
429  cWorld * World = nullptr;
430  AString Name;
431  Vector3f SrcPos, Offset;
432  float ParticleData;
433  int ParticleAmount;
434  cClientHandle * ExcludeClient = nullptr;
435 
436  if (
437  !L.GetStackValues(1, World, Name) ||
438  !GetStackVectorOr3Numbers(L, 3, SrcPos) ||
439  !GetStackVectorOr3Numbers(L, OffsetIndex, Offset) ||
440  !L.GetStackValues(ParticleDataIndex, ParticleData, ParticleAmount)
441  )
442  {
443  return 0;
444  }
445 
446  // Read up to 3 more optional params:
447  L.GetStackValue(ParticleDataIndex + 2, ExcludeClient);
448 
449  std::array<int, 2> Data;
450  bool HasData = L.GetStackValues(ParticleDataIndex + 3, Data[0], Data[1]);
451 
452  if (HasData)
453  {
454  World->BroadcastParticleEffect(Name, SrcPos, Offset, ParticleData, ParticleAmount, Data, ExcludeClient);
455  }
456  else
457  {
458  World->BroadcastParticleEffect(Name, SrcPos, Offset, ParticleData, ParticleAmount, ExcludeClient);
459  }
460  return 0;
461 }
462 
463 
464 
465 
466 
467 static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
468 {
469  /* Function signature:
470  World:ChunkStay(ChunkCoordTable, OnChunkAvailable, OnAllChunksAvailable)
471  ChunkCoordTable == { {Chunk1x, Chunk1z}, {Chunk2x, Chunk2z}, ... }
472  */
473 
474  cLuaState L(tolua_S);
475  if (
476  !L.CheckParamUserType (1, "cWorld") ||
477  !L.CheckParamTable (2) ||
478  !L.CheckParamFunctionOrNil(3, 4)
479  )
480  {
481  return 0;
482  }
483 
484  // Read the params:
485  cWorld * world;
486  cLuaState::cStackTablePtr chunkCoords;
487  cLuaState::cOptionalCallbackPtr onChunkAvailable, onAllChunksAvailable; // Callbacks may be unassigned at all - as a request to load / generate chunks
488  if (!L.GetStackValues(1, world, chunkCoords, onChunkAvailable, onAllChunksAvailable))
489  {
490  LOGWARNING("cWorld:ChunkStay(): Cannot read parameters, bailing out.");
491  L.LogStackTrace();
492  L.LogStackValues("Values on the stack");
493  return 0;
494  }
495  if (world == nullptr)
496  {
497  LOGWARNING("World:ChunkStay(): invalid world parameter");
498  L.LogStackTrace();
499  return 0;
500  }
501  ASSERT(chunkCoords != nullptr); // If the table was invalid, GetStackValues() would have failed
502 
503  // Read the chunk coords:
504  auto chunkStay = std::make_unique<cLuaChunkStay>();
505  if (!chunkStay->AddChunks(*chunkCoords))
506  {
507  return 0;
508  }
509 
510  // Activate the ChunkStay:
511  chunkStay.release()->Enable(*world->GetChunkMap(), std::move(onChunkAvailable), std::move(onAllChunksAvailable));
512  return 0;
513 }
514 
515 
516 
517 
518 
519 static int tolua_cWorld_DoExplosionAt(lua_State * tolua_S)
520 {
521  /* Function signature:
522  World:DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, [SourceData])
523  */
524 
525  cLuaState L(tolua_S);
526  if (
527  !L.CheckParamUserType (1, "cWorld") ||
528  !L.CheckParamNumber (2, 5) ||
529  !L.CheckParamBool (6) ||
530  !L.CheckParamNumber (7) ||
531  !L.CheckParamEnd (9)
532  )
533  {
534  return 0;
535  }
536 
537  // Read the params:
538  cWorld * World;
539  double ExplosionSize;
540  int BlockX, BlockY, BlockZ;
541  bool CanCauseFire;
542  int SourceTypeInt;
543  if (!L.GetStackValues(1, World, ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceTypeInt))
544  {
545  LOGWARNING("World:DoExplosionAt(): invalid parameters");
546  L.LogStackTrace();
547  return 0;
548  }
549  if ((SourceTypeInt < 0) || (SourceTypeInt >= esMax))
550  {
551  LOGWARNING("World:DoExplosionAt(): Invalid source type");
552  L.LogStackTrace();
553  return 0;
554  }
555  eExplosionSource SourceType;
556  void * SourceData;
557  switch (SourceTypeInt)
558  {
559  case esBed:
560  {
561  // esBed receives a Vector3i SourceData param:
562  Vector3i pos;
563  L.GetStackValue(8, pos);
564  SourceType = esBed;
565  SourceData = &pos;
566  break;
567  }
568 
569  case esEnderCrystal:
570  case esGhastFireball:
571  case esMonster:
572  case esPrimedTNT:
573  case esWitherBirth:
574  case esWitherSkull:
575  {
576  // These all receive a cEntity descendant SourceData param:
577  cEntity * ent = nullptr;
578  L.GetStackValue(8, ent);
579  SourceType = static_cast<eExplosionSource>(SourceTypeInt);
580  SourceData = ent;
581  break;
582  }
583 
584  case esOther:
585  case esPlugin:
586  {
587  // esOther and esPlugin ignore their SourceData params
588  SourceType = static_cast<eExplosionSource>(SourceTypeInt);
589  SourceData = nullptr;
590  break;
591  }
592 
593  default:
594  {
595  LOGWARNING("cWorld:DoExplosionAt(): invalid SourceType parameter: %d", SourceTypeInt);
596  L.LogStackTrace();
597  return 0;
598  }
599  }
600 
601  // Create the actual explosion:
602  World->DoExplosionAt(ExplosionSize, BlockX, BlockY, BlockZ, CanCauseFire, SourceType, SourceData);
603 
604  return 0;
605 }
606 
607 
608 
609 
610 
611 static int tolua_cWorld_DoWithPlayerByUUID(lua_State * tolua_S)
612 {
613  // Check params:
614  cLuaState L(tolua_S);
615  if (
616  !L.CheckParamSelf("cWorld") ||
617  !L.CheckParamUUID(2) ||
618  !L.CheckParamFunction(3) ||
619  !L.CheckParamEnd(4)
620  )
621  {
622  return 0;
623  }
624 
625  // Get parameters:
626  cWorld * Self;
627  cUUID PlayerUUID;
628  cLuaState::cRef FnRef;
629  L.GetStackValues(1, Self, PlayerUUID, FnRef);
630 
631  if (PlayerUUID.IsNil())
632  {
633  return L.ApiParamError("Expected a non-nil UUID for parameter #1");
634  }
635  if (!FnRef.IsValid())
636  {
637  return L.ApiParamError("Expected a valid callback function for parameter #2");
638  }
639 
640  // Call the function:
641  bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player)
642  {
643  bool ret = false;
644  L.Call(FnRef, &a_Player, cLuaState::Return, ret);
645  return ret;
646  }
647  );
648 
649  // Push the result as the return value:
650  L.Push(res);
651  return 1;
652 }
653 
654 
655 
656 
657 
658 static int tolua_cWorld_DoWithNearestPlayer(lua_State * tolua_S)
659 {
660  // Check params:
661  cLuaState L(tolua_S);
662  if (
663  !L.CheckParamSelf("cWorld") ||
664  !L.CheckParamUserType(2, "Vector3<double>") ||
665  !L.CheckParamNumber(3) ||
666  !L.CheckParamFunction(4) ||
667  // Params 5 and 6 are optional bools, no check for those
668  !L.CheckParamEnd(7)
669  )
670  {
671  return 0;
672  }
673 
674  // Get parameters:
675  cWorld * Self;
676  Vector3d Position;
677  double RangeLimit;
678  cLuaState::cRef FnRef;
679  bool CheckLineOfSight = true, IgnoreSpectators = true; // Defaults for the optional params
680  L.GetStackValues(1, Self, Position, RangeLimit, FnRef, CheckLineOfSight, IgnoreSpectators);
681 
682  if (!FnRef.IsValid())
683  {
684  return L.ApiParamError("Expected a valid callback function for parameter #3");
685  }
686 
687  // Call the function:
688  bool res = Self->DoWithNearestPlayer(Position, RangeLimit, [&](cPlayer & a_Player)
689  {
690  bool ret = false;
691  L.Call(FnRef, &a_Player, cLuaState::Return, ret);
692  return ret;
693  }, CheckLineOfSight, IgnoreSpectators);
694 
695  // Push the result as the return value:
696  L.Push(res);
697  return 1;
698 }
699 
700 
701 
702 
703 
704 static int tolua_cWorld_FastSetBlock(lua_State * tolua_S)
705 {
706  /* Function signature:
707  World:FastSetBlock(BlockX, BlockY, BlockZ)
708  --or--
709  World:FastSetBlock(Position)
710  */
711 
712  cLuaState L(tolua_S);
713  int OffsetIndex;
714  if (
715  !L.CheckParamSelf("cWorld") ||
716  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
717  !L.CheckParamNumber(OffsetIndex, OffsetIndex + 1) ||
718  !L.CheckParamEnd(OffsetIndex + 2)
719  )
720  {
721  return 0;
722  }
723 
724  if (OffsetIndex != 3) // Not the vector overload
725  {
726  L.LogStackTrace();
727  LOGWARN("FastSetBlock with 3 position arguments is deprecated, use vector-parametered version instead.");
728  }
729 
730  cWorld * World;
731  Vector3i Position;
732  BLOCKTYPE Type;
733  NIBBLETYPE Meta;
734 
735  // Read the params:
736  if (
737  !L.GetStackValues(1, World) ||
738  !GetStackVectorOr3Numbers(L, 2, Position) ||
739  !L.GetStackValues(OffsetIndex, Type, Meta)
740  )
741  {
742  return 0;
743  }
744 
745  if (World == nullptr)
746  {
747  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
748  }
749 
750  if (!cChunkDef::IsValidHeight(Position))
751  {
752  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
753  }
754 
755  World->FastSetBlock(Position, Type, Meta);
756  return 0;
757 }
758 
759 
760 
761 
762 
763 static int tolua_cWorld_ForEachEntityInChunk(lua_State * tolua_S)
764 {
765  // Check params:
766  cLuaState L(tolua_S);
767  if (
768  !L.CheckParamUserType(1, "cWorld") ||
769  !L.CheckParamNumber(2, 3) ||
770  !L.CheckParamFunction(4) ||
771  !L.CheckParamEnd(5)
772  )
773  {
774  return 0;
775  }
776 
777  // Get parameters:
778  cWorld * Self = nullptr;
779  int ChunkX = 0;
780  int ChunkZ = 0;
781  cLuaState::cRef FnRef;
782  L.GetStackValues(1, Self, ChunkX, ChunkZ, FnRef);
783  if (Self == nullptr)
784  {
785  return L.ApiParamError("Invalid 'self'");
786  }
787  if (!FnRef.IsValid())
788  {
789  return L.ApiParamError("Expected a valid callback function for parameter #4");
790  }
791 
792  // Call the DoWith function:
793  bool res = Self->ForEachEntityInChunk(ChunkX, ChunkZ, [&](cEntity & a_Item)
794  {
795  bool ret = false;
796  L.Call(FnRef, &a_Item, cLuaState::Return, ret);
797  return ret;
798  }
799  );
800 
801  // Push the result as the return value:
802  L.Push(res);
803  return 1;
804 }
805 
806 
807 
808 
809 
810 static int tolua_cWorld_ForEachLoadedChunk(lua_State * tolua_S)
811 {
812  // Exported manually, because tolua doesn't support converting functions to functor types.
813  // Function signature: ForEachLoadedChunk(callback) -> bool
814 
815  cLuaState L(tolua_S);
816  if (
817  !L.CheckParamUserType(1, "cWorld") ||
818  !L.CheckParamFunction(2)
819  )
820  {
821  return 0;
822  }
823 
824  cPluginLua * Plugin = cManualBindings::GetLuaPlugin(tolua_S);
825  if (Plugin == nullptr)
826  {
827  return 0;
828  }
829 
830  // Read the params:
831  cWorld * World = static_cast<cWorld *>(tolua_tousertype(tolua_S, 1, nullptr));
832  if (World == nullptr)
833  {
834  LOGWARNING("World:ForEachLoadedChunk(): invalid world parameter");
835  L.LogStackTrace();
836  return 0;
837  }
838  cLuaState::cRef FnRef;
839  L.GetStackValues(2, FnRef);
840  if (!FnRef.IsValid())
841  {
842  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #2");
843  }
844 
845  // Call the enumeration:
846  bool ret = World->ForEachLoadedChunk(
847  [&L, &FnRef](int a_ChunkX, int a_ChunkZ) -> bool
848  {
849  bool res = false; // By default continue the enumeration
850  L.Call(FnRef, a_ChunkX, a_ChunkZ, cLuaState::Return, res);
851  return res;
852  }
853  );
854 
855  // Push the return value:
856  L.Push(ret);
857  return 1;
858 }
859 
860 
861 
862 
863 
864 static int tolua_cWorld_GetBlock(lua_State * tolua_S)
865 {
866  /* Function signature:
867  World:GetBlock(BlockX, BlockY, BlockZ) -> BlockType
868  --or--
869  World:GetBlock(Position) -> BlockType
870  */
871 
872  cLuaState L(tolua_S);
873  int OffsetIndex;
874  if (
875  !L.CheckParamSelf("cWorld") ||
876  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
877  !L.CheckParamEnd(OffsetIndex)
878  )
879  {
880  return 0;
881  }
882 
883  if (OffsetIndex != 3) // Not the vector overload
884  {
885  L.LogStackTrace();
886  LOGWARN("GetBlock with 3 position arguments is deprecated, use vector-parametered version instead.");
887  }
888 
889  cWorld * World;
890  Vector3i Position;
891 
892  // Read the params:
893  if (
894  !L.GetStackValues(1, World) ||
895  !GetStackVectorOr3Numbers(L, 2, Position)
896  )
897  {
898  return 0;
899  }
900 
901  if (World == nullptr)
902  {
903  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
904  }
905 
906  if (!cChunkDef::IsValidHeight(Position))
907  {
908  L.Push(E_BLOCK_AIR);
909  return 1;
910  }
911 
912  L.Push(World->GetBlock(Position));
913  return 1;
914 }
915 
916 
917 
918 
919 
920 static int tolua_cWorld_GetBlockBlockLight(lua_State * tolua_S)
921 {
922  /* Function signature:
923  World:GetBlockBlockLight(BlockX, BlockY, BlockZ) -> BlockLight
924  --or--
925  World:GetBlockBlockLight(Position) -> BlockLight
926  */
927 
928  cLuaState L(tolua_S);
929  int OffsetIndex;
930  if (
931  !L.CheckParamSelf("cWorld") ||
932  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
933  !L.CheckParamEnd(OffsetIndex)
934  )
935  {
936  return 0;
937  }
938 
939  if (OffsetIndex != 3) // Not the vector overload
940  {
941  L.LogStackTrace();
942  LOGWARN("GetBlockBlockLight with 3 position arguments is deprecated, use vector-parametered version instead.");
943  }
944 
945  cWorld * World;
946  Vector3i Position;
947 
948  // Read the params:
949  if (
950  !L.GetStackValues(1, World) ||
951  !GetStackVectorOr3Numbers(L, 2, Position)
952  )
953  {
954  return 0;
955  }
956 
957  if (World == nullptr)
958  {
959  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
960  }
961 
962  if (!cChunkDef::IsValidHeight(Position))
963  {
964  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
965  }
966 
967  L.Push(World->GetBlockBlockLight(Position));
968  return 1;
969 }
970 
971 
972 
973 
974 
975 static int tolua_cWorld_GetBlockInfo(lua_State * tolua_S)
976 {
977  /* Exported manually, because tolua would generate useless additional parameters (a_BlockType .. a_BlockSkyLight)
978  Function signature:
979  GetBlockInfo(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight]
980  --or--
981  GetBlockInfo(Position) -> BlockValid, [BlockType, BlockMeta, BlockSkyLight, BlockBlockLight]
982  */
983 
984  // Check params:
985  cLuaState L(tolua_S);
986  int OffsetIndex;
987  if (
988  !L.CheckParamSelf("cWorld") ||
989  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
990  !L.CheckParamEnd(OffsetIndex)
991  )
992  {
993  return 0;
994  }
995 
996  if (OffsetIndex != 3) // Not the vector overload
997  {
998  L.LogStackTrace();
999  LOGWARN("GetBlockInfo with 3 position arguments is deprecated, use vector-parametered version instead.");
1000  }
1001 
1002  cWorld * World;
1003  Vector3i Position;
1004 
1005  // Read the params:
1006  if (
1007  !L.GetStackValues(1, World) ||
1008  !GetStackVectorOr3Numbers(L, 2, Position)
1009  )
1010  {
1011  return 0;
1012  }
1013 
1014  if (World == nullptr)
1015  {
1016  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1017  }
1018 
1019  if (!cChunkDef::IsValidHeight(Position))
1020  {
1021  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
1022  }
1023 
1025  NIBBLETYPE BlockMeta, BlockSkyLight, BlockBlockLight;
1026 
1027  // Call the function:
1028  bool res = World->GetBlockInfo(Position, BlockType, BlockMeta, BlockSkyLight, BlockBlockLight);
1029 
1030  // Push the returned values:
1031  L.Push(res);
1032  if (res)
1033  {
1034  L.Push(BlockType, BlockMeta, BlockSkyLight, BlockBlockLight);
1035  return 5;
1036  }
1037  return 1;
1038 }
1039 
1040 
1041 
1042 
1043 
1044 static int tolua_cWorld_GetBlockMeta(lua_State * tolua_S)
1045 {
1046  /* Function signature:
1047  World:GetBlockMeta(BlockX, BlockY, BlockZ) -> BlockMeta
1048  --or--
1049  World:GetBlockMeta(Position) -> BlockMeta
1050  */
1051 
1052  cLuaState L(tolua_S);
1053  int OffsetIndex;
1054  if (
1055  !L.CheckParamSelf("cWorld") ||
1056  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
1057  !L.CheckParamEnd(OffsetIndex)
1058  )
1059  {
1060  return 0;
1061  }
1062 
1063  if (OffsetIndex != 3) // Not the vector overload
1064  {
1065  L.LogStackTrace();
1066  LOGWARN("GetBlockMeta with 3 position arguments is deprecated, use vector-parametered version instead.");
1067  }
1068 
1069  cWorld * World;
1070  Vector3i Position;
1071 
1072  // Read the params:
1073  if (
1074  !L.GetStackValues(1, World) ||
1075  !GetStackVectorOr3Numbers(L, 2, Position)
1076  )
1077  {
1078  return 0;
1079  }
1080 
1081  if (World == nullptr)
1082  {
1083  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1084  }
1085 
1086  if (!cChunkDef::IsValidHeight(Position))
1087  {
1088  L.Push(0);
1089  return 1;
1090  }
1091 
1092  L.Push(World->GetBlockMeta(Position));
1093  return 1;
1094 }
1095 
1096 
1097 
1098 
1099 
1100 static int tolua_cWorld_GetBlockSkyLight(lua_State * tolua_S)
1101 {
1102  /* Function signature:
1103  World:GetBlockSkyLight(BlockX, BlockY, BlockZ) -> BlockLight
1104  --or--
1105  World:GetBlockSkyLight(Position) -> BlockLight
1106  */
1107 
1108  cLuaState L(tolua_S);
1109  int OffsetIndex;
1110  if (
1111  !L.CheckParamSelf("cWorld") ||
1112  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
1113  !L.CheckParamEnd(OffsetIndex)
1114  )
1115  {
1116  return 0;
1117  }
1118 
1119  if (OffsetIndex != 3) // Not the vector overload
1120  {
1121  L.LogStackTrace();
1122  LOGWARN("GetBlockSkyLight with 3 position arguments is deprecated, use vector-parametered version instead.");
1123  }
1124 
1125  cWorld * World;
1126  Vector3i Position;
1127 
1128  // Read the params:
1129  if (
1130  !L.GetStackValues(1, World) ||
1131  !GetStackVectorOr3Numbers(L, 2, Position)
1132  )
1133  {
1134  return 0;
1135  }
1136 
1137  if (World == nullptr)
1138  {
1139  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1140  }
1141 
1142  if (!cChunkDef::IsValidHeight(Position))
1143  {
1144  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
1145  }
1146 
1147  L.Push(World->GetBlockSkyLight(Position));
1148  return 1;
1149 }
1150 
1151 
1152 
1153 
1154 
1155 static int tolua_cWorld_GetBlockTypeMeta(lua_State * tolua_S)
1156 {
1157  /* Exported manually, because tolua would generate useless additional parameters (a_BlockType, a_BlockMeta)
1158  Function signature:
1159  GetBlockTypeMeta(BlockX, BlockY, BlockZ) -> BlockValid, [BlockType, BlockMeta]
1160  --or--
1161  GetBlockTypeMeta(Position) -> BlockValid, [BlockType, BlockMeta]
1162  */
1163 
1164  // Check params:
1165  cLuaState L(tolua_S);
1166  int OffsetIndex;
1167  if (
1168  !L.CheckParamSelf("cWorld") ||
1169  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
1170  !L.CheckParamEnd(OffsetIndex)
1171  )
1172  {
1173  return 0;
1174  }
1175 
1176  if (OffsetIndex != 3) // Not the vector overload
1177  {
1178  L.LogStackTrace();
1179  LOGWARN("GetBlockTypeMeta with 3 position arguments is deprecated, use vector-parametered version instead.");
1180  }
1181 
1182  cWorld * World;
1183  Vector3i Position;
1184 
1185  // Read the params:
1186  if (
1187  !L.GetStackValues(1, World) ||
1188  !GetStackVectorOr3Numbers(L, 2, Position)
1189  )
1190  {
1191  return 0;
1192  }
1193 
1194  if (World == nullptr)
1195  {
1196  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1197  }
1198 
1199  if (!cChunkDef::IsValidHeight(Position))
1200  {
1201  L.Push(E_BLOCK_AIR, 0);
1202  return 2;
1203  }
1204 
1206  NIBBLETYPE BlockMeta;
1207 
1208  // Call the function:
1209  bool res = World->GetBlockTypeMeta(Position, BlockType, BlockMeta);
1210 
1211  // Push the returned values:
1212  L.Push(res);
1213  if (res)
1214  {
1215  L.Push(BlockType, BlockMeta);
1216  return 3;
1217  }
1218  return 1;
1219 }
1220 
1221 
1222 
1223 
1224 
1225 static int tolua_cWorld_GetSignLines(lua_State * tolua_S)
1226 {
1227  // Exported manually, because tolua would generate useless additional parameters (a_Line1 .. a_Line4)
1228 
1229  // Check params:
1230  cLuaState L(tolua_S);
1231  if (
1232  !L.CheckParamUserType(1, "cWorld") ||
1233  !L.CheckParamNumber(2, 4) ||
1234  !L.CheckParamEnd(5)
1235  )
1236  {
1237  return 0;
1238  }
1239 
1240  // Get params:
1241  cWorld * Self = nullptr;
1242  int BlockX = 0;
1243  int BlockY = 0;
1244  int BlockZ = 0;
1245  L.GetStackValues(1, Self, BlockX, BlockY, BlockZ);
1246  if (Self == nullptr)
1247  {
1248  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1249  }
1250 
1251  // Call the function:
1252  AString Line1, Line2, Line3, Line4;
1253  bool res = Self->GetSignLines(BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
1254 
1255  // Push the returned values:
1256  L.Push(res);
1257  if (res)
1258  {
1259  L.Push(Line1, Line2, Line3, Line4);
1260  return 5;
1261  }
1262  return 1;
1263 }
1264 
1265 
1266 
1267 
1268 
1269 static int tolua_cWorld_GetTimeOfDay(lua_State * tolua_S)
1270 {
1271  // Check params:
1272  cLuaState L(tolua_S);
1273  if (
1274  !L.CheckParamSelf("cWorld") ||
1275  !L.CheckParamEnd(2)
1276  )
1277  {
1278  return 0;
1279  }
1280 
1281  // Get params:
1282  cWorld * Self = nullptr;
1283  L.GetStackValues(1, Self);
1284  if (Self == nullptr)
1285  {
1286  return L.ApiParamError("Invalid 'self'");
1287  }
1288 
1289  // Call the function:
1290  const auto Time = Self->GetTimeOfDay();
1291 
1292  // Push the returned value:
1293  L.Push(Time.count());
1294  return 1;
1295 }
1296 
1297 
1298 
1299 
1300 
1301 static int tolua_cWorld_GetWorldAge(lua_State * tolua_S)
1302 {
1303  // Check params:
1304  cLuaState L(tolua_S);
1305  if (
1306  !L.CheckParamSelf("cWorld") ||
1307  !L.CheckParamEnd(2)
1308  )
1309  {
1310  return 0;
1311  }
1312 
1313  // Get params:
1314  cWorld * Self = nullptr;
1315  L.GetStackValues(1, Self);
1316  if (Self == nullptr)
1317  {
1318  return L.ApiParamError("Invalid 'self'");
1319  }
1320 
1321  // Call the function:
1322  const auto Time = Self->GetWorldAge();
1323 
1324  // Push the returned value:
1325  L.Push(static_cast<lua_Number>(Time.count()));
1326  return 1;
1327 }
1328 
1329 
1330 
1331 
1332 
1333 static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
1334 {
1335  /* Function signature:
1336  World:PrepareChunk(ChunkX, ChunkZ, Callback)
1337  */
1338 
1339  // Check the param types:
1340  cLuaState L(tolua_S);
1341  if (
1342  !L.CheckParamUserType (1, "cWorld") ||
1343  !L.CheckParamNumber (2, 3) ||
1345  )
1346  {
1347  return 0;
1348  }
1349 
1350  // Wrap the Lua callback inside a C++ callback class:
1351  class cCallback:
1352  public cChunkCoordCallback
1353  {
1354  public:
1355  // cChunkCoordCallback override:
1356  virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess) override
1357  {
1358  m_LuaCallback.Call(a_Coords.m_ChunkX, a_Coords.m_ChunkZ, a_IsSuccess);
1359  }
1360 
1361  cLuaState::cOptionalCallback m_LuaCallback;
1362  };
1363 
1364  // Read the params:
1365  cWorld * world = nullptr;
1366  int chunkX = 0;
1367  int chunkZ = 0;
1368  auto Callback = std::make_unique<cCallback>();
1369  L.GetStackValues(1, world, chunkX, chunkZ, Callback->m_LuaCallback);
1370  if (world == nullptr)
1371  {
1372  LOGWARNING("World:PrepareChunk(): invalid world parameter");
1373  L.LogStackTrace();
1374  return 0;
1375  }
1376 
1377  // Call the chunk preparation:
1378  world->PrepareChunk(chunkX, chunkZ, std::move(Callback));
1379  return 0;
1380 }
1381 
1382 
1383 
1384 
1385 
1386 static int tolua_cWorld_QueueTask(lua_State * tolua_S)
1387 {
1388  // Function signature:
1389  // World:QueueTask(Callback)
1390 
1391  // Retrieve the args:
1392  cLuaState L(tolua_S);
1393  if (
1394  !L.CheckParamUserType(1, "cWorld") ||
1395  !L.CheckParamFunction(2)
1396  )
1397  {
1398  return 0;
1399  }
1400  cWorld * World;
1402  if (!L.GetStackValues(1, World, Task))
1403  {
1404  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Cannot read parameters");
1405  }
1406  if (World == nullptr)
1407  {
1408  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
1409  }
1410  if (!Task->IsValid())
1411  {
1412  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter");
1413  }
1414 
1415  World->QueueTask([Task](cWorld & a_World)
1416  {
1417  Task->Call(&a_World);
1418  }
1419  );
1420  return 0;
1421 }
1422 
1423 
1424 
1425 
1426 
1427 static int tolua_cWorld_SetBlock(lua_State * tolua_S)
1428 {
1429  /* Function signature:
1430  World:SetBlock(BlockX, BlockY, BlockZ, BlockType, BlockMeta)
1431  --or--
1432  World:SetBlock(Position, BlockType, BlockMeta)
1433  */
1434 
1435  cLuaState L(tolua_S);
1436  int OffsetIndex;
1437  if (
1438  !L.CheckParamSelf("cWorld") ||
1439  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
1440  !L.CheckParamNumber(OffsetIndex, OffsetIndex + 1) ||
1441  !L.CheckParamEnd(OffsetIndex + 2)
1442  )
1443  {
1444  return 0;
1445  }
1446 
1447  if (OffsetIndex != 3) // Not the vector overload
1448  {
1449  L.LogStackTrace();
1450  LOGWARN("SetBlock with 3 position arguments is deprecated, use vector-parametered version instead.");
1451  }
1452 
1453  cWorld * World;
1454  Vector3i Position;
1455  BLOCKTYPE Type;
1456  NIBBLETYPE Meta;
1457 
1458  // Read the params:
1459  if (
1460  !L.GetStackValues(1, World) ||
1461  !GetStackVectorOr3Numbers(L, 2, Position) ||
1462  !L.GetStackValues(OffsetIndex, Type, Meta)
1463  )
1464  {
1465  return 0;
1466  }
1467 
1468  if (World == nullptr)
1469  {
1470  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1471  }
1472 
1473  if (!cChunkDef::IsValidHeight(Position))
1474  {
1475  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
1476  }
1477 
1478  World->SetBlock(Position, Type, Meta);
1479  return 0;
1480 }
1481 
1482 
1483 
1484 
1485 
1486 static int tolua_cWorld_SetBlockMeta(lua_State * tolua_S)
1487 {
1488  /* Function signature:
1489  World:SetBlockMeta(BlockX, BlockY, BlockZ, BlockMeta)
1490  --or--
1491  World:SetBlockMeta(Position, BlockMeta)
1492  */
1493 
1494  cLuaState L(tolua_S);
1495  int OffsetIndex;
1496  if (
1497  !L.CheckParamSelf("cWorld") ||
1498  !CheckParamVectorOr3Numbers(L, "Vector3<int>", 2, OffsetIndex) ||
1499  !L.CheckParamNumber(OffsetIndex) ||
1500  !L.CheckParamEnd(OffsetIndex + 1)
1501  )
1502  {
1503  return 0;
1504  }
1505 
1506  if (OffsetIndex != 3) // Not the vector overload
1507  {
1508  L.LogStackTrace();
1509  LOGWARN("SetBlockMeta with 3 position arguments is deprecated, use vector-parametered version instead.");
1510  }
1511 
1512  cWorld * World;
1513  Vector3i Position;
1514  NIBBLETYPE Meta;
1515 
1516  // Read the params:
1517  if (
1518  !L.GetStackValue(1, World) ||
1519  !GetStackVectorOr3Numbers(L, 2, Position) ||
1520  !L.GetStackValue(OffsetIndex, Meta)
1521  )
1522  {
1523  return 0;
1524  }
1525 
1526  if (World == nullptr)
1527  {
1528  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1529  }
1530 
1531  if (!cChunkDef::IsValidHeight(Position))
1532  {
1533  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'position'");
1534  }
1535 
1536  World->SetBlockMeta(Position, Meta);
1537  return 0;
1538 }
1539 
1540 
1541 
1542 
1543 
1544 static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
1545 {
1546  // Exported manually, because tolua would generate useless additional return values (a_Line1 .. a_Line4)
1547 
1548  // Check params:
1549  cLuaState L(tolua_S);
1550  if (
1551  !L.CheckParamUserType(1, "cWorld") ||
1552  !L.CheckParamNumber(2, 4) ||
1553  !L.CheckParamString(5, 8) ||
1554  !L.CheckParamEnd(9)
1555  )
1556  {
1557  return 0;
1558  }
1559 
1560  // Get params:
1561  cWorld * Self = nullptr;
1562  int BlockX = 0;
1563  int BlockY = 0;
1564  int BlockZ = 0;
1565  AString Line1, Line2, Line3, Line4;
1566  L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, Line1, Line2, Line3, Line4);
1567  if (Self == nullptr)
1568  {
1569  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
1570  }
1571 
1572  // Call the function:
1573  bool res = Self->SetSignLines({BlockX, BlockY, BlockZ}, Line1, Line2, Line3, Line4);
1574 
1575  // Push the returned values:
1576  L.Push(res);
1577  return 1;
1578 }
1579 
1580 
1581 
1582 
1583 
1584 static int tolua_cWorld_SetTimeOfDay(lua_State * tolua_S)
1585 {
1586  // Check params:
1587  cLuaState L(tolua_S);
1588  if (
1589  !L.CheckParamSelf("cWorld") ||
1590  !L.CheckParamNumber(2) ||
1591  !L.CheckParamEnd(3)
1592  )
1593  {
1594  return 0;
1595  }
1596 
1597  // Get params:
1598  cWorld * Self = nullptr;
1599  cTickTime::rep Time;
1600  L.GetStackValues(1, Self, Time);
1601  if (Self == nullptr)
1602  {
1603  return L.ApiParamError("Invalid 'self'");
1604  }
1605 
1606  // Call the function:
1607  Self->SetTimeOfDay(cTickTime(Time));
1608  return 0;
1609 }
1610 
1611 
1612 
1613 
1614 
1615 static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
1616 {
1617  // Function signature:
1618  // World:ScheduleTask(NumTicks, Callback)
1619 
1620  // Retrieve the args:
1621  cLuaState L(tolua_S);
1622  if (
1623  !L.CheckParamUserType(1, "cWorld") ||
1624  !L.CheckParamNumber (2) ||
1625  !L.CheckParamFunction(3)
1626  )
1627  {
1628  return 0;
1629  }
1630  cWorld * World;
1631  int NumTicks;
1632  auto Task = std::make_shared<cLuaState::cCallback>();
1633  if (!L.GetStackValues(1, World, NumTicks, Task))
1634  {
1635  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Cannot read parameters");
1636  }
1637  if (World == nullptr)
1638  {
1639  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
1640  }
1641  if (!Task->IsValid())
1642  {
1643  return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not store the callback parameter");
1644  }
1645 
1646  World->ScheduleTask(cTickTime(NumTicks), [Task](cWorld & a_World)
1647  {
1648  Task->Call(&a_World);
1649  }
1650  );
1651  return 0;
1652 }
1653 
1654 
1655 
1656 
1657 
1658 static int tolua_cWorld_SpawnSplitExperienceOrbs(lua_State* tolua_S)
1659 {
1660  cLuaState L(tolua_S);
1661  if (
1662  !L.CheckParamSelf("cWorld") ||
1663  !L.CheckParamUserType(2, "Vector3<double>") ||
1664  !L.CheckParamNumber(3) ||
1665  !L.CheckParamEnd(4)
1666  )
1667  {
1668  return 0;
1669  }
1670 
1671  cWorld * self = nullptr;
1672  Vector3d Position;
1673  int Reward;
1674  L.GetStackValues(1, self, Position, Reward);
1675  if (self == nullptr)
1676  {
1677  tolua_error(tolua_S, "Invalid 'self' in function 'SpawnSplitExperienceOrbs'", nullptr);
1678  return 0;
1679  }
1680 
1681  // Execute and push result:
1682  L.Push(self->SpawnExperienceOrb(Position, Reward));
1683  return 1;
1684 }
1685 
1686 
1687 
1688 
1689 
1690 static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
1691 {
1692  /* Exported manually, because tolua would require the out-only param a_Height to be used when calling
1693  Function signature: world:TryGetHeight(a_World, a_BlockX, a_BlockZ) -> IsValid, Height
1694  */
1695 
1696  // Check params:
1697  cLuaState L(tolua_S);
1698  if (
1699  !L.CheckParamUserType(1, "cWorld") ||
1700  !L.CheckParamNumber(2, 3) ||
1701  !L.CheckParamEnd(4)
1702  )
1703  {
1704  return 0;
1705  }
1706 
1707  // Get params:
1708  cWorld * self = nullptr;
1709  int BlockX = 0;
1710  int BlockZ = 0;
1711  L.GetStackValues(1, self, BlockX, BlockZ);
1712  if (self == nullptr)
1713  {
1714  tolua_error(tolua_S, "Invalid 'self' in function 'TryGetHeight'", nullptr);
1715  return 0;
1716  }
1717 
1718  // Call the implementation:
1719  int Height = 0;
1720  bool res = self->TryGetHeight(BlockX, BlockZ, Height);
1721  L.Push(res);
1722  if (res)
1723  {
1724  L.Push(Height);
1725  return 2;
1726  }
1727  return 1;
1728 }
1729 
1730 
1731 
1732 
1733 
1734 void cManualBindings::BindWorld(lua_State * tolua_S)
1735 {
1736  tolua_beginmodule(tolua_S, nullptr);
1737  tolua_beginmodule(tolua_S, "cWorld");
1738  tolua_function(tolua_S, "BroadcastBlockAction", tolua_cWorld_BroadcastBlockAction);
1739  tolua_function(tolua_S, "BroadcastSoundEffect", tolua_cWorld_BroadcastSoundEffect);
1740  tolua_function(tolua_S, "BroadcastSoundParticleEffect", tolua_cWorld_BroadcastSoundParticleEffect);
1741  tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect);
1742  tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
1743  tolua_function(tolua_S, "DoExplosionAt", tolua_cWorld_DoExplosionAt);
1744  tolua_function(tolua_S, "DoWithBeaconAt", DoWithBlockEntityAt<cBeaconEntity, E_BLOCK_BEACON>);
1745  tolua_function(tolua_S, "DoWithBedAt", DoWithBlockEntityAt<cBedEntity, E_BLOCK_BED>);
1746  tolua_function(tolua_S, "DoWithBlockEntityAt", DoWithBlockEntityAt<cBlockEntity>);
1747  tolua_function(tolua_S, "DoWithBrewingstandAt", DoWithBlockEntityAt<cBrewingstandEntity, E_BLOCK_BREWING_STAND>);
1748  tolua_function(tolua_S, "DoWithChestAt", DoWithBlockEntityAt<cChestEntity, E_BLOCK_CHEST, E_BLOCK_TRAPPED_CHEST>);
1749  tolua_function(tolua_S, "DoWithCommandBlockAt", DoWithBlockEntityAt<cCommandBlockEntity, E_BLOCK_COMMAND_BLOCK>);
1750  tolua_function(tolua_S, "DoWithDispenserAt", DoWithBlockEntityAt<cDispenserEntity, E_BLOCK_DISPENSER>);
1751  tolua_function(tolua_S, "DoWithDropSpenserAt", DoWithBlockEntityAt<cDropSpenserEntity, E_BLOCK_DISPENSER, E_BLOCK_DROPPER>);
1752  tolua_function(tolua_S, "DoWithDropperAt", DoWithBlockEntityAt<cDropperEntity, E_BLOCK_DROPPER>);
1753  tolua_function(tolua_S, "DoWithEntityByID", DoWithID<cWorld, cEntity, &cWorld::DoWithEntityByID>);
1754  tolua_function(tolua_S, "DoWithFlowerPotAt", DoWithBlockEntityAt<cFlowerPotEntity, E_BLOCK_FLOWER_POT>);
1755  tolua_function(tolua_S, "DoWithFurnaceAt", DoWithBlockEntityAt<cFurnaceEntity, E_BLOCK_FURNACE, E_BLOCK_LIT_FURNACE>);
1756  tolua_function(tolua_S, "DoWithHopperAt", DoWithBlockEntityAt<cHopperEntity, E_BLOCK_HOPPER>);
1757  tolua_function(tolua_S, "DoWithMobHeadAt", DoWithBlockEntityAt<cMobHeadEntity, E_BLOCK_HEAD>);
1758  tolua_function(tolua_S, "DoWithNearestPlayer", tolua_cWorld_DoWithNearestPlayer);
1759  tolua_function(tolua_S, "DoWithNoteBlockAt", DoWithBlockEntityAt<cNoteEntity, E_BLOCK_NOTE_BLOCK>);
1760  tolua_function(tolua_S, "DoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::DoWithPlayer>);
1761  tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_cWorld_DoWithPlayerByUUID);
1762  tolua_function(tolua_S, "FastSetBlock", tolua_cWorld_FastSetBlock);
1763  tolua_function(tolua_S, "FindAndDoWithPlayer", DoWith<cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
1764  tolua_function(tolua_S, "ForEachBlockEntityInChunk", ForEachBlockEntityInChunk<cBlockEntity>);
1765  tolua_function(tolua_S, "ForEachBrewingstandInChunk", ForEachBlockEntityInChunk<cBrewingstandEntity, E_BLOCK_BREWING_STAND>);
1766  tolua_function(tolua_S, "ForEachChestInChunk", ForEachBlockEntityInChunk<cChestEntity, E_BLOCK_CHEST, E_BLOCK_TRAPPED_CHEST>);
1767  tolua_function(tolua_S, "ForEachEntity", ForEach<cWorld, cEntity, &cWorld::ForEachEntity>);
1768  tolua_function(tolua_S, "ForEachEntityInBox", ForEachInBox<cWorld, cEntity, &cWorld::ForEachEntityInBox>);
1769  tolua_function(tolua_S, "ForEachEntityInChunk", tolua_cWorld_ForEachEntityInChunk);
1770  tolua_function(tolua_S, "ForEachFurnaceInChunk", ForEachBlockEntityInChunk<cFurnaceEntity, E_BLOCK_FURNACE, E_BLOCK_LIT_FURNACE>);
1771  tolua_function(tolua_S, "ForEachLoadedChunk", tolua_cWorld_ForEachLoadedChunk);
1772  tolua_function(tolua_S, "ForEachPlayer", ForEach<cWorld, cPlayer, &cWorld::ForEachPlayer>);
1773  tolua_function(tolua_S, "GetBlock", tolua_cWorld_GetBlock);
1774  tolua_function(tolua_S, "GetBlockBlockLight", tolua_cWorld_GetBlockBlockLight);
1775  tolua_function(tolua_S, "GetBlockInfo", tolua_cWorld_GetBlockInfo);
1776  tolua_function(tolua_S, "GetBlockMeta", tolua_cWorld_GetBlockMeta);
1777  tolua_function(tolua_S, "GetBlockSkyLight", tolua_cWorld_GetBlockSkyLight);
1778  tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cWorld_GetBlockTypeMeta);
1779  tolua_function(tolua_S, "GetSignLines", tolua_cWorld_GetSignLines);
1780  tolua_function(tolua_S, "GetTimeOfDay", tolua_cWorld_GetTimeOfDay);
1781  tolua_function(tolua_S, "GetWorldAge", tolua_cWorld_GetWorldAge);
1782  tolua_function(tolua_S, "PrepareChunk", tolua_cWorld_PrepareChunk);
1783  tolua_function(tolua_S, "QueueTask", tolua_cWorld_QueueTask);
1784  tolua_function(tolua_S, "ScheduleTask", tolua_cWorld_ScheduleTask);
1785  tolua_function(tolua_S, "SetBlock", tolua_cWorld_SetBlock);
1786  tolua_function(tolua_S, "SetBlockMeta", tolua_cWorld_SetBlockMeta);
1787  tolua_function(tolua_S, "SetSignLines", tolua_cWorld_SetSignLines);
1788  tolua_function(tolua_S, "SetTimeOfDay", tolua_cWorld_SetTimeOfDay);
1789  tolua_function(tolua_S, "SpawnSplitExperienceOrbs", tolua_cWorld_SpawnSplitExperienceOrbs);
1790  tolua_function(tolua_S, "TryGetHeight", tolua_cWorld_TryGetHeight);
1791  tolua_endmodule(tolua_S);
1792  tolua_endmodule(tolua_S);
1793 }
static int ForEachBlockEntityInChunk(lua_State *tolua_S)
static bool GetStackVectorOr3Numbers(cLuaState &L, int a_Index, Vector3< T > &a_Return)
Get a vector from the stack, which may be represented in lua as either a Vector3<T> or 3 numbers.
static int tolua_cWorld_BroadcastSoundParticleEffect(lua_State *tolua_S)
static int tolua_cWorld_GetBlockBlockLight(lua_State *tolua_S)
static int tolua_cWorld_GetBlockSkyLight(lua_State *tolua_S)
static int tolua_cWorld_GetWorldAge(lua_State *tolua_S)
static int tolua_cWorld_DoExplosionAt(lua_State *tolua_S)
static int tolua_cWorld_PrepareChunk(lua_State *tolua_S)
static int tolua_cWorld_GetBlock(lua_State *tolua_S)
static int tolua_cWorld_DoWithNearestPlayer(lua_State *tolua_S)
static int tolua_cWorld_ForEachLoadedChunk(lua_State *tolua_S)
static int tolua_cWorld_SetTimeOfDay(lua_State *tolua_S)
static int tolua_cWorld_QueueTask(lua_State *tolua_S)
static int ForEachInBox(lua_State *tolua_S)
static int tolua_cWorld_ForEachEntityInChunk(lua_State *tolua_S)
static int tolua_cWorld_BroadcastSoundEffect(lua_State *tolua_S)
static int tolua_cWorld_SetSignLines(lua_State *tolua_S)
static bool CheckParamVectorOr3Numbers(cLuaState &L, const char *a_VectorName, int a_Index, int &a_NextIndex)
Check that a Lua parameter is either a vector or 3 numbers in sequence.
static int tolua_cWorld_ChunkStay(lua_State *tolua_S)
static int tolua_cWorld_DoWithPlayerByUUID(lua_State *tolua_S)
static int tolua_cWorld_ScheduleTask(lua_State *tolua_S)
static int tolua_cWorld_FastSetBlock(lua_State *tolua_S)
static int tolua_cWorld_SetBlock(lua_State *tolua_S)
static int tolua_cWorld_GetBlockTypeMeta(lua_State *tolua_S)
static int tolua_cWorld_GetBlockMeta(lua_State *tolua_S)
static int tolua_cWorld_BroadcastBlockAction(lua_State *tolua_S)
static int tolua_cWorld_SetBlockMeta(lua_State *tolua_S)
static int tolua_cWorld_TryGetHeight(lua_State *tolua_S)
static int tolua_cWorld_SpawnSplitExperienceOrbs(lua_State *tolua_S)
static int tolua_cWorld_GetTimeOfDay(lua_State *tolua_S)
static int tolua_cWorld_GetBlockInfo(lua_State *tolua_S)
static int DoWithBlockEntityAt(lua_State *tolua_S)
Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that don't need to check their coord...
static int tolua_cWorld_GetSignLines(lua_State *tolua_S)
static int tolua_cWorld_BroadcastParticleEffect(lua_State *tolua_S)
@ 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
eExplosionSource
The source of an explosion.
Definition: Defines.h:309
@ esMonster
Definition: Defines.h:313
@ esOther
Definition: Defines.h:314
@ esWitherSkull
Definition: Defines.h:319
@ esEnderCrystal
Definition: Defines.h:311
@ esMax
Definition: Defines.h:320
@ esPlugin
Definition: Defines.h:315
@ esPrimedTNT
Definition: Defines.h:316
@ esBed
Definition: Defines.h:310
@ esWitherBirth
Definition: Defines.h:318
@ esGhastFireball
Definition: Defines.h:312
EffectID
Definition: EffectID.h:6
signed int Int32
Definition: Globals.h:152
std::chrono::duration< signed int, std::ratio_multiply< std::chrono::milliseconds::period, std::ratio< 50 > >> cTickTime
Definition: Globals.h:364
#define ASSERT(x)
Definition: Globals.h:276
unsigned char Byte
Definition: Globals.h:161
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
#define LOGWARN
Definition: LoggerSimple.h:88
BlockType
Definition: BlockTypes.h:4
std::string AString
Definition: StringUtils.h:11
Utilities to allow casting a cWorld to one of its interfaces without including World....
Definition: OpaqueWorld.h:13
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 LogStackValues(const char *a_Header=nullptr)
Logs all the elements' types on the API stack, with an optional header for the listing.
Definition: LuaState.cpp:2418
void LogStackTrace(int a_StartingDepth=0)
Logs all items in the current stack trace to the server console.
Definition: LuaState.cpp:2134
std::unique_ptr< cOptionalCallback > cOptionalCallbackPtr
Definition: LuaState.h:356
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
std::unique_ptr< cStackTable > cStackTablePtr
Definition: LuaState.h:542
bool CheckParamBool(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are bools; also logs warning if not.
Definition: LuaState.cpp:1796
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 CheckParamFunctionOrNil(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are functions or nils; also logs warning if not...
Definition: LuaState.cpp:1898
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 CheckParamUUID(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are UUIDs; also logs warning if not Accepts eit...
Definition: LuaState.cpp:1957
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 CheckParamTable(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are tables; also logs warning if not.
Definition: LuaState.cpp:1727
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
std::shared_ptr< cCallback > cCallbackSharedPtr
Definition: LuaState.h:327
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
Same thing as cCallback, but GetStackValue() won't fail if the callback value is nil.
Definition: LuaState.h:334
BLOCKTYPE GetBlockType() const
Definition: BlockEntity.h:97
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Wraps the chunk coords into a single structure.
Definition: ChunkDef.h:57
int m_ChunkZ
Definition: ChunkDef.h:60
int m_ChunkX
Definition: ChunkDef.h:59
static bool IsValidHeight(Vector3i a_BlockPosition)
Validates a height-coordinate.
Definition: ChunkDef.h:185
Interface class used as a callback for operations that involve chunk coords.
Definition: ChunkDef.h:467
virtual void Call(cChunkCoords a_Coords, bool a_IsSuccess)=0
Called with the chunk's coords, and an optional operation status flag for operations that support it.
Definition: Entity.h:76
Definition: Player.h:29
Definition: UUID.h:11
bool IsNil() const
Returns true if this contains the "nil" UUID with all bits set to 0.
Definition: UUID.h:30
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
bool DoWithPlayerByUUID(const cUUID &a_PlayerUUID, cPlayerListCallback a_Callback)
Finds the player over his uuid and calls the callback.
Definition: World.cpp:2339
void PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr< cChunkCoordCallback > a_CallAfter={})
Queues the chunk for preparing - making sure that it's generated and lit.
Definition: World.cpp:2542
virtual cTickTimeLong GetWorldAge(void) const override
Definition: World.cpp:491
bool ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
Calls the callback for each block entity in the specified chunk; returns true if all block entities p...
Definition: World.cpp:1375
bool SetSignLines(Vector3i a_BlockPos, const AString &a_Line1, const AString &a_Line2, const AString &a_Line3, const AString &a_Line4, cPlayer *a_Player=nullptr)
Sets the sign text, asking plugins for permission first.
Definition: World.cpp:2560
virtual void BroadcastBlockAction(Vector3i a_BlockPos, Byte a_Byte1, Byte a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle *a_Exclude=nullptr) override
bool GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString &a_Line1, AString &a_Line2, AString &a_Line3, AString &a_Line4)
Retrieves the test on the sign at the specified coords; returns false if there's no sign at those coo...
Definition: World.cpp:1429
virtual cTickTime GetTimeOfDay(void) const override
Definition: World.cpp:480
virtual bool DoWithBlockEntityAt(Vector3i a_Position, cBlockEntityCallback a_Callback) override
Calls the callback for the block entity at the specified coords; returns false if there's no block en...
Definition: World.cpp:1420
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override
bool DoWithNearestPlayer(Vector3d a_Pos, double a_RangeLimit, cPlayerListCallback a_Callback, bool a_CheckLineOfSight=true, bool a_IgnoreSpectator=true)
Calls the callback for nearest player for given position, Returns false if player not found,...
Definition: World.cpp:2356
cChunkMap * GetChunkMap(void)
Definition: World.h:852
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback)
Calls the callback for each entity in the specified chunk; returns true if all entities processed,...
Definition: World.cpp:2436
virtual void SetTimeOfDay(cTickTime a_TimeOfDay) override
Definition: World.cpp:518