589{
590
591 {
593
595 if (!result)
596 {
598 LOG_WARN(
"server.loading",
">> Loaded 0 object pools. DB table `pool_template` is empty.");
600 return;
601 }
602
604 do
605 {
606 Field* fields = result->Fetch();
607
609
612 pPoolTemplate.MapId = -1;
613 pPoolTemplate.Description = fields[2].
Get<std::string>();
614
615 ++count;
616 } while (result->NextRow());
617
620 }
621
622
623
624 LOG_INFO(
"server.loading",
"Loading Creatures Pooling Data...");
625 {
627
628
630
631 if (!result)
632 {
633 LOG_WARN(
"server.loading",
">> Loaded 0 creatures in pools. DB table `pool_creature` is empty.");
635 }
636 else
637 {
639 do
640 {
641 Field* fields = result->Fetch();
642
645 float chance = fields[2].
Get<
float>();
646
648 if (!data)
649 {
650 LOG_ERROR(
"sql.sql",
"`pool_creature` has a non existing creature spawn (GUID: {}) defined for pool id ({}), skipped.", guid, pool_id);
651 continue;
652 }
655 {
656 LOG_ERROR(
"sql.sql",
"`pool_creature` pool id ({}) is not in `pool_template`, skipped.", pool_id);
657 continue;
658 }
659 if (chance < 0 || chance > 100)
660 {
661 LOG_ERROR(
"sql.sql",
"`pool_creature` has an invalid chance ({}) for creature guid ({}) in pool id ({}), skipped.", chance, guid, pool_id);
662 continue;
663 }
664
666 if (pPoolTemplate->
MapId == -1)
668
669 if (pPoolTemplate->
MapId !=
int32(data->mapid))
670 {
671 LOG_ERROR(
"sql.sql",
"`pool_creature` has creature spawns on multiple different maps for creature guid ({}) in pool id ({}), skipped.", guid, pool_id);
672 continue;
673 }
674
681
682 ++count;
683 } while (result->NextRow());
684
687 }
688 }
689
690
691
692 LOG_INFO(
"server.loading",
"Loading Gameobjects Pooling Data...");
693 {
695
696
698
699 if (!result)
700 {
701 LOG_WARN(
"server.loading",
">> Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty.");
703 }
704 else
705 {
707 do
708 {
709 Field* fields = result->Fetch();
710
713 float chance = fields[2].
Get<
float>();
714
716 if (!data)
717 {
718 LOG_ERROR(
"sql.sql",
"`pool_gameobject` has a non existing gameobject spawn (GUID: {}) defined for pool id ({}), skipped.", guid, pool_id);
719 continue;
720 }
721
726 {
727 LOG_ERROR(
"sql.sql",
"`pool_gameobject` has a not lootable gameobject spawn (GUID: {}, type: {}) defined for pool id ({}), skipped.", guid, goinfo->
type, pool_id);
728 continue;
729 }
730
733 {
734 LOG_ERROR(
"sql.sql",
"`pool_gameobject` pool id ({}) is not in `pool_template`, skipped.", pool_id);
735 continue;
736 }
737
738 if (chance < 0 || chance > 100)
739 {
740 LOG_ERROR(
"sql.sql",
"`pool_gameobject` has an invalid chance ({}) for gameobject guid ({}) in pool id ({}), skipped.", chance, guid, pool_id);
741 continue;
742 }
743
745 if (pPoolTemplate->
MapId == -1)
747
748 if (pPoolTemplate->
MapId !=
int32(data->mapid))
749 {
750 LOG_ERROR(
"sql.sql",
"`pool_gameobject` has gameobject spawns on multiple different maps for gameobject guid ({}) in pool id ({}), skipped.", guid, pool_id);
751 continue;
752 }
753
760
761 ++count;
762 } while (result->NextRow());
763
766 }
767 }
768
769
770
771 LOG_INFO(
"server.loading",
"Loading Mother Pooling Data...");
772 {
774
775
777
778 if (!result)
779 {
780 LOG_WARN(
"server.loading",
">> Loaded 0 pools in pools");
782 }
783 else
784 {
786 do
787 {
788 Field* fields = result->Fetch();
789
792 float chance = fields[2].
Get<
float>();
793
794 {
797 {
798 LOG_ERROR(
"sql.sql",
"`pool_pool` mother_pool id ({}) is not in `pool_template`, skipped.", mother_pool_id);
799 continue;
800 }
801 }
802 {
805 {
806 LOG_ERROR(
"sql.sql",
"`pool_pool` included pool_id ({}) is not in `pool_template`, skipped.", child_pool_id);
807 continue;
808 }
809 }
810 if (mother_pool_id == child_pool_id)
811 {
812 LOG_ERROR(
"sql.sql",
"`pool_pool` pool_id ({}) includes itself, dead-lock detected, skipped.", child_pool_id);
813 continue;
814 }
815 if (chance < 0 || chance > 100)
816 {
817 LOG_ERROR(
"sql.sql",
"`pool_pool` has an invalid chance ({}) for pool id ({}) in mother pool id ({}), skipped.", chance, child_pool_id, mother_pool_id);
818 continue;
819 }
827
828 ++count;
829 } while (result->NextRow());
830
831
832
834 {
835 std::set<uint32> checkedPools;
837 {
838
840 {
843
845 {
846 LOG_ERROR(
"sql.sql",
"`pool_pool` has child pools on multiple maps in pool id ({}), skipped.", poolItr->second);
849 --count;
850 break;
851 }
852 }
853
854 checkedPools.insert(poolItr->first);
855 if (checkedPools.find(poolItr->second) != checkedPools.end())
856 {
857 std::ostringstream ss;
858 ss << "The pool(s) ";
859 for (std::set<uint32>::const_iterator itr = checkedPools.begin(); itr != checkedPools.end(); ++itr)
860 ss << *itr << ' ';
861 ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool "
862 << poolItr->first << " and child pool " << poolItr->second;
866 --count;
867 break;
868 }
869 }
870 }
871
874 }
875 }
876
877 LOG_INFO(
"server.loading",
"Loading Quest Pooling Data...");
878 {
880
883
884 if (!result)
885 {
886 LOG_WARN(
"server.loading",
">> Loaded 0 quests in pools");
888 }
889 else
890 {
893
894 enum eQuestTypes
895 {
896 QUEST_NONE = 0,
897 QUEST_DAILY = 1,
898 QUEST_WEEKLY = 2
899 };
900
901 std::map<uint32, int32> poolTypeMap;
903 do
904 {
905 Field* fields = result->Fetch();
906
909
911 if (!quest)
912 {
913 LOG_ERROR(
"sql.sql",
"`pool_quest` has a non existing quest template (Entry: {}) defined for pool id ({}), skipped.", entry, pool_id);
914 continue;
915 }
916
919 {
920 LOG_ERROR(
"sql.sql",
"`pool_quest` pool id ({}) is not in `pool_template`, skipped.", pool_id);
921 continue;
922 }
923
924
925
926 if (
uint32 motherPoolId = IsPartOfAPool<Pool>(pool_id))
927 {
928 LOG_ERROR(
"sql.sql",
"`pool_quest` pool id ({}) is a child of mother pool ({}), quest pools cannot be part of mother pools, skipped.", pool_id, motherPoolId);
929 continue;
930 }
931
932 if (!quest->IsDailyOrWeekly())
933 {
934 LOG_ERROR(
"sql.sql",
"`pool_quest` has an quest ({}) which is not daily or weekly in pool id ({}), use ExclusiveGroup instead, skipped.", entry, pool_id);
935 continue;
936 }
937
938 if (poolTypeMap[pool_id] == QUEST_NONE)
939 poolTypeMap[pool_id] = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY;
940
941 int32 currType = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY;
942
943 if (poolTypeMap[pool_id] != currType)
944 {
945 LOG_ERROR(
"sql.sql",
"`pool_quest` quest {} is {} but pool ({}) is specified for {}, mixing not allowed, skipped.",
946 entry, currType == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY", pool_id, poolTypeMap[pool_id] == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY");
947 continue;
948 }
949
952
953 if (creBounds.first == creBounds.second && goBounds.first == goBounds.second)
954 {
955 LOG_ERROR(
"sql.sql",
"`pool_quest` lists entry ({}) as member of pool ({}) but is not started anywhere, skipped.", entry, pool_id);
956 continue;
957 }
958
966
967 ++count;
968 } while (result->NextRow());
969
972 }
973 }
974
976 {
978 LOG_ERROR(
"sql.sql",
"Pool Id {} is empty (has no creatures, no gameobjects, no quests and no valid child pools). The pool will not be spawned.", poolId);
979 }
980
981
982 LOG_INFO(
"server.loading",
"Starting Objects Pooling System...");
983 {
985
986 QueryResult result =
WorldDatabase.Query(
"SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool FROM pool_template"
987 " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry"
988 " LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL");
989
990 if (!result)
991 {
992 LOG_INFO(
"server.loading",
">> Pool handling system initialized, 0 pools spawned.");
994 }
995 else
996 {
998 do
999 {
1000 Field* fields = result->Fetch();
1003
1005 continue;
1006
1008 {
1009 if (pool_pool_id)
1010
1011
1012 LOG_ERROR(
"sql.sql",
"Pool Id {} has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id {} and cannot be safely removed.", pool_entry, fields[2].Get<uint32>());
1013 else
1014 LOG_ERROR(
"sql.sql",
"Pool Id {} has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry);
1015 continue;
1016 }
1017
1018
1019 if (!pool_pool_id)
1020 {
1021
1022
1025
1027 if (templateData.
MapId != -1)
1029
1030 count++;
1031 }
1032 } while (result->NextRow());
1033
1034 LOG_INFO(
"server.loading",
">> Pool handling system initialized, {} pools will be spawned by default in {} ms", count,
GetMSTimeDiffToNow(oldMSTime));
1036 }
1037 }
1038}
std::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition DatabaseEnvFwd.h:45
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition DatabaseEnv.cpp:20
#define LOG_INFO(filterType__,...)
Definition Log.h:153
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
#define LOG_WARN(filterType__,...)
Definition Log.h:149
std::pair< PooledQuestRelation::const_iterator, PooledQuestRelation::const_iterator > PooledQuestRelationBounds
Definition PoolMgr.h:121
@ GAMEOBJECT_TYPE_CHEST
Definition SharedDefines.h:1567
@ GAMEOBJECT_TYPE_FISHINGHOLE
Definition SharedDefines.h:1589
@ GAMEOBJECT_TYPE_GOOBER
Definition SharedDefines.h:1574
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:131
uint32 getMSTime()
Definition Timer.h:103
@ WORLD_SEL_QUEST_POOLS
Definition WorldDatabase.h:31
Class used to access individual fields of database query result.
Definition Field.h:98
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition Field.h:112
uint32 LowType
Definition ObjectGuid.h:125
void SetPoolId(uint32 pool_id)
Definition PoolMgr.h:90
void AddEntry(PoolObject &poolitem, uint32 maxentries)
Definition PoolMgr.cpp:133
std::pair< uint32, uint32 > SearchPair
Definition PoolMgr.h:194
bool IsEmpty(uint32 pool_id) const
Definition PoolMgr.cpp:1194
bool CheckPool(uint32 pool_id) const
Definition PoolMgr.cpp:1220
PooledQuestRelation mQuestGORelation
Definition PoolMgr.h:173
PooledQuestRelation mQuestCreatureRelation
Definition PoolMgr.h:172
Definition PreparedStatement.h:157
Definition CreatureData.h:370
Definition GameObjectData.h:715
Definition GameObjectData.h:32
uint32 type
Definition GameObjectData.h:34
uint32 MaxLimit
Definition PoolMgr.h:32