Permalink
Browse files

[2762] Use own SD2 Error log file. Requires C-MaNGOS 12280

Update your configuration file.
Please be so kind to forward errors of the SD2Errors log file to the SD2-Team

You can find C-MaNGOS at github.com/cmangos
  • Loading branch information...
1 parent eed918a commit c68d6e4029ff848c1a950d29832bc9689d86ff81 @Schmoozerd Schmoozerd committed Nov 23, 2012
Showing with 82 additions and 69 deletions.
  1. +31 −22 ScriptMgr.cpp
  2. +3 −3 base/escort_ai.cpp
  3. +1 −1 base/follower_ai.cpp
  4. +1 −1 config.h
  5. +4 −4 include/sc_creature.cpp
  6. +5 −5 include/sc_instance.cpp
  7. +1 −1 include/sc_instance.h
  8. +4 −1 scriptdev2.conf.dist.in
  9. +1 −1 scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp
  10. +1 −1 scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp
  11. +2 −2 scripts/eastern_kingdoms/shadowfang_keep/boss_hummel.cpp
  12. +1 −1 scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp
  13. +1 −1 scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp
  14. +1 −1 scripts/eastern_kingdoms/zulaman/zulaman.cpp
  15. +1 −1 scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp
  16. +1 −1 scripts/kalimdor/durotar.cpp
  17. +1 −1 scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp
  18. +1 −1 scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp
  19. +1 −1 scripts/northrend/azjol-nerub/ahnkahet/instance_ahnkahet.cpp
  20. +1 −1 scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp
  21. +1 −1 scripts/northrend/gundrak/instance_gundrak.cpp
  22. +1 −1 scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_citadel.cpp
  23. +1 −1 scripts/northrend/naxxramas/instance_naxxramas.cpp
  24. +1 −1 scripts/northrend/nexus/nexus/instance_nexus.cpp
  25. +1 −1 scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp
  26. +1 −1 scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp
  27. +1 −1 scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp
  28. +1 −1 scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp
  29. +1 −1 scripts/outland/black_temple/instance_black_temple.cpp
  30. +1 −1 scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp
  31. +1 −1 scripts/outland/hellfire_peninsula.cpp
  32. +1 −1 scripts/outland/shadowmoon_valley.cpp
  33. +1 −1 scripts/outland/shattrath_city.cpp
  34. +1 −1 scripts/world/go_scripts.cpp
  35. +1 −1 scripts/world/npcs_special.cpp
  36. +1 −1 sd2_revision_nr.h
  37. +1 −1 sql/scriptdev2_script_full.sql
  38. +1 −0 sql/updates/r2762_scriptdev2.sql
  39. +1 −1 system/system.cpp
View
@@ -27,7 +27,7 @@ void LoadDatabase()
if (strSD2DBinfo.empty())
{
- error_log("SD2: Missing Scriptdev2 database info from configuration file. Load database aborted.");
+ script_error_log("Missing Scriptdev2 database info from configuration file. Load database aborted.");
return;
}
@@ -45,12 +45,11 @@ void LoadDatabase()
}
else
{
- error_log("SD2: Unable to connect to Database. Load database aborted.");
+ script_error_log("Unable to connect to Database. Load database aborted.");
return;
}
SD2Database.HaltDelayThread();
-
}
struct TSpellSummary
@@ -72,6 +71,8 @@ void FreeScriptLibrary()
m_scripts.clear();
num_sc_scripts = 0;
+
+ setScriptLibraryErrorFile(NULL, NULL);
}
MANGOS_DLL_EXPORT
@@ -89,14 +90,22 @@ void InitScriptLibrary()
outstring_log("");
// Get configuration file
+ bool configFailure = false;
if (!SD2Config.SetSource(_SCRIPTDEV2_CONFIG))
- error_log("SD2: Unable to open configuration file. Database will be unaccessible. Configuration values will use default.");
+ configFailure = true;
else
outstring_log("SD2: Using configuration file %s", _SCRIPTDEV2_CONFIG);
+ // Set SD2 Error Log File
+ std::string sd2LogFile = SD2Config.GetStringDefault("SD2ErrorLogFile", "SD2Errors.log");
+ setScriptLibraryErrorFile(sd2LogFile.c_str(), "SD2");
+
+ if (configFailure)
+ script_error_log("Unable to open configuration file. Database will be unaccessible. Configuration values will use default.");
+
// Check config file version
if (SD2Config.GetIntDefault("ConfVersion", 0) != SD2_CONF_VERSION)
- error_log("SD2: Configuration file version doesn't match expected version. Some config variables may be wrong or missing.");
+ script_error_log("Configuration file version doesn't match expected version. Some config variables may be wrong or missing.");
outstring_log("");
@@ -119,7 +128,7 @@ void InitScriptLibrary()
for (uint32 i = 1; i < GetScriptIdsCount(); ++i)
{
if (!m_scripts[i])
- error_log("SD2: No script found for ScriptName '%s'.", GetScriptName(i));
+ script_error_log("No script found for ScriptName '%s'.", GetScriptName(i));
}
outstring_log(">> Loaded %i C++ Scripts.", num_sc_scripts);
@@ -139,23 +148,23 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
{
if (!pSource)
{
- error_log("SD2: DoScriptText entry %i, invalid Source pointer.", iTextEntry);
+ script_error_log("DoScriptText entry %i, invalid Source pointer.", iTextEntry);
return;
}
if (iTextEntry >= 0)
{
- error_log("SD2: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.",
- pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
+ script_error_log("DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.",
+ pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
return;
}
const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry);
if (!pData)
{
- error_log("SD2: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.",
- pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
+ script_error_log("DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.",
+ pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
return;
}
@@ -179,15 +188,15 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
pSource->PlayDirectSound(pData->uiSoundId);
}
else
- error_log("SD2: DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
+ script_error_log("DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
}
if (pData->uiEmote)
{
if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER)
((Unit*)pSource)->HandleEmote(pData->uiEmote);
else
- error_log("SD2: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId());
+ script_error_log("DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId());
}
switch (pData->uiType)
@@ -209,7 +218,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
pSource->MonsterWhisper(iTextEntry, pTarget);
else
- error_log("SD2: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
+ script_error_log("DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
break;
}
@@ -218,7 +227,7 @@ void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
pSource->MonsterWhisper(iTextEntry, pTarget, true);
else
- error_log("SD2: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
+ script_error_log("DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
break;
}
@@ -241,27 +250,27 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
{
if (!pMap)
{
- error_log("SD2: DoOrSimulateScriptTextForMap entry %i, invalid Map pointer.", iTextEntry);
+ script_error_log("DoOrSimulateScriptTextForMap entry %i, invalid Map pointer.", iTextEntry);
return;
}
if (iTextEntry >= 0)
{
- error_log("SD2: DoOrSimulateScriptTextForMap with source entry %u for map %u attempts to process text entry %i, but text entry must be negative.", uiCreatureEntry, pMap->GetId(), iTextEntry);
+ script_error_log("DoOrSimulateScriptTextForMap with source entry %u for map %u attempts to process text entry %i, but text entry must be negative.", uiCreatureEntry, pMap->GetId(), iTextEntry);
return;
}
CreatureInfo const* pInfo = GetCreatureTemplateStore(uiCreatureEntry);
if (!pInfo)
{
- error_log("SD2: DoOrSimulateScriptTextForMap has invalid source entry %u for map %u.", uiCreatureEntry, pMap->GetId());
+ script_error_log("DoOrSimulateScriptTextForMap has invalid source entry %u for map %u.", uiCreatureEntry, pMap->GetId());
return;
}
const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry);
if (!pData)
{
- error_log("SD2: DoOrSimulateScriptTextForMap with source entry %u for map %u could not find text entry %i.", uiCreatureEntry, pMap->GetId(), iTextEntry);
+ script_error_log("DoOrSimulateScriptTextForMap with source entry %u for map %u could not find text entry %i.", uiCreatureEntry, pMap->GetId(), iTextEntry);
return;
}
@@ -270,7 +279,7 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
if (pData->uiType != CHAT_TYPE_ZONE_YELL)
{
- error_log("SD2: DoSimulateScriptTextForMap entry %i has not supported chat type %u.", iTextEntry, pData->uiType);
+ script_error_log("DoSimulateScriptTextForMap entry %i has not supported chat type %u.", iTextEntry, pData->uiType);
return;
}
@@ -279,7 +288,7 @@ void DoOrSimulateScriptTextForMap(int32 iTextEntry, uint32 uiCreatureEntry, Map*
if (GetSoundEntriesStore()->LookupEntry(pData->uiSoundId))
pMap->PlayDirectSoundToMap(pData->uiSoundId);
else
- error_log("SD2: DoOrSimulateScriptTextForMap entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
+ script_error_log("DoOrSimulateScriptTextForMap entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
}
if (pCreatureSource) // If provided pointer for sayer, use direct version
@@ -301,7 +310,7 @@ void Script::RegisterSelf(bool bReportError)
else
{
if (bReportError)
- error_log("SD2: Script registering but ScriptName %s is not assigned in database. Script will not be used.", Name.c_str());
+ script_error_log("Script registering but ScriptName %s is not assigned in database. Script will not be used.", Name.c_str());
delete this;
}
View
@@ -385,7 +385,7 @@ void npc_escortAI::MovementInform(uint32 uiMoveType, uint32 uiPointId)
// Make sure that we are still on the right waypoint
if (CurrentWP->uiId != uiPointId)
{
- error_log("SD2: EscortAI for Npc %u reached waypoint out of order %u, expected %u.", m_creature->GetEntry(), uiPointId, CurrentWP->uiId);
+ script_error_log("EscortAI for Npc %u reached waypoint out of order %u, expected %u.", m_creature->GetEntry(), uiPointId, CurrentWP->uiId);
return;
}
@@ -489,13 +489,13 @@ void npc_escortAI::Start(bool bRun, const Player* pPlayer, const Quest* pQuest,
{
if (m_creature->getVictim())
{
- error_log("SD2: EscortAI attempt to Start while in combat.");
+ script_error_log("EscortAI attempt to Start while in combat.");
return;
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
- error_log("SD2: EscortAI attempt to Start while already escorting.");
+ script_error_log("EscortAI attempt to Start while already escorting.");
return;
}
@@ -283,7 +283,7 @@ void FollowerAI::StartFollow(Player* pLeader, uint32 uiFactionForFollower, const
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
- error_log("SD2: FollowerAI attempt to StartFollow while already following.");
+ script_error_log("FollowerAI attempt to StartFollow while already following.");
return;
}
View
@@ -25,7 +25,7 @@
// Format is YYYYMMDDRR where RR is the change in the conf file
// for that day.
-#define SD2_CONF_VERSION 2010062001
+#define SD2_CONF_VERSION 2012112301
#ifdef WIN32
#define MANGOS_DLL_EXPORT extern "C" __declspec(dllexport)
@@ -187,7 +187,7 @@ void ScriptedAI::DoPlaySoundToSet(WorldObject* pSource, uint32 uiSoundId)
if (!GetSoundEntriesStore()->LookupEntry(uiSoundId))
{
- error_log("SD2: Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", uiSoundId, pSource->GetTypeId(), pSource->GetGUIDLow());
+ script_error_log("Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", uiSoundId, pSource->GetTypeId(), pSource->GetGUIDLow());
return;
}
@@ -401,7 +401,7 @@ void ScriptedAI::DoResetThreat()
{
if (!m_creature->CanHaveThreatList() || m_creature->getThreatManager().isThreatListEmpty())
{
- error_log("SD2: DoResetThreat called for creature that either cannot have threat list or has empty threat list (m_creature entry = %d)", m_creature->GetEntry());
+ script_error_log("DoResetThreat called for creature that either cannot have threat list or has empty threat list (m_creature entry = %d)", m_creature->GetEntry());
return;
}
@@ -422,7 +422,7 @@ void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, flo
if (pUnit->GetTypeId() != TYPEID_PLAYER)
{
- error_log("SD2: %s tried to teleport non-player (%s) to x: %f y:%f z: %f o: %f. Aborted.", m_creature->GetGuidStr().c_str(), pUnit->GetGuidStr().c_str(), fX, fY, fZ, fO);
+ script_error_log("%s tried to teleport non-player (%s) to x: %f y:%f z: %f o: %f. Aborted.", m_creature->GetGuidStr().c_str(), pUnit->GetGuidStr().c_str(), fX, fY, fZ, fO);
return;
}
@@ -570,7 +570,7 @@ bool ScriptedAI::EnterEvadeIfOutOfCombatArea(const uint32 uiDiff)
return false;
break;
default:
- error_log("SD2: EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition.", m_creature->GetEntry());
+ script_error_log("EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition.", m_creature->GetEntry());
return false;
}
@@ -26,7 +26,7 @@ void ScriptedInstance::DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTi
pGo->ResetDoorOrButton();
}
else
- error_log("SD2: Script call DoUseDoorOrButton, but gameobject entry %u is type %u.", pGo->GetEntry(), pGo->GetGoType());
+ script_error_log("Script call DoUseDoorOrButton, but gameobject entry %u is type %u.", pGo->GetEntry(), pGo->GetGoType());
}
}
@@ -38,7 +38,7 @@ void ScriptedInstance::DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTim
DoUseDoorOrButton(find->second, uiWithRestoreTime, bUseAlternativeState);
else
// Output log, possible reason is not added GO to storage, or not yet loaded
- debug_log("SD2: Script call DoUseDoorOrButton(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
+ script_error_log("Script call DoUseDoorOrButton(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
/**
@@ -75,7 +75,7 @@ void ScriptedInstance::DoToggleGameObjectFlags(uint32 uiEntry, uint32 uiGOflags,
DoToggleGameObjectFlags(find->second, uiGOflags, bApply);
else
// Output log, possible reason is not added GO to storage, or not yet loaded
- debug_log("SD2: Script call ToogleTameObjectFlags (by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
+ script_error_log("Script call ToogleTameObjectFlags (by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
/**
@@ -108,7 +108,7 @@ void ScriptedInstance::DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespaw
DoRespawnGameObject(find->second, uiTimeToDespawn);
else
// Output log, possible reason is not added GO to storage, or not yet loaded;
- debug_log("SD2: Script call DoRespawnGameObject(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
+ script_error_log(" Script call DoRespawnGameObject(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
/**
@@ -266,7 +266,7 @@ void DialogueHelper::StartNextDialogueText(int32 iTextEntry)
if (!bFound)
{
- error_log("SD2: Script call DialogueHelper::StartNextDialogueText, but textEntry %i is not in provided dialogue (on map id %u)", iTextEntry, m_pInstance ? m_pInstance->instance->GetId() : 0);
+ script_error_log("Script call DialogueHelper::StartNextDialogueText, but textEntry %i is not in provided dialogue (on map id %u)", iTextEntry, m_pInstance ? m_pInstance->instance->GetId() : 0);
return;
}
@@ -21,7 +21,7 @@ enum EncounterState
#define OUT_SAVE_INST_DATA_COMPLETE debug_log("SD2: Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_LOAD_INST_DATA(a) debug_log("SD2: Loading Instance Data for Instance %s (Map %d, Instance Id %d). Input is '%s'", instance->GetMapName(), instance->GetId(), instance->GetInstanceId(), a)
#define OUT_LOAD_INST_DATA_COMPLETE debug_log("SD2: Instance Data Load for Instance %s (Map %d, Instance Id: %d) is complete.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
-#define OUT_LOAD_INST_DATA_FAIL error_log("SD2: Unable to load Instance Data for Instance %s (Map %d, Instance Id: %d).", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
+#define OUT_LOAD_INST_DATA_FAIL script_error_log("Unable to load Instance Data for Instance %s (Map %d, Instance Id: %d).", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
class MANGOS_DLL_DECL ScriptedInstance : public InstanceData
{
@@ -2,7 +2,7 @@
# This file must be placed within the directory which holds mangosd.conf and realmd.conf
[ScriptDev2Conf]
-ConfVersion=2010062001
+ConfVersion=2012112301
# Database connection settings for the world server.
# Default: hostname;port;username;password;database
@@ -11,3 +11,6 @@ ConfVersion=2010062001
# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux
# Unix sockets: experimental, not tested
ScriptDev2DatabaseInfo = "127.0.0.1;3306;mangos;mangos;scriptdev2"
+
+# Log File for SD2-Errors
+SD2ErrorLogFile = "SD2Errors.log"
@@ -397,7 +397,7 @@ void instance_blackrock_spire::DoProcessEmberseerEvent()
if (m_lIncarceratorGUIDList.empty())
{
- error_log("SD2: Npc %u couldn't be found. Please check your DB content!", NPC_BLACKHAND_INCARCERATOR);
+ script_error_log("Npc %u couldn't be found. Please check your DB content!", NPC_BLACKHAND_INCARCERATOR);
return;
}
@@ -147,7 +147,7 @@ struct MANGOS_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
else
{
// Make an error message in case something weird happened here
- error_log("SD2: Selin Fireheart unable to drain crystal as the crystal is either dead or deleted..");
+ script_error_log("Selin Fireheart unable to drain crystal as the crystal is either dead or deleted..");
m_bDrainingCrystal = false;
}
}
@@ -191,7 +191,7 @@ struct MANGOS_DLL_DECL npc_valentine_boss_managerAI : public ScriptedAI, private
pBaxter->GetMotionMaster()->MovePoint(1, fX, fY, fZ);
}
else
- error_log("SD2: Gameobject %u couldn't be found or something really bad happened.", GO_APOTHECARE_VIALS);
+ script_error_log("Gameobject %u couldn't be found or something really bad happened.", GO_APOTHECARE_VIALS);
}
// Move Frye to position
@@ -209,7 +209,7 @@ struct MANGOS_DLL_DECL npc_valentine_boss_managerAI : public ScriptedAI, private
pFrye->GetMotionMaster()->MovePoint(1, fX, fY, fZ);
}
else
- error_log("SD2: Gameobject %u couldn't be found or something really bad happened.", GO_CHEMISTRY_SET);
+ script_error_log("Gameobject %u couldn't be found or something really bad happened.", GO_CHEMISTRY_SET);
}
}
@@ -201,7 +201,7 @@ struct MANGOS_DLL_DECL boss_brutallusAI : public ScriptedAI, private DialogueHel
{
// Error log if Madrigosa dies
if (pSummoned->GetEntry() == NPC_MADRIGOSA)
- error_log("SD2: Npc %u, %s, died unexpectedly. Felmyst won't be summoned anymore.", pSummoned->GetEntry(), pSummoned->GetName());
+ script_error_log("Npc %u, %s, died unexpectedly. Felmyst won't be summoned anymore.", pSummoned->GetEntry(), pSummoned->GetName());
}
void SummonedCreatureDespawn(Creature* pSummoned) override
@@ -295,7 +295,7 @@ void instance_zulaman::SetData(uint32 uiType, uint32 uiData)
break;
default:
- error_log("SD2: Instance Zulaman: ERROR SetData = %u for type %u does not exist/not implemented.", uiType, uiData);
+ script_error_log("Instance Zulaman: ERROR SetData = %u for type %u does not exist/not implemented.", uiType, uiData);
return;
}
Oops, something went wrong.

0 comments on commit c68d6e4

Please sign in to comment.