#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "LogClient/LogClient.h" #include "LuaVM.h" #include "ScriptNPC.h" #include "ScriptItem.h" #include "ScriptMisc.h" #include "ScriptCommon.h" #include "ScriptPlayer.h" #include "ScriptGuild.h" #include "ScriptQuest.h" #include "StructPlayer.h" #include "StructSummon.h" #include "StructMonster.h" #include "StructItem.h" #include "AuctionManager.h" #include "DungeonManager.h" #include "FieldPropManager.h" #include "ScheduledCommandManager.h" #include "StructEventItemManager.h" #include "RoamingManager.h" #include "HuntaholicManager.h" #include "CompeteManager.h" #include "RankingManager.h" #include "InstanceDungeonManager.h" #include "BattleArenaManager.h" #include "GameNetwork.h" #include "CommunityLoader.h" #include "ContentLoader.h" #include "LocationLoader.h" #include "GameAllocator.h" #include "DBAllocator.h" #include "SendMessage.h" #include "XSecuritySolutionManager.h" #include "DBPerformanceTracker.h" #include "SchedulingPerformanceTracker.h" #include "NetworkReceiverPerformanceTracker.h" #include "ADOConnection.h" #include #include __declspec( thread ) XSEH::THREAD_INFO s_ThreadInfo; volatile bool g_bPerformanceTracing = true; volatile DWORD g_nIntervalTimeToLogPerformance = 10000; // default: 10초마다 기록 bool b_performanceUpdate; unsigned __stdcall performanceLogFunc( void* ); void WriteHeapUsageInfo( HANDLE hFile ) { DWORD dwWritten = 0; std::string strMemoryPoolSize; XStringUtil::Format( strMemoryPoolSize, "PlayerHeapSize : %d kb\r\n", GetPlayerHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "MonsterHeapSize : %d kb\r\n", GetMonsterHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "ItemHeapSize : %d kb\r\n", GetItemHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "SummonHeapSize : %d kb\r\n", GetSummonHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "PetHeapSize : %d kb\r\n", GetPetHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "SkillHeapSize : %d kb\r\n", GetSkillHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "QuestHeapSize : %d kb\r\n", GetQuestHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "TitleHeapSize : %d kb\r\n", GetTitleHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "TitleConditionHeapSize: %d kb\r\n", GetTitleConditionHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "ProcHeapSize : %d kb\r\n", GetProcHeapSize() ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); XStringUtil::Format( strMemoryPoolSize, "DBHeapSize : %d kb\r\n\r\n", GetDBHeap().GetAllocSize() >> 10 ); WriteFile( hFile, strMemoryPoolSize.c_str(), static_cast< DWORD >( strMemoryPoolSize.length() ), &dwWritten, NULL ); } void WINAPI CaptainHerlockExceptionFilter( HANDLE hFile ) { g_DBTracker.dump(); std::string strVersionInfo; DWORD dwWritten; XModuleInfo cModuleInfo; cModuleInfo.Load( ::GetCurrentProcess() ); char szMyVersion[64] = ""; const WORD* pFileVerion = cModuleInfo.FileVersion(); s_sprintf( szMyVersion, _countof( szMyVersion ), "%d.%d.%d.%d", pFileVerion[0], pFileVerion[1], pFileVerion[2], pFileVerion[3] ); XStringUtil::Format( strVersionInfo, "Server Version : v%s\r\n", szMyVersion ); WriteFile( hFile, strVersionInfo.c_str(), static_cast< DWORD >( strVersionInfo.length() ), &dwWritten, NULL ); WriteHeapUsageInfo( hFile ); } volatile int g_bUseLockDelayLogging = 0; struct _HerlockIntf : ArcadiaFrameworkIntf { bool onInit( HWND hWnd ); bool onMessage( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); bool onKeyDown( int nVkCode ); bool onCommand( const char* szTarget, const char* szFrom, const char *szFullCmd, std::vector< std::string > & vList, ArcadiaCommandResultReceiver & receiver ); bool onDeInit(); void onDrawUser( HDC dc ); } myFrameworkIntf; unsigned __stdcall initFunc( void* ) { XSetThreadName( -1, "GameLoader" ); CoInitialize(NULL); InitGameHeap(); InitDBHeap(); XSEH::SetUserFunc( CaptainHerlockExceptionFilter ); StructItem::InitItemSystem(); StructCreature::InitCreatureSystem(); XBossWorker worker; void InitArcadia(); InitArcadia(); void LoadResource(); LoadResource(); ResourceManager::Init(); MonsterLoader monster_loader; PetLoader pet_loader; ItemLoader item_loader; EventAreaHandlerLoader event_area_loader; MapLoader map_loader; SkillLoader skill_loader; StringLoader string_loader; MixLoader mix_loader; BitmapLoader bitmap_loader; PartyLoader party_loader; GuildLoader guild_loader; ETCLoader etc_loader; QuestLoader quest_loader; LocationLoader location_loader; NPCLoader npc_loader; ChannelLoader channel_loader; FieldPropLoader prop_loader; FieldPropSwitchingLoader prop_switching_loader; FieldPropDataLoader prop_data_loader; DungeonLoader dungeon_loader; ScheduledCommandLoader scheduled_command_loader; AuctionCategoryLoader auction_category_loader; AutoAuctionLoader auto_auction_loader; AutoAuctionRegistrationInfoLoader auto_auction_reg_info_loader; AuctionLoader auction_loader; RoamingLoader roaming_loader; HuntaholicLoader huntaholic_loader; RankingLoader ranking_loader; DeathmatchLoader deathmatch_loader; CreatureEnhanceLoader creature_enhance_loader; CreatureFarmLoader creature_farm_loader; InstanceDungeonLoader instance_dungeon_loader; TitleLoader title_loader; BattleArenaLoader battle_arena_loader; AwakenLoader awaken_loader; RandomItemLoader random_item_loader; void thread_com_init_func( int nThreadNum ); // 워커 쓰레드 생성 worker.StartThread( "GameLoader", 4, THREAD_PRIORITY_NORMAL, thread_com_init_func ); // 스트링 테이블은 미리 읽어야함 string_loader.onProcess( 0 ); worker.Push( &skill_loader ); worker.Push( &item_loader ); worker.Push( &auction_category_loader ); worker.Push( &event_area_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &monster_loader ); // skill_loader 완료 필요 worker.Push( &bitmap_loader ); worker.Push( &map_loader ); worker.Push( &auto_auction_loader ); // auction_category_loader 완료 필요 while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &etc_loader ); // skill_loader 완료 필요 worker.Push( &quest_loader ); worker.Push( &location_loader ); worker.Push( &auto_auction_reg_info_loader ); // auto_auction_loader 완료 필요 while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &guild_loader ); worker.Push( &channel_loader ); // map_loader 완료 필요 worker.Push( &dungeon_loader ); // map_loader 완료 필요 worker.Push( &mix_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &prop_loader ); // channel_loader 완료 필요 worker.Push( &roaming_loader ); // channel_loader 완료 필요 worker.Push( &prop_switching_loader ); worker.Push( &creature_enhance_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &party_loader ); worker.Push( &prop_data_loader ); // prop_loader, prop_switching_loader 완료 필요 worker.Push( &pet_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &auction_loader ); // auction_category_loader, item_loader, skill_loader, state_loader, etc_loader(소환수 로딩 관련 스텟 정보 및 소환수 강화 정보 필요), pet loader, monster_loader 완료 필요 worker.Push( &scheduled_command_loader ); worker.Push( &npc_loader ); // string_loader, channel_loader, roaming_loader 완료 필요 worker.Push( &huntaholic_loader ); // channel_loader 완료 필요 while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &ranking_loader ); worker.Push( &deathmatch_loader ); worker.Push( &creature_farm_loader ); worker.Push( &instance_dungeon_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); worker.Push( &title_loader ); worker.Push( &battle_arena_loader ); worker.Push( &awaken_loader ); worker.Push( &random_item_loader ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); // prop_data_loader의 로딩까지 완료된 후에 동작 시작해야 함 FieldPropManager::GetInstance().Init(); StructEventItemManager::GetInstance().Init(); // 이벤트 아이템 매니저도 로딩 함 해주고~ // 스크립트 로드 GameContent::LoadScript(); // 리스폰 정보 처리 map_loader.InitMapInfo(); // Call a first script on server initialization LUA()->RunString( "on_server_init()" ); while( ( worker.GetActiveThreadCount() + worker.GetWaitingWorkCount() ) ) Sleep( 50 ); GameContent::AddNPCToWorld(); GameContent::AddRespawnObjectToWorld(); worker.EndThread(); ENV().Set( "game.loading", "complete" ); DungeonManager::Instance().Init(); AuctionManager::Instance().Init(); // AutoAuctionRegistrationInfoLoader 완료 전에는 호출되면 안 됨 RoamingManager::Instance().Init(); HuntaholicManager::Instance().Init(); BattleArenaManager::Instance().Init(); CompeteManager::Instance().Init(); RankingManager::Instance().Init(); InstanceDungeonManager::Instance().Init(); ArcadiaServer::Instance().SetObjectPriority( &g_DBTracker, ArSchedulerObject::UPDATE_PRIORITY_NORMAL ); InitMessageLogger(); return 0; } void InitDefaultEnv() { XModuleInfo cModuleInfo; cModuleInfo.Load( ::GetCurrentProcess() ); char szMyVersion[64] = ""; const WORD* pFileVerion = cModuleInfo.FileVersion(); s_sprintf( szMyVersion, _countof( szMyVersion ), "%d.%d.%d.%d", pFileVerion[0], pFileVerion[1], pFileVerion[2], pFileVerion[3] ); ENV().Set( "game.server_version", szMyVersion ); ENV().SetReadOnly( "game.server_version" ); ENV().SetDefaultValue( "db.user.name", "Telecaster" ); ENV().SetDefaultValue( "db.user.server", "127.0.0.1" ); // Fraun changed cadb.nflavor.com to 127.0.0.1 to avoid leaks to galalab 8/16/2025 ENV().SetDefaultValue( "db.user.thread_total", 4 ), ENV().SetDefaultValue( "db.user.account", "sa" ); ENV().SetDefaultValue( "db.user._password", "" ); ENV().SetDefaultValue( "db.c.name", "Arcadia" ); ENV().SetDefaultValue( "db.c.server", "127.0.0.1" ); // Fraun changed cadb.nflavor.com to 127.0.0.1 to avoid leaks to galalab 8/16/2025 ENV().SetDefaultValue( "db.c.account", "sa" ); ENV().SetDefaultValue( "db.c._password", "" ); ENV().Bind( "game.battle_arena_reconnect_wait_duration", (int*)&GameRule::nBattleArenaReconnectWaitDuration ); ENV().Bind( "game.mod", &GameRule::fPlyMod ); ENV().Bind( "game.user_count", (int*)&StructPlayer::GetPlayerCount() ); ENV().Bind( "game.party_exp_penalty_level", &GameRule::nPartyExpPenaltyLevel ); ENV().Bind( "game.party_exp_rate_0", &GameRule::fPartyEXPRate[ 0 ] ); ENV().Bind( "game.party_exp_rate_1", &GameRule::fPartyEXPRate[ 1 ] ); ENV().Bind( "game.party_exp_rate_2", &GameRule::fPartyEXPRate[ 2 ] ); ENV().Bind( "game.party_exp_rate_3", &GameRule::fPartyEXPRate[ 3 ] ); ENV().Bind( "game.party_exp_rate_4", &GameRule::fPartyEXPRate[ 4 ] ); ENV().Bind( "game.party_exp_rate_5", &GameRule::fPartyEXPRate[ 5 ] ); ENV().Bind( "game.party_exp_rate_6", &GameRule::fPartyEXPRate[ 6 ] ); ENV().Bind( "game.card_drop_rate", &GameRule::fCardDropRate ); ENV().Bind( "game.item_drop_rate", &GameRule::fItemDropRate ); ENV().Bind( "game.no_collision_check", &GameRule::bIsNoCollisionCheck ); ENV().Bind( "game.skip_loading_attribute", &GameRule::bSkipLoadingAttribute ); ENV().Bind( "game.gold_drop_rate", &GameRule::fGoldDropRate ); ENV().Bind( "game.min_speed", &GameRule::nMinSpeed); ENV().Bind( "game.item_hold_time", &GameRule::nItemHoldTime); ENV().Bind( "game.chaos_drop_rate", &GameRule::fChaosDropRate ); ENV().Bind( "game.exp_rate", &GameRule::fEXPRate ); ENV().Bind( "game.pvp_damage_rate_for_player", &GameRule::fPVPDamageRateForPlayer ); ENV().Bind( "game.pvp_damage_rate_for_summon", &GameRule::fPVPDamageRateForSummon ); ENV().Bind( "game.evp_boss_damage_rate", &GameRule::fEVPBossDamageRate); ENV().Bind( "game.evs_boss_damage_rate", &GameRule::fEVSBossDamageRate); ENV().Bind( "game.evp_damage_rate", &GameRule::fEVPDamageRate); ENV().Bind( "game.evs_damage_rate", &GameRule::fEVSDamageRate); ENV().Bind( "game.stamina_bonus_rate", &GameRule::fStaminaBonusRate ); ENV().Bind( "game.stamina_consume_rate", &GameRule::fStaminaConsumeRate ); ENV().Bind( "game.stamina_regen_rate", &GameRule::fStaminaRegenRate ); ENV().Bind( "game.super_save_bonus_rate", &GameRule::fSuperSaveBonusRate ); ENV().Bind( "game.super_save_level_min_limit_0", &GameRule::anSuperSaveLevelMinLimit[ 0 ] ); ENV().Bind( "game.super_save_level_min_limit_1", &GameRule::anSuperSaveLevelMinLimit[ 1 ] ); ENV().Bind( "game.super_save_level_min_limit_2", &GameRule::anSuperSaveLevelMinLimit[ 2 ] ); ENV().Bind( "game.super_save_level_min_limit_3", &GameRule::anSuperSaveLevelMinLimit[ 3 ] ); ENV().Bind( "game.super_save_level_min_limit_4", &GameRule::anSuperSaveLevelMinLimit[ 4 ] ); ENV().Bind( "game.super_save_level_min_limit_5", &GameRule::anSuperSaveLevelMinLimit[ 5 ] ); ENV().Bind( "game.super_save_level_min_limit_6", &GameRule::anSuperSaveLevelMinLimit[ 6 ] ); ENV().Bind( "game.super_save_level_max_limit_0", &GameRule::anSuperSaveLevelMaxLimit[ 0 ] ); ENV().Bind( "game.super_save_level_max_limit_1", &GameRule::anSuperSaveLevelMaxLimit[ 1 ] ); ENV().Bind( "game.super_save_level_max_limit_2", &GameRule::anSuperSaveLevelMaxLimit[ 2 ] ); ENV().Bind( "game.super_save_level_max_limit_3", &GameRule::anSuperSaveLevelMaxLimit[ 3 ] ); ENV().Bind( "game.super_save_level_max_limit_4", &GameRule::anSuperSaveLevelMaxLimit[ 4 ] ); ENV().Bind( "game.super_save_level_max_limit_5", &GameRule::anSuperSaveLevelMaxLimit[ 5 ] ); ENV().Bind( "game.super_save_level_max_limit_6", &GameRule::anSuperSaveLevelMaxLimit[ 6 ] ); ENV().Bind( "game.ally_pcbang_bonus_rate", &GameRule::fAllyPCBangBonusRate ); ENV().Bind( "game.ally_pcbang_chaos_bonus_rate", &GameRule::fAllyPCBangChaosBonusRate ); ENV().Bind( "game.premium_pcbang_bonus_rate", &GameRule::fPremiumPCBangBonusRate ); ENV().Bind( "game.premium_pcbang_chaos_bonus_rate", &GameRule::fPremiumPCBangChaosBonusRate ); ENV().Bind( "game.premium_pcbang_gold_bonus_drop_rate", &GameRule::fPremiumPCBangGoldBonusDropRate ); ENV().Bind( "game.premium_pcbang_item_bonus_drop_rate", &GameRule::fPremiumPCBangItemBonusDropRate ); ENV().Bind( "game.premium_pcbang_chaos_bonus_drop_rate", &GameRule::fPremiumPCBangChaosBonusDropRate ); ENV().Bind( "game.apply_stamina_bonus_in_premium_pcbang", &GameRule::bApplyStaminaBonusInPremiumPCBang ); ENV().Bind( "game.use_play_point", &GameRule::bUsePlayPoint ); ENV().Bind( "game.play_point_accumulate_term", &GameRule::nPlayPointAccumulateTerm ); ENV().Bind( "game.play_point_accumulate_amount", &GameRule::nPlayPointAccumulateAmount ); ENV().Bind( "game.premium_pcbang_play_point_bonus_rate", &GameRule::fPremiumPCBangPlayPointBonusRate ); ENV().Bind( "game.use_time_based_event_script", &GameRule::bUseTimeBasedEventScript ); ENV().Bind( "game.use_time_based_event_db", &GameRule::bUseTimeBasedEventDB ); ENV().Bind( "game.term_for_time_based_event_script", &GameRule::nTermForTimeBasedEventScript ); ENV().Bind( "game.term_for_time_based_event_db", &GameRule::nTermForTimeBasedEventDB ); ENV().Bind( "game.monster_wandering", &GameRule::bMonsterWandering ); ENV().Bind( "game.monster_collision_line", &GameRule::bMonsterCollisionToLine ); ENV().Bind( "game.monster_pathfinding", &GameRule::bMonsterPathFinding ); ENV().Bind( "game.log_monster_pathfinding", &GameRule::bLogMonsterPathFinding ); extern volatile LONG g_nMobLineCount; extern volatile LONG g_nMobPathFindingCount; extern volatile LONG g_nMobFindDuplicatePos; extern volatile LONG g_nMobRandomMove; extern volatile LONG g_nMobFirstLineCount; ENV().Bind( "game.LineCount", (int*) &g_nMobLineCount ); ENV().Bind( "game.PathFindingCount", (int*) &g_nMobPathFindingCount ); ENV().Bind( "game.FindDuplicatePos", (int*) &g_nMobFindDuplicatePos ); ENV().Bind( "game.RandomMove", (int*) &g_nMobRandomMove ); ENV().Bind( "game.FirstLineCount", (int*) &g_nMobFirstLineCount ); ENV().Bind( "game.TracingGamePerformance", (bool*) &g_bPerformanceTracing ); ENV().Bind( "game.GamePerformanceLogingInterval", (int*) &g_nIntervalTimeToLogPerformance ); ENV().Bind( "game.log_scheduling_status", &GameRule::bLogSchedulingStatus ); ENV().Bind( "game.ProcessingPlayerCount", (int*) &g_PlayerPerformanceTracker.m_count ); ENV().Bind( "game.ProcessingSummonCount", (int*) &g_SummonPerformanceTracker.m_count ); ENV().Bind( "game.ProcessingMonsterCount", (int*) &g_MonsterPerformanceTracker.m_count ); ENV().Bind( "game.ProcessingPlayerTime", (int*) &g_PlayerPerformanceTracker.m_totalTime ); ENV().Bind( "game.ProcessingSummonTime", (int*) &g_SummonPerformanceTracker.m_totalTime ); ENV().Bind( "game.ProcessingMonsterTime", (int*) &g_MonsterPerformanceTracker.m_totalTime ); ENV().Bind( "game.no_skill_cooltime", &GameRule::bIgnoreSkillCoolTime ); ENV().Bind( "game.PKServer", &GameRule::bIsPKServer ); ENV().Bind( "game.PKPenaltyLevel", &GameRule::nPKPenaltyLevel ); ENV().Bind( "game.disable_pk_on", &GameRule::bDisablePKOn ); ENV().Bind( "game.AdultServer", &GameRule::bIsAdultServer ); ENV().Bind( "game.restrict_special_char", &GameRule::bRestrictSpeicialChar ); ENV().Bind( "game.allowed_special_char", &GameRule::strAllowedSpecialChar ); ENV().Bind( "game.AutoOpenOnly", &GameRule::bAutoOpen ); ENV().Bind( "game.disable_huntaholic", &GameRule::bDisableHuntaholic ); ENV().Bind( "game.use_auto_jail", &GameRule::bUseAutoJail ); ENV().Bind( "game.security_solution_type", &GameRule::nSecuritySolutionType ); ENV().Bind( "game.period_of_security_solution_check", (int *)&GameRule::nPeriodOfSecuritySolutionCheck ); ENV().Bind( "game.security_solution_response_timeout", (int *)&GameRule::nSecuritySolutionResponseTimeout ); ENV().Bind( "game.security_solution_exceptional_ip", &GameRule::strSecuritySolutionExceptionalIP ); ENV().Bind( "game.disable_dungeon_raid_siege", &GameRule::bDisableDungeonRaidSiege ); ENV().Bind( "game.cash_usable_server", &GameRule::bIsCashUsableServer ); ENV().Bind( "game.use_account_authority_db", &GameRule::bUseAccountAuthorityDB ); ENV().Bind( "game.cash_item_dropable", &GameRule::bCashItemDropable ); ENV().Bind( "game.use_auto_trap", &GameRule::bUseAutoTrap ); ENV().Bind( "game.max_level", &GameRule::nMaxLevel ); ENV().Bind( "game.max_creature_level", &GameRule::nMaxCreatureLevel); ENV().Bind( "game.base_ethereal_durability_consumption_on_normal_attack", &GameRule::nEtherealDurabilityBaseConsumptionOnNormalAttack ); ENV().Bind( "game.base_ethereal_durability_consumption_on_skill_attack", &GameRule::nEtherealDurabilityBaseConsumptionOnSkillAttack ); ENV().Bind( "game.base_ethereal_durability_consumption_on_damage", &GameRule::nEtherealDurabilityBaseConsumptionOnDamage ); ENV().Bind( "game.base_ethereal_durability_consumption_rate", &GameRule::nEtherealDurabilityConsumptionRate ); ENV().Bind( "game.broadcast_event_item_pickup", &GameRule::bBroadcastEventItemPickup ); ENV().Bind( "game.use_guild_donation_point", &GameRule::bUseGuildDonationPoint ); ENV().Bind( "game.restrict_banword_for_booth", &GameRule::bRestrictBanWordForBooth ); ENV().Bind( "game.min_booth_startable_level", &GameRule::nMinBoothStartableLevel ); ENV().Bind( "game.limit_booth_openable_layer_to_zero", &GameRule::bLimitBoothOpenableLayerToZero ); ENV().Bind( "game.disable_buy_booth", &GameRule::bDisableBuyBooth ); ENV().Bind( "game.disable_booth", &GameRule::bDisableBooth ); ENV().Bind( "game.disable_trade", &GameRule::bDisableTrade ); ENV().Bind( "game.limit_adv_chat_count", &GameRule::bLimitAdvChatCount ); ENV().Bind( "game.min_global_chat_usable_level", &GameRule::nMinGlobalChatUsableLevel ); ENV().Bind( "game.max_storage_item_count", &GameRule::nMaxStorageItemCount ); ENV().Bind( "game.max_characters_per_account", &GameRule::nMaxCharactersPerAccount ); ENV().Bind( "game.auction_search_request_min_interval", (int *)&GameRule::nAuctionSearchRequestMinInterval ); ENV().Bind( "game.auction_process_request_min_interval", (int *)&GameRule::nAuctionProcessRequestMinInterval ); ENV().Bind( "game.use_security", &GameRule::bUseSecurityNo ); ENV().Bind( "game.use_storage_security", &GameRule::bUseSecurityNoForStorage ); ENV().Bind( "game.use_delete_security", &GameRule::bUseSecurityNoForDeletingCharacter ); ENV().Bind( "game.check_storage_security_always", &GameRule::bCheckStorageSecurityAlways ); ENV().Bind( "game.limit_field_logout", &GameRule::bLimitFieldLogout ); ENV().Bind( "game.logout_timer", (int *)&GameRule::nLogoutTimer ); ENV().Bind( "game.force_unregister_account_on_kick_fail", &GameRule::bForceUnregisterAccountOnKickFail ); ENV().Bind( "game.forbidden_script_init", &GameRule::bForbiddenScriptInitialized ); ENV().Bind( "game.forbidden_script", &GameRule::strForbiddenScript ); ENV().Bind( "game.use_login_logout_debug", &GameRule::bUseLoginLogoutDebug ); ENV().Bind( "game.log_vulcanus_dungeon", &GameRule::bLogVulcanusDungeon ); ENV().Bind( "game.limit_game_time" , &GameRule::bLimitGameTime ); ENV().Bind( "game.max_game_time_limited_age" , &GameRule::nMaxGameTimeLimitedAge ); ENV().Bind( "game.max_healthy_game_time" , (int *)&GameRule::nMaxHealthyGameTime ); ENV().Bind( "game.max_tired_game_time" , (int *)&GameRule::nMaxTiredGameTime ); ENV().Bind( "game.log_required_state_list", &GameRule::strLogRequiredStateList ); ENV().Bind( "game.log_required_item_list", &GameRule::strLogRequiredItemList ); ENV().Bind( "game.farm_normal_summon_exp", &GameRule::nFarmNormalSummonEXP ); ENV().Bind( "game.farm_growth_summon_exp", &GameRule::nFarmGrowthSummonEXP ); ENV().Bind( "game.farm_evolve_summon_exp", &GameRule::nFarmEvolveSummonEXP ); ENV().Bind( "game.premium_farm_normal_summon_exp", &GameRule::nPremiumFarmNormalSummonEXP ); ENV().Bind( "game.premium_farm_growth_summon_exp", &GameRule::nPremiumFarmGrowthSummonEXP ); ENV().Bind( "game.premium_farm_evolve_summon_exp", &GameRule::nPremiumFarmEvolveSummonEXP ); extern volatile LONG g_nDropRespawn; extern volatile LONG g_nRespawnObjectCnt; extern volatile LONG g_nRespawnCnt; extern volatile LONG g_nRespawnTryCnt; extern volatile int g_nCurrentLocalFlag; extern volatile int g_bUseLockDelayLogging; extern volatile int g_bIgnoreRandomDamage; ENV().Bind( "game.monster_drop_respawn", (int *) &g_nDropRespawn ); ENV().Bind( "game.monster_respawn_object_cnt", (int *) &g_nRespawnObjectCnt ); ENV().Bind( "game.monster_respawn_cnt", (int *) &g_nRespawnCnt ); ENV().Bind( "game.monster_respawn_try_cnt", (int *) &g_nRespawnTryCnt ); ENV().Bind( "game.local_flag", (int *) &g_nCurrentLocalFlag ); ENV().Bind( "game.bUseLockDelayLogging", (int *) &g_bUseLockDelayLogging ); ENV().Bind( "game.ignore_random_damage", (int *) &g_bIgnoreRandomDamage ); ENV().Bind( "memory.player_heap_size", GetPlayerHeapSize ); ENV().Bind( "memory.monster_heap_size", GetMonsterHeapSize ); ENV().Bind( "memory.item_heap_size", GetItemHeapSize ); ENV().Bind( "memory.summon_heap_size", GetSummonHeapSize ); ENV().Bind( "game.HardcoreServer", &GameRule::bHardcore ); ENV().Bind( "game.HardcoreServerXPRate", &GameRule::fHardcoreExpRate ); ENV().Bind( "game.boss_effect", &GameRule::nBossEffect ); ENV().Bind( "game.killed_drop", &GameRule::fKilledDrop ); ENV().Bind( "game.crime_state", &GameRule::nCrimeState ); ENV().Bind( "game.crime_party", &GameRule::nCrimeParty ); ENV().Bind( "game.killed_exp_percentage", &GameRule::fKilledExpPercentage ); ENV().Bind( "game.kill_immoral_percentage", &GameRule::fKillImmoralPercentage ); ENV().Bind( "game.monster_regen_boss", &GameRule::fMonsterRegenBoss ); ENV().Bind( "game.monster_regen", &GameRule::fMonsterRegen ); ENV().Bind( "game.summon_exp_limit", &GameRule::fSummonExpLimit ); ENV().Bind( "game.summon_exp_penalty_level", &GameRule::nSummonExpPenaltyLevel ); ENV().Bind( "game.exception_arabic", &GameRule::nException_AR ); ENV().Bind( "game.exception_31109", &GameRule::fException_31109 ); ENV().Bind( "game.exception_31309", &GameRule::fException_31309 ); ENV().Bind( "game.stamina_consume_rate", &GameRule::fStaminaConsumeRate ); ENV().Bind( "game.stamina_regen_rate", &GameRule::fStaminaRegenRate ); ENV().Bind( "game.lak_guard", &GameRule::bIsLakGuard ); ENV().Bind( "game.forgotten_stamina_bonus_rate", &GameRule::fForgottenStaminaBonusRate ); ENV().Bind( "game.forgotten_stamina_consume_rate", &GameRule::fForgottenStaminaConsumeRate ); ENV().Bind( "game.item_expert_cube", &GameRule::nItemExpertCube ); ENV().Bind( "game.item_expert_grade", &GameRule::nItemExpertGrade ); ENV().Bind( "game.guild_buff_minute", &GameRule::nGuildBuffMinute ); // Guild buff duration ENV().Bind( "game.guild_donate_gold", &GameRule::nGuildDonateGold ); // Basic price for donation for guild ENV().Bind( "game.direct_inventory_loot", &GameRule::bDirectInventoryLoot); // Direct loot ENV().Bind( "game.item_durability_switch", &GameRule::bItemDurabilitySwitch); // Credits to AziaMafia: Durability consumption switch ENV().Bind( "game.playerkiller_bonus_rate", &GameRule::fPlayerKillerBonusRate); // AziaMafia TODO:Check this shit } void InitLua() { // Init Lua VM _cprint( "LUA initialize... " ); if( LuaVM::Inst()->Init() ) { _cprint( "ok\n" ); FILELOG( "LUA initialize... ok" ); } else { _cprint( "Failed\n" ); FILELOG( "LUA initialize... failed" ); } LUA()->RegisterFunction( "insert_item", SCRIPT_InsertItem ); LUA()->RegisterFunction( "insert_item_target", SCRIPT_InsertItemTarget ); LUA()->RegisterFunction( "insert_item_near", SCRIPT_InsertItemNear ); //TODO LUA()->RegisterFunction( "insert_item_all", SCRIPT_InsertItemAll ); //TODO LUA()->RegisterFunction( "delete_item", SCRIPT_DeleteItem ); LUA()->RegisterFunction( "putoff_item", SCRIPT_PutoffItem ); LUA()->RegisterFunction( "puton_item", SCRIPT_PutonItem); LUA()->RegisterFunction( "putoff_skillcard", SCRIPT_Putoffskillcard); LUA()->RegisterFunction( "puton_skillcard", SCRIPT_Putonskillcard); LUA()->RegisterFunction( "get_wear_item_handle_creature", SCRIPT_GetWearItemHandleCreature); LUA()->RegisterFunction( "get_item_weartype", SCRIPT_GetItemWearType); LUA()->RegisterFunction( "get_item_group", SCRIPT_GetItemGroup); LUA()->RegisterFunction( "get_item_list", SCRIPT_GetItemList); LUA()->RegisterFunction( "get_item_list_group", SCRIPT_GetItemList_Group); LUA()->RegisterFunction( "get_summon_id_by_monster_id", SCRIPT_GetSummonIDByMonsterID); LUA()->RegisterFunction( "get_summon_name_code", SCRIPT_GetSummonNameCode); LUA()->RegisterFunction( "get_main_summon", SCRIPT_GetMainSummon); LUA()->RegisterFunction( "get_sub_summon", SCRIPT_GetSubSummon); LUA()->RegisterFunction( "is_erasable_item", SCRIPT_IsErasableItem ); LUA()->RegisterFunction( "find_item", SCRIPT_FindItem ); LUA()->RegisterFunction( "drop_item", SCRIPT_DropItem ); LUA()->RegisterFunction( "drop_gold", SCRIPT_DropGold ); LUA()->RegisterFunction( "insert_gold", SCRIPT_InsertGold ); LUA()->RegisterFunction( "has_item", SCRIPT_HasItem ); LUA()->RegisterFunction( "get_item_handle", SCRIPT_GetItemHandle ); LUA()->RegisterFunction( "get_item_handle_list", SCRIPT_GetItemHandleList ); LUA()->RegisterFunction( "get_item_name", SCRIPT_GetItemName ); LUA()->RegisterFunction( "get_item_code", SCRIPT_GetItemCode ); LUA()->RegisterFunction( "get_item_count", SCRIPT_GetItemCount ); LUA()->RegisterFunction( "get_item_level", SCRIPT_GetItemLevel ); LUA()->RegisterFunction( "set_item_level", SCRIPT_SetItemLevel ); LUA()->RegisterFunction( "get_item_level", SCRIPT_GetItemLevel ); LUA()->RegisterFunction( "set_item_enhance", SCRIPT_SetItemEnhance ); LUA()->RegisterFunction( "set_item_enhance_fail", SCRIPT_SetItemEnhanceFail ); LUA()->RegisterFunction( "get_item_enhance", SCRIPT_GetItemEnhance ); LUA()->RegisterFunction( "get_item_grade", SCRIPT_GetItemGrade ); LUA()->RegisterFunction( "get_item_rank", SCRIPT_GetItemRank ); LUA()->RegisterFunction( "get_item_price", SCRIPT_GetItemPrice ); LUA()->RegisterFunction( "get_item_endurance", SCRIPT_GetItemEndurance ); LUA()->RegisterFunction( "set_item_endurance", SCRIPT_SetItemEndurance ); LUA()->RegisterFunction( "get_socket_info", SCRIPT_GetItemSocketCode ); LUA()->RegisterFunction( "set_socket_info", SCRIPT_SetItemSocketCode ); LUA()->RegisterFunction( "set_item_element", SCRIPT_SetItemElement ); LUA()->RegisterFunction( "set_item_element_parameter", SCRIPT_SetItemElementParameter ); LUA()->RegisterFunction( "get_item_name_by_code", SCRIPT_ItemName ); LUA()->RegisterFunction( "get_item_name_id", SCRIPT_GetItemNameId ); LUA()->RegisterFunction( "get_wear_item_handle", SCRIPT_GetWearItemHandle ); LUA()->RegisterFunction( "get_item_appearance_code",SCRIPT_GetItemAppearanceCode ); LUA()->RegisterFunction( "set_item_appearance_code",SCRIPT_SetItemAppearanceCode ); LUA()->RegisterFunction( "get_item_in_belt", SCRIPT_GetItemInBelt ); LUA()->RegisterFunction( "insert_awaken", SCRIPT_InsertAwakenOption ); LUA()->RegisterFunction( "delete_awaken", SCRIPT_DeleteAwakenOption ); LUA()->RegisterFunction( "identify_item", SCRIPT_IdentifyItemForRandomOption ); LUA()->RegisterFunction( "insert_summon_by_summon_id", SCRIPT_InsertSummonBySummonID ); LUA()->RegisterFunction( "insert_summon_by_monster_id", SCRIPT_InsertSummonByMonsterID ); LUA()->RegisterFunction( "change_item_code", SCRIPT_ChangeItemCode ); LUA()->RegisterFunction( "get_item_random_option", SCRIPT_GetItemIdentifiedOption ); LUA()->RegisterFunction( "get_item_awaken_option", SCRIPT_GetAwakenOption); LUA()->RegisterFunction( "set_item_awaken_option", SCRIPT_SetItemAwakenOption); LUA()->RegisterFunction( "set_item_random_option", SCRIPT_SetItemIdentifiedOption ); LUA()->RegisterFunction( "pick_item_in_drop_group", SCRIPT_PickItemInDropGroup ); LUA()->RegisterFunction( "donate_item", SCRIPT_DonateItem ); // 에테리얼 내구도 관련 LUA()->RegisterFunction( "get_item_ethereal_durability", SCRIPT_GetItemEtherealDurability ); LUA()->RegisterFunction( "set_item_ethereal_durability", SCRIPT_SetItemEtherealDurability ); LUA()->RegisterFunction( "get_max_item_ethereal_durability", SCRIPT_GetMaxItemEtherealDurability ); // 소울스톤 관련 LUA()->RegisterFunction( "show_soulstone_craft_window", SCRIPT_ShowSoulStoneCraftWindow ); LUA()->RegisterFunction( "get_item_soulstone_endurance", SCRIPT_GetItemSoulStoneEndurance ); LUA()->RegisterFunction( "get_max_item_soulstone_endurance", SCRIPT_GetMaxItemSoulStoneEndurance ); LUA()->RegisterFunction( "show_soulstone_repair_window", SCRIPT_ShowSoulStoneRepairWindow ); // 아이템 드랍 이벤트 관련 LUA()->RegisterFunction( "refresh_event_drop", SCRIPT_RefreshEventDropInfo ); LUA()->RegisterFunction( "start_event_drop", SCRIPT_StartEventDrop ); LUA()->RegisterFunction( "stop_event_drop", SCRIPT_StopEventDrop ); LUA()->RegisterFunction( "show_event_drop", SCRIPT_ShowEventDrop ); LUA()->RegisterFunction( "update_event_drop", SCRIPT_UpdateEventDrop ); LUA()->RegisterFunction( "insert_event_drop", SCRIPT_InsertEventDrop ); // 던전 드랍율 이벤트 관련 LUA()->RegisterFunction( "start_event_dungeon_droprate", SCRIPT_StartEventDungeonDroprate ); LUA()->RegisterFunction( "stop_event_dungeon_droprate", SCRIPT_StopEventDungeonDroprate ); LUA()->RegisterFunction( "refresh_event_dungeon_droprate", SCRIPT_RefreshEventDungeonDroprate ); // 아이템 지급 이벤트 관련 LUA()->RegisterFunction( "event_supply", SCRIPT_EventSupply ); LUA()->RegisterFunction( "refresh_event_supply", SCRIPT_RefreshEventSupplyInfo ); LUA()->RegisterFunction( "start_event_supply", SCRIPT_StartEventSupply ); LUA()->RegisterFunction( "stop_event_supply", SCRIPT_StopEventSupply ); LUA()->RegisterFunction( "supply_event_item", SCRIPT_SupplyEventItem ); // 프로퍼티 관련 LUA()->RegisterFunction( "get_target_value", SCRIPT_GetTargetValue ); LUA()->RegisterFunction( "gtv", SCRIPT_GetTargetValue ); LUA()->RegisterFunction( "get_handle_value", SCRIPT_GetHandleValue ); LUA()->RegisterFunction( "ghv", SCRIPT_GetHandleValue ); LUA()->RegisterFunction( "get_value", SCRIPT_GetValue ); LUA()->RegisterFunction( "add_value", SCRIPT_AddValue ); LUA()->RegisterFunction( "add_exp_jp", SCRIPT_AddExpJP ); LUA()->RegisterFunction( "get_exp_require", SCRIPT_GetExpRequire); LUA()->RegisterFunction( "set_value", SCRIPT_SetValue ); LUA()->RegisterFunction( "echo_value", SCRIPT_EchoValue ); LUA()->RegisterFunction( "gv", SCRIPT_GetValue ); LUA()->RegisterFunction( "av", SCRIPT_AddValue ); LUA()->RegisterFunction( "sv", SCRIPT_SetValue ); LUA()->RegisterFunction( "ev", SCRIPT_EchoValue ); LUA()->RegisterFunction( "get_all_value", SCRIPT_GetAllValue ); LUA()->RegisterFunction( "set_creature_value", SCRIPT_SetCreatureValue ); LUA()->RegisterFunction( "get_creature_value", SCRIPT_GetCreatureValue ); LUA()->RegisterFunction( "change_creature_name", SCRIPT_ChangeCreatureName ); LUA()->RegisterFunction( "scv", SCRIPT_SetCreatureValue ); LUA()->RegisterFunction( "smcv", SCRIPT_SetMainCreatureValue ); LUA()->RegisterFunction( "gcv", SCRIPT_GetCreatureValue ); LUA()->RegisterFunction( "gmcv", SCRIPT_GetMainCreatureValue ); LUA()->RegisterFunction( "emcv", SCRIPT_EchoMainCreatureValue); // 플레이어 플래그 관련 LUA()->RegisterFunction( "get_flag", SCRIPT_GetPlayerFlag ); LUA()->RegisterFunction( "set_flag", SCRIPT_SetPlayerFlag ); LUA()->RegisterFunction( "del_flag", SCRIPT_RemovePlayerFlag ); // 계정 플래그 관련 LUA()->RegisterFunction( "get_account_flag", SCRIPT_GetAccountFlag ); LUA()->RegisterFunction( "set_account_flag", SCRIPT_SetAccountFlag ); LUA()->RegisterFunction( "del_account_flag", SCRIPT_RemoveAccountFlag ); // 대기시간 없이 PK 모드 변경 LUA()->RegisterFunction( "set_pk_mode", SCRIPT_SetPKMode ); // 길드 연합 관련 LUA()->RegisterFunction( "is_alliance_leader", SCRIPT_IsAllianceLeader ); LUA()->RegisterFunction( "increase_max_alliance_member_count", SCRIPT_IncreaseMaxAllianceMemberCount ); LUA()->RegisterFunction( "get_max_alliance_member_count", SCRIPT_GetMaxAllianceMemberCount ); // NPC 대화 및 퀘스트 관련 LUA()->RegisterFunction( "dlg_title", SCRIPT_DialogTitle ); LUA()->RegisterFunction( "dlg_text", SCRIPT_DialogText ); LUA()->RegisterFunction( "dlg_menu", SCRIPT_DialogMenu ); LUA()->RegisterFunction( "dlg_show", SCRIPT_DialogShow ); LUA()->RegisterFunction( "quest_text_without_quest_menu", SCRIPT_QuestTextWithoutQuest); LUA()->RegisterFunction( "dlg_text_without_quest_menu", SCRIPT_DialogTextWithoutQuest); LUA()->RegisterFunction( "start_quest", SCRIPT_StartQuest ); LUA()->RegisterFunction( "force_start_quest", SCRIPT_ForceStartQuest ); LUA()->RegisterFunction( "add_pending_quest", SCRIPT_AddPendingQuest ); LUA()->RegisterFunction( "end_quest", SCRIPT_EndQuest ); LUA()->RegisterFunction( "drop_quest", SCRIPT_DropQuest ); LUA()->RegisterFunction( "quest_info", SCRIPT_QuestInfo ); LUA()->RegisterFunction( "show_quest_info_without_npc", SCRIPT_ShowQuestInfoWithoutNPC ); LUA()->RegisterFunction( "get_quest_progress", SCRIPT_GetQuestProgress ); LUA()->RegisterFunction( "get_quest_status", SCRIPT_GetQuestStatus ); LUA()->RegisterFunction( "set_quest_status", SCRIPT_SetQuestStatus ); LUA()->RegisterFunction( "get_last_accept_quest", SCRIPT_GetLastAcceptQuest ); LUA()->RegisterFunction( "reset_finished_quest", SCRIPT_ResetFinishedQuest ); // 다이얼로그 관련 LUA()->RegisterFunction( "dlg_general", SCRIPT_DialogGeneral ); LUA()->RegisterFunction( "dlg_special", SCRIPT_DialogSpecial ); LUA()->RegisterFunction( "dlg_special_menu", SCRIPT_SpecialMenu ); LUA()->RegisterFunction( "dlg_number", SCRIPT_DialogNumber ); LUA()->RegisterFunction( "kick", SCRIPT_Kick ); LUA()->RegisterFunction( "force_unregister_account", SCRIPT_ForceUnregisterAccount ); LUA()->RegisterFunction( "env", SCRIPT_GetEnv ); LUA()->RegisterFunction( "add_npc", SCRIPT_AddMonster ); LUA()->RegisterFunction( "add_monster", SCRIPT_AddMonster2 ); LUA()->RegisterFunction( "set_home", SCRIPT_SetHome ); LUA()->RegisterFunction( "add_instance_dungeon_monster", SCRIPT_AddInstanceDungeonMonster ); LUA()->RegisterFunction( "add_npc_to_world", SCRIPT_AddNPC ); LUA()->RegisterFunction( "add_field_prop", SCRIPT_AddFieldProp ); LUA()->RegisterFunction( "remove_field_prop", SCRIPT_RemoveFieldProp ); LUA()->RegisterFunction( "respawn", SCRIPT_AddRespawnInfo ); LUA()->RegisterFunction( "respawn_guardian", SCRIPT_AddDungeonGuardianRespawnInfo ); LUA()->RegisterFunction( "respawn_environmental_guardian", SCRIPT_AddDungeonEnvironmentalGuardianRespawnInfo ); LUA()->RegisterFunction( "respawn_rare_mob", SCRIPT_AddRareMobRespawnInfo ); LUA()->RegisterFunction( "respawn_roaming_mob", SCRIPT_AddRoamingMobRespawnInfo ); LUA()->RegisterFunction( "raid_respawn", SCRIPT_AddRaidRespawnInfo ); LUA()->RegisterFunction( "raid_respawn_rare_mob", SCRIPT_AddRaidRareMobRespawnInfo); // 몬스터 랜덤 리젠 LUA()->RegisterFunction( "set_random_respawn", SCRIPT_SetRandomRespawnInfo ); LUA()->RegisterFunction( "add_random_area", SCRIPT_AddRandomAreaInfo ); LUA()->RegisterFunction( "add_random_monster", SCRIPT_AddRandomMonster ); // 랜덤 몬스터 그룹 LUA()->RegisterFunction( "add_random_monster_group", SCRIPT_AddRandomMonsterGroup ); LUA()->RegisterFunction( "kill", SCRIPT_Kill ); LUA()->RegisterFunction( "kill_target", SCRIPT_KillTarget ); // 시스템 날짜와 시간 관련 함수 LUA()->RegisterFunction( "get_os_time", SCRIPT_LuaSTDLib_Time ); LUA()->RegisterFunction( "get_os_date", SCRIPT_LuaSTDLib_Date ); LUA()->RegisterFunction( "get_os_second", SCRIPT_GetOsSecond ); LUA()->RegisterFunction( "get_minute", SCRIPT_GetMinute ); LUA()->RegisterFunction( "notice", SCRIPT_Notice ); LUA()->RegisterFunction( "private_notice", SCRIPT_PrivateNotice ); LUA()->RegisterFunction( "announce", SCRIPT_Announce ); LUA()->RegisterFunction( "whisper", SCRIPT_Whisper ); LUA()->RegisterFunction( "warp", SCRIPT_Warp ); LUA()->RegisterFunction( "force_warp", SCRIPT_ForceWarp ); LUA()->RegisterFunction( "recall_player", SCRIPT_RecallPlayer ); LUA()->RegisterFunction( "is_in_siege_dungeon", SCRIPT_IsInSiegeDungeon ); LUA()->RegisterFunction( "respawn_guardian_object", SCRIPT_RespawnGuardian ); LUA()->RegisterFunction( "show_dungeon_stone", SCRIPT_ShowDungeonStone ); LUA()->RegisterFunction( "change_tactical_position_owner", SCRIPT_ChangeTacticalPositionOwner ); LUA()->RegisterFunction( "request_dungeon_raid", SCRIPT_RequestDungeonRaid ); LUA()->RegisterFunction( "cancel_dungeon_raid", SCRIPT_CancelDungeonRaid ); // 숨겨진 던전 LUA()->RegisterFunction( "enter_secret_dungeon", SCRIPT_EnterSecretDungeon ); LUA()->RegisterFunction( "warp_to_secret_dungeon", SCRIPT_WarpToSecretDungeon ); // 인스턴스 던전 LUA()->RegisterFunction( "enter_instance_dungeon", SCRIPT_EnterInstanceDungeon ); LUA()->RegisterFunction( "enter_other_instance_dungeon", SCRIPT_EnterOtherInstanceDungeon); LUA()->RegisterFunction( "warp_to_instance_dungeon", SCRIPT_WarpToInstanceDungeon ); LUA()->RegisterFunction( "leave_instance_dungeon", SCRIPT_LeaveInstanceDungeon ); LUA()->RegisterFunction( "quit_instance_dungeon", SCRIPT_QuitInstanceDungeon ); LUA()->RegisterFunction( "get_instance_dungeon_id", SCRIPT_GetInstanceDungeonID ); LUA()->RegisterFunction( "get_instance_dungeon_type_id", SCRIPT_GetInstanceDungeonTypeID ); LUA()->RegisterFunction( "set_instance_dungeon_flag", SCRIPT_SetInstanceDungeonFlag ); LUA()->RegisterFunction( "get_instance_dungeon_flag", SCRIPT_GetInstanceDungeonFlag ); LUA()->RegisterFunction( "get_alive_instance_respawn_group_monster_count", SCRIPT_GetAliveInstanceRespawnGroupMonsterCount ); LUA()->RegisterFunction( "do_each_player_in_instance_dungeon", SCRIPT_DoEachPlayerInInstanceDungeon ); // 인스턴스 던전 미션 관련(인던 진행상황 표시용 UI - 미션 UI라고 지칭함) // * 미션에 관련된 데이터를 서버가 따로 보관하지는 않으며 InstanceDungeonFlag를 이용해서 스크립트에서 데이터를 관리하며 // 유저에게 방송만 함으로써 UI 갱신만 시켜주는 것으로, 데이터의 세팅/값 확인 등의 함수 없이 방송 함수만 있음 LUA()->RegisterFunction( "send_mission_title", SCRIPT_SendMissionTitle ); LUA()->RegisterFunction( "send_mission_reward", SCRIPT_SendMissionReward ); LUA()->RegisterFunction( "send_mission_objective", SCRIPT_SendMissionObjective ); LUA()->RegisterFunction( "send_mission_objective_progress", SCRIPT_SendMissionObjectiveProgress ); LUA()->RegisterFunction( "broadcast_mission_title", SCRIPT_BroadcastMissionTitle ); LUA()->RegisterFunction( "broadcast_mission_reward", SCRIPT_BroadcastMissionReward ); LUA()->RegisterFunction( "broadcast_mission_objective", SCRIPT_BroadcastMissionObjective ); LUA()->RegisterFunction( "broadcast_mission_objective_progress", SCRIPT_BroadcastMissionObjectiveProgress ); LUA()->RegisterFunction( "broadcast_notice", SCRIPT_BroadcastNotice ); // 배틀 아레나 관련 LUA()->RegisterFunction( "activate_battle_arena_prop", SCRIPT_ActivateBattleArenaProp ); LUA()->RegisterFunction( "set_battle_arena_instance_flag", SCRIPT_SetBattleArenaInstanceFlag ); LUA()->RegisterFunction( "get_battle_arena_instance_flag", SCRIPT_GetBattleArenaInstanceFlag ); LUA()->RegisterFunction( "do_each_player_in_battle_arena_instance", SCRIPT_DoEachPlayerInBattleArenaInstance ); LUA()->RegisterFunction( "do_each_player_in_battle_arena_team", SCRIPT_DoEachPlayerInBattleArenaTeam ); LUA()->RegisterFunction( "get_battle_arena_block_time", SCRIPT_GetBattleArenaBlockTime ); LUA()->RegisterFunction( "set_battle_arena_block_time", SCRIPT_SetBattleArenaBlockTime ); LUA()->RegisterFunction( "get_battle_arena_penalty_count", SCRIPT_GetBattleArenaPenaltyCount ); LUA()->RegisterFunction( "set_battle_arena_penalty_count", SCRIPT_SetBattleArenaPenaltyCount ); LUA()->RegisterFunction( "get_battle_arena_next_penalty_dec_time", SCRIPT_GetBattleArenaNextPenaltyDecTime ); LUA()->RegisterFunction( "set_battle_arena_next_penalty_dec_time", SCRIPT_SetBattleArenaNextPenaltyDecTime ); LUA()->RegisterFunction( "get_battle_arena_team_no", SCRIPT_GetBattleArenaTeamNo ); LUA()->RegisterFunction( "set_secroute_free_pass", SCRIPT_SetSecrouteFreePass ); LUA()->RegisterFunction( "set_chat_block_time", SCRIPT_SetChatBlockTime ); LUA()->RegisterFunction( "set_invisible", SCRIPT_SetInvisible ); LUA()->RegisterFunction( "rebirth", SCRIPT_Rebirth ); LUA()->RegisterFunction( "set_level", SCRIPT_SetLevel ); LUA()->RegisterFunction( "heal", SCRIPT_Heal ); LUA()->RegisterFunction( "enter_dungeon", SCRIPT_WarpToDungeon ); LUA()->RegisterFunction( "warp_to_stored_position", SCRIPT_WarpToStoredPosition ); LUA()->RegisterFunction( "begin_dungeon_raid", SCRIPT_BeginDungeonRaid ); LUA()->RegisterFunction( "drop_dungeon_owner_ship", SCRIPT_DropDungeonOwnership ); LUA()->RegisterFunction( "change_dungeon_owner", SCRIPT_ChangeDungeonOwner ); LUA()->RegisterFunction( "clear_dungeon_core_guardian", SCRIPT_ClearDungeonCoreGuardian ); LUA()->RegisterFunction( "get_own_dungeon_id", SCRIPT_GetOwnDungeonID ); LUA()->RegisterFunction( "get_siege_dungeon_id", SCRIPT_GetSiegeDungeonID ); LUA()->RegisterFunction( "stat", SCRIPT_Stat ); LUA()->RegisterFunction( "setspeed", SCRIPT_SetSpeed ); LUA()->RegisterFunction( "saveall", SCRIPT_SaveAllPlayer ); LUA()->RegisterFunction( "shutdown", SCRIPT_Shutdown ); LUA()->RegisterFunction( "delete_block_account", SCRIPT_DeleteFromBlockAccount ); LUA()->RegisterFunction( "save", SCRIPT_SavePlayer ); LUA()->RegisterFunction( "respawn_near_monster", SCRIPT_RespawnNearMonster); LUA()->RegisterFunction( "monster_skill_cast", SCRIPT_MonsterSkillCast ); LUA()->RegisterFunction( "get_monster_skill_target_position", SCRIPT_GetMonsterSkillTargetPosition ); LUA()->RegisterFunction( "set_monster_skill_target_position", SCRIPT_SetMonsterSkillTargetPosition ); LUA()->RegisterFunction( "set_next_attackable_time", SCRIPT_SetNextAttackableTime ); LUA()->RegisterFunction( "get_monster_id", SCRIPT_GetMonsterID ); LUA()->RegisterFunction( "get_monster_info", SCRIPT_GetMonsterInfo); LUA()->RegisterFunction( "get_monster_info_handle", SCRIPT_GetMonsterInfo_byHandle); LUA()->RegisterFunction( "db_trace_dump", SCRIPT_DBTraceDump ); LUA()->RegisterFunction( "force_monster_proc_dead", SCRIPT_ForceMonsterProcDead ); LUA()->RegisterFunction( "open_market", SCRIPT_ShowMarket ); LUA()->RegisterFunction( "gametime", SCRIPT_GetGameTime ); LUA()->RegisterFunction( "refresh", SCRIPT_Reload ); LUA()->RegisterFunction( "learn_skill", SCRIPT_LearnSkill ); LUA()->RegisterFunction( "learn_all_skill", SCRIPT_LearnAllSkill ); LUA()->RegisterFunction( "learn_all_skill_no_levelup", SCRIPT_LearnAllSkill_no_levelup); LUA()->RegisterFunction( "learn_creature_all_skill",SCRIPT_LearnCreatureAllSkill); LUA()->RegisterFunction( "reset_skill", SCRIPT_ResetSkill ); LUA()->RegisterFunction( "set_job", SCRIPT_SetJob ); LUA()->RegisterFunction( "reset_job", SCRIPT_ResetJob ); LUA()->RegisterFunction( "set_race", SCRIPT_SetRace ); LUA()->RegisterFunction( "get_base_skill_level", SCRIPT_GetBaseSkillLevel ); LUA()->RegisterFunction( "get_cur_skill_level", SCRIPT_GetCurSkillLevel); LUA()->RegisterFunction( "get_cur_skill_enchant", SCRIPT_GetCurSkillEnchant); LUA()->RegisterFunction( "show_creature_dialog", SCRIPT_ShowCreatureDialog ); LUA()->RegisterFunction( "sconv", SCRIPT_Conv ); LUA()->RegisterFunction( "message", SCRIPT_Message ); LUA()->RegisterFunction( "is_changeable_job", SCRIPT_IsChangeableJob ); LUA()->RegisterFunction( "add_state", SCRIPT_AddState ); LUA()->RegisterFunction( "get_state_time", SCRIPT_GetStateTime); LUA()->RegisterFunction( "get_state_level", SCRIPT_GetStateLevel ); LUA()->RegisterFunction( "remove_state", SCRIPT_RemoveState ); LUA()->RegisterFunction( "add_cstate", SCRIPT_AddCreatureState ); LUA()->RegisterFunction( "remove_cstate", SCRIPT_RemoveCreatureState ); LUA()->RegisterFunction( "add_event_state", SCRIPT_AddEventState ); LUA()->RegisterFunction( "remove_event_state", SCRIPT_RemoveEventState ); LUA()->RegisterFunction( "clear_event_state", SCRIPT_ClearEventState ); LUA()->RegisterFunction( "get_event_state_list", SCRIPT_GetEventStateList ); LUA()->RegisterFunction( "cast_world_state", SCRIPT_CastWorldState ); LUA()->RegisterFunction( "set_env", SCRIPT_SetEnv ); LUA()->RegisterFunction( "get_env", SCRIPT_GetEnv ); LUA()->RegisterFunction( "set_global_variable", SCRIPT_SetGlobalVariable ); LUA()->RegisterFunction( "get_global_variable", SCRIPT_GetGlobalVariable ); LUA()->RegisterFunction( "del_global_variable", SCRIPT_DeleteGlobalVariable ); LUA()->RegisterFunction( "sgv", SCRIPT_SetGlobalVariable ); LUA()->RegisterFunction( "ggv", SCRIPT_GetGlobalVariable ); LUA()->RegisterFunction( "dgv", SCRIPT_DeleteGlobalVariable ); //LUA()->RegisterFunction( "revival_summon", SCRIPT_ResurrectSummon ); LUA()->RegisterFunction( "get_string", SCRIPT_GetString ); LUA()->RegisterFunction( "get_creature_handle", SCRIPT_GetCreatureHandle ); LUA()->RegisterFunction( "open_storage", SCRIPT_ShowStorage ); LUA()->RegisterFunction( "get_user_count_near", SCRIPT_GetUserCountNear ); LUA()->RegisterFunction( "create_guild", SCRIPT_CreateGuild ); LUA()->RegisterFunction( "destroy_guild", SCRIPT_DestroyGuild ); LUA()->RegisterFunction( "show_guild_create", SCRIPT_ShowCreateGuild ); LUA()->RegisterFunction( "show_alliance_create", SCRIPT_ShowCreateAlliance ); LUA()->RegisterFunction( "force_change_guild_name", SCRIPT_ForceChangeGuildName ); LUA()->RegisterFunction( "force_promote_guild_leader", SCRIPT_ForcePromoteGuildLeader ); LUA()->RegisterFunction( "check_valid_guild_name", SCRIPT_CheckValidGuildName ); LUA()->RegisterFunction( "create_alliance", SCRIPT_CreateAlliance ); LUA()->RegisterFunction( "destroy_alliance", SCRIPT_DestroyAlliance ); LUA()->RegisterFunction( "check_valid_alliance_name", SCRIPT_CheckValidAllianceName ); LUA()->RegisterFunction( "get_npc_id", SCRIPT_GetNPCId ); LUA()->RegisterFunction( "get_npc_handle", SCRIPT_GetNPCHandle ); LUA()->RegisterFunction( "get_npc_type", SCRIPT_GetNPCType ); LUA()->RegisterFunction( "get_npc_name", SCRIPT_GetNPCName ); LUA()->RegisterFunction( "show_npc", SCRIPT_ShowNPC ); LUA()->RegisterFunction( "creature_evolution", SCRIPT_CreatureEvolution ); LUA()->RegisterFunction( "creature_enhance", SCRIPT_CreatureEnhance ); LUA()->RegisterFunction( "call_lc_In", SCRIPT_SetCurrentLocationId ); LUA()->RegisterFunction( "creature_learn_skill", SCRIPT_CreatureLearnSkill ); LUA()->RegisterFunction( "get_proper_channel_num", SCRIPT_GetProperChannelNo ); LUA()->RegisterFunction( "get_min_channel_num", SCRIPT_GetMinChannelNo ); LUA()->RegisterFunction( "get_max_channel_num", SCRIPT_GetMaxChannelNo ); LUA()->RegisterFunction( "get_user_count_in_channel",SCRIPT_GetUserCountInChannel); LUA()->RegisterFunction( "get_layer_of_channel", SCRIPT_GetLayerOfChannel ); LUA()->RegisterFunction( "get_summon_name_id", SCRIPT_GetSummonNameId ); LUA()->RegisterFunction( "equip_summon_card", SCRIPT_EquipSummonCard ); LUA()->RegisterFunction( "show_channel_set", SCRIPT_ShowChannelSet ); LUA()->RegisterFunction( "update_guild_info", SCRIPT_UpdateGuildInfo ); LUA()->RegisterFunction( "update_guild_banner_info", SCRIPT_UpdateGuildBannerInfo ); LUA()->RegisterFunction( "is_guild_leader", SCRIPT_IsGuildLeader ); LUA()->RegisterFunction( "set_guild_block_time", SCRIPT_SetGuildBlockTime ); LUA()->RegisterFunction( "get_guild_block_time", SCRIPT_GetGuildBlockTime ); LUA()->RegisterFunction( "get_guild_name", SCRIPT_GetGuildName ); LUA()->RegisterFunction( "get_own_guild_name", SCRIPT_GetOwnGuildName ); LUA()->RegisterFunction( "get_dungeon_relation", SCRIPT_GetDungeonRelation ); LUA()->RegisterFunction( "get_tax_rate", SCRIPT_GetTaxRate ); LUA()->RegisterFunction( "set_tax_rate", SCRIPT_SetTaxRate ); LUA()->RegisterFunction( "get_tax_amount", SCRIPT_GetTaxAmount ); LUA()->RegisterFunction( "get_tax_chaos_amount", SCRIPT_GetTaxChaosAmount ); LUA()->RegisterFunction( "draw_tax", SCRIPT_DrawTax ); LUA()->RegisterFunction( "draw_tax_chaos", SCRIPT_DrawTaxChaos ); #ifndef _USE_NEW_ROAMING_ONLY LUA()->RegisterFunction( "add_way_point", SCRIPT_AddWayPoint ); LUA()->RegisterFunction( "set_way_point_type", SCRIPT_SetWayPointType ); LUA()->RegisterFunction( "set_way_point_speed", SCRIPT_SetWayPointSpeed ); #endif LUA()->RegisterFunction( "recall_feather", SCRIPT_RecallFeather ); LUA()->RegisterFunction( "warp_to_exit_position", SCRIPT_WarpToExitPosition ); LUA()->RegisterFunction( "warp_to_revive_position", SCRIPT_WarpToRevivePosition ); LUA()->RegisterFunction( "get_server_category", SCRIPT_GetServerCategory ); LUA()->RegisterFunction( "find_npc", SCRIPT_FindNPC ); LUA()->RegisterFunction( "set_auto_user", SCRIPT_SetAutoUser ); LUA()->RegisterFunction( "set_auto_account", SCRIPT_SetAutoAccount ); LUA()->RegisterFunction( "clear_auto_account", SCRIPT_ClearAutoAccount ); LUA()->RegisterFunction( "open_url", SCRIPT_OpenUrl ); LUA()->RegisterFunction( "open_popup", SCRIPT_OpenPopup ); LUA()->RegisterFunction( "open_popup_and_set_size", SCRIPT_OpenPopupAndSetSize ); LUA()->RegisterFunction( "get_local_info", SCRIPT_GetLocalInfo ); LUA()->RegisterFunction( "update_gold_chaos", SCRIPT_SendGoldChaosUpdate ); LUA()->RegisterFunction( "show_donation_prop", SCRIPT_ShowDonationMenu ); LUA()->RegisterFunction( "set_pcbang_user", SCRIPT_SetPCBangUser ); LUA()->RegisterFunction( "set_continuous_play_time", SCRIPT_SetContinuousPlayTime ); // NPC에 의한 소환수 이름 변경 기능 관련 LUA()->RegisterFunction( "get_creature_name_id", SCRIPT_GetCreatureNameID ); LUA()->RegisterFunction( "creature_name_change_box", SCRIPT_ShowCreatureNameChangeBox ); // NPC에 의한 소환수 스킬 초기화 기능 관련 LUA()->RegisterFunction( "reset_summon_skill", SCRIPT_ResetSummonSkill ); // NPC에 의한 소환수 농장 기능 관련 LUA()->RegisterFunction( "show_creature_farm_window", SCRIPT_ShowCreatureFarmWindow ); LUA()->RegisterFunction( "get_summon_list", SCRIPT_GetSummonList ); LUA()->RegisterFunction( "get_farmed_summon_list", SCRIPT_GetFarmedSummonList ); LUA()->RegisterFunction( "get_farmed_summon_count", SCRIPT_GetFarmedSummonCount ); LUA()->RegisterFunction( "get_farmed_summon_value", SCRIPT_GetFarmedSummonValue ); LUA()->RegisterFunction( "get_farmed_summon_level", SCRIPT_GetFarmedSummonLevel ); LUA()->RegisterFunction( "get_summon_rate", SCRIPT_GetSummonRate ); LUA()->RegisterFunction( "farm_summon", SCRIPT_FarmSummon ); LUA()->RegisterFunction( "regain_summon", SCRIPT_RegainSummon ); LUA()->RegisterFunction( "nurse_summon", SCRIPT_NurseSummon ); // 호칭 관련 LUA()->RegisterFunction( "open_title", SCRIPT_OpenTitle ); LUA()->RegisterFunction( "achieve_title", SCRIPT_AchieveTitle ); LUA()->RegisterFunction( "get_main_title", SCRIPT_GetMainTitle ); LUA()->RegisterFunction( "set_main_title", SCRIPT_SetMainTitle ); LUA()->RegisterFunction( "get_sub_title", SCRIPT_GetSubTitle ); LUA()->RegisterFunction( "set_sub_title", SCRIPT_SetSubTitle ); LUA()->RegisterFunction( "update_title_condition", SCRIPT_UpdateTitleCondition ); LUA()->RegisterFunction( "set_remain_title_time", SCRIPT_SetRemainTitleTime ); // 경매 관련 LUA()->RegisterFunction( "show_auction_window", SCRIPT_ShowAuctionWindow ); LUA()->RegisterFunction( "cancel_auction_by_seller", SCRIPT_CancelAuctionBySeller ); // 헌터홀릭 관련 LUA()->RegisterFunction( "show_huntaholic_lobby_window", SCRIPT_ShowHuntaholicLobbyWindow ); LUA()->RegisterFunction( "set_huntaholic_point", SCRIPT_SetHuntaholicPoint ); // 이벤트 영역 진입 횟수 기록 관련 LUA()->RegisterFunction( "get_event_area_enter_count", SCRIPT_GetEventAreaEnterCount ); LUA()->RegisterFunction( "set_event_area_enter_count", SCRIPT_SetEventAreaEnterCount ); // 서버 강제 덤프 생성 후 종료(카운트 및 유저 정보 저장 처리 없음) LUA()->RegisterFunction( "suicide", SCRIPT_Suicide ); // ScheduledCommandManager priority 설정 함수 LUA()->RegisterFunction( "set_scheduled_command_manager_priority", SCRIPT_SetScheduledCommandManagerPriority ); // 인벤토리 아이템 삭제 (GM 본인 인벤토리 아이템 삭제) LUA()->RegisterFunction( "clear_inventory", SCRIPT_ClearInventory ); // 계정 관련 LUA()->RegisterFunction( "set_account_authority", SCRIPT_SetAccountAuthority ); LUA()->RegisterFunction( "update_wear", SCRIPT_UpdateWear ); LUA()->RegisterFunction( "do_each_player_in_party", SCRIPT_DoEachPlayerInParty ); LUA()->RegisterFunction( "do_each_player_in_guild", SCRIPT_DoEachPlayerInGuild ); LUA()->RegisterFunction( "do_each_player_in_world", SCRIPT_DoEachPlayerInWorld ); LUA()->RegisterFunction( "do_player", SCRIPT_DoPlayer ); LUA()->RegisterFunction( "set_item_flag", SCRIPT_SetItemFlag); LUA()->RegisterFunction( "get_item_flag", SCRIPT_GetItemFlag); LUA()->RegisterFunction( "awaken_item_rdm", SCRIPT_AwakenItemForRandomOption); LUA()->RegisterFunction( "exec_smp", SCRIPT_Exec_Smp); // Fraun stored procedures execution from lua 8/17/2025 LUA()->RegisterFunction( "re_identify_item", SCRIPT_Re_IdentifyItemForRandomOption); LUA()->RegisterFunction( "ispartyleader", SCRIPT_ispartyleader); LUA()->RegisterFunction( "partycount", SCRIPT_partycount); LUA()->RegisterFunction( "loc_id", SCRIPT_loc_id); LUA()->RegisterFunction( "creature_item_card_handle", SCRIPT_CreatureItemCardHandle); // Fraun 7/12/2025 new functions LUA()->RegisterFunction("get_server_time", SCRIPT_GetServerTime); LUA()->RegisterFunction("get_location_id", SCRIPT_GetLocationID); LUA()->RegisterFunction("get_location_type", SCRIPT_GetLocationType); LUA()->RegisterFunction("get_item_class", SCRIPT_GetItemClass); LUA()->RegisterFunction("get_awakening", SCRIPT_GetAwakening); LUA()->RegisterFunction("set_specific_awaken", SCRIPT_SetSpecificAwakening); StructSummon::BindProperty(); StructPlayer::BindProperty(); StructMonster::BindProperty(); // 출력방향 설정 LUA()->BindLogOutputFunction( ScriptLog ); } bool _HerlockIntf::onInit( HWND hWnd ) { SetWindowText( hWnd, ENV().GetString( "app.name", "Rappelz Server" ).c_str() ); FileLogHandler::Init(); g_DBTracker.init(); // init COM CoInitialize(NULL); // init random srand( GetArTime() ); // init network _cprint( "Network initialize... " ); if( XNetworkUtil::InitNetwork() ) { _cprint( "ok\n" ); FILELOG( "Network initialize... ok" ); } else { _cprint( "Failed\n" ); FILELOG( "Network initialize... failed" ); } void InitNetwork(); InitNetwork(); // init script InitLua(); if( !XSecuritySolutionManager::Instance().Init() ) { return true; } unsigned id; HANDLE hThread; hThread = reinterpret_cast( _beginthreadex( NULL, 0, initFunc, NULL, 0, &id ) ); CloseHandle( hThread ); b_performanceUpdate = true; hThread = reinterpret_cast( _beginthreadex( NULL, 0, performanceLogFunc, NULL, 0, &id ) ); CloseHandle( hThread ); // set timer SetTimer( ArcadiaFrameworkIntf::GetViewWindow(), 0, 100, NULL ); // init log LOG::Init( ENV().GetString( "app.name", "CA Game Server" ).c_str() ); LOG::Log11N4S( LM_SERVER_INFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, "", 0, "", 0, "START", LOG::STR_NTS ); return true; } bool _HerlockIntf::onDeInit() { LOG::Log11N4S( LM_SERVER_INFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, "", 0, "", 0, "END", LOG::STR_NTS ); KillTimer( ArcadiaFrameworkIntf::GetViewWindow(), 0 ); int nShutdownState = ShutdownManager::Instance().m_nShutdownState; if( !( nShutdownState & ShutdownManager::SDS_WRAPUP_COMPLETE ) ) { _lprint( "GameLog.txt", "onDeInit is called with SDS 0x%08X.\n", nShutdownState ); } b_performanceUpdate = false; g_DBTracker.dump(); void DeInitGame(); DeInitGame(); //LUA()->DeInitThread(); LUA()->DeInit(); LOG::DeInit(); FileLogHandler::DeInit(); return true; } bool _HerlockIntf::onKeyDown( int nVkCode ) { return false; } void _HerlockIntf::onDrawUser( HDC dc ) { static DWORD dwPrevTime = timeGetTime() - 1000; if( dwPrevTime + 1000 < timeGetTime() ) { void Draw(); Draw(); dwPrevTime = timeGetTime(); InvalidateRect( GetViewWindow(), NULL, false ); } } bool _HerlockIntf::onMessage( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { if( msg == WM_TIMER ) { static bool bLoadingComplete = false; if( !bLoadingComplete && ENV().GetString( "game.loading" ) == "complete" ) { bLoadingComplete = true; extern IStreamSocketConnection * g_pAuthConnection; if( !g_pAuthConnection || !g_pAuthConnection->IsConnected() ) { if( !ConnectToAuth() ) { _cprint( "Connecting to the auth server failed. Check auth server status. IP:%s / PORT:%d\n", ENV().GetString( "io.auth.ip", "127.0.0.1" ).c_str(), ENV().GetInt( "io.auth.port", 4502 ) ); _cprint( "Enter 'connect auth' to retry.\n" ); FILELOG( "Connecting to the auth server failed. Check auth server status. IP:%s / PORT:%d", ENV().GetString( "io.auth.ip", "127.0.0.1" ).c_str(), ENV().GetInt( "io.auth.port", 4502 ) ); ENV().Remove( "game.loading" ); bLoadingComplete = false; return true; } } void SendGameServerLoginToAuth( const char * szServerName, const char * szServerScreenshotUrl, unsigned short nServerIdx, const char * szServerIP, int nServerPort ); SendGameServerLoginToAuth( ENV().GetString( "auth.server_name", "LeviathanServer" ).c_str(), ENV().GetString( "game.server_screenshot_url", "about:blank" ).c_str(), ENV().GetInt( "auth.server_idx", 1 ), ENV().GetString( "io.ip_address", "192.168.0.84" ).c_str(), ENV().GetInt( "io.port", 4514 ) ); while( 1 ) { std::string strAuthConnectState = ENV().GetString( "auth.connect", "" ); if( strAuthConnectState.empty() ) Sleep( 1 ); else if( strAuthConnectState == "complete" ) break; else if( strAuthConnectState == "failed" ) { _cprint( "Registering this server to auth server with idx %d is failed.\n", ENV().GetInt( "auth.server_idx", 1 ) ); _cprint( "Enter 'connect auth' to retry.\n" ); FILELOG( "Registering this server to auth server with idx %d is failed.", ENV().GetInt( "auth.server_idx", 1 ) ); ENV().Remove( "game.loading" ); ENV().Remove( "auth.connect" ); bLoadingComplete = false; return true; } } std::string strUploadConnectState = ENV().GetString( "upload.connect", "" ); if( strUploadConnectState.empty() ) { ENV().Set( "upload.connect", "failed" ); ConnectToUpload(); } StartAccept(); // 접속을 받기 시작한 이후에 ScheduledCommand 실행을 시작 ScheduledCommandManager::Instance().Init(); } #ifdef _MEM_USAGE_DEBUG static DWORD dwPrevTime = GetTickCount(); DWORD dwCurrentTime = GetTickCount(); if( ENV().GetInt( "game.mem_usage_info_save_interval" ) && dwPrevTime + ENV().GetInt( "game.mem_usage_info_save_interval" ) < dwCurrentTime ) { dwPrevTime = dwCurrentTime; XSEH::WriteAllocCountInfo( "MemUsageInfo.txt" ); HANDLE hFile = INVALID_HANDLE_VALUE; if ( (hFile = CreateFile( "MemUsageInfo.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) != INVALID_HANDLE_VALUE ) { SetFilePointer( hFile, 0, NULL, FILE_END ); WriteHeapUsageInfo( hFile ); CloseHandle( hFile ); } } #endif } if( GetViewMode() == ArcadiaFrameworkIntf::VIEW_USER ) { if( msg == WM_PAINT || msg == WM_TIMER ) { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); onDrawUser( hdc ); EndPaint( hWnd, &ps ); return true; } } if( GetViewMode() == ArcadiaFrameworkIntf::VIEW_LOG ) { if( msg == WM_TIMER ) { static DWORD dwPrevTime = GetTickCount(); if( GetTickCount() > dwPrevTime + 200 ) { dwPrevTime = GetTickCount(); InvalidateRect( hWnd, NULL, false ); } return true; } if( msg == WM_PAINT ) { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); onDrawLog( hdc ); EndPaint( hWnd, &ps ); return true; } } return false; } struct _ProfilerScreenOutput { _ProfilerScreenOutput( ArcadiaCommandResultReceiver * pReceiver ) { m_pReceiver = pReceiver; } void operator()( const char * szString, ... ) { char p[2048]; va_list ap; va_start(ap, szString); s_vsprintf(p, _countof(p), szString, ap); va_end(ap); std::string str = p; XStringUtil::Replace( str, "%", "%%" ); m_pReceiver->onWrite( str.c_str() ); } ArcadiaCommandResultReceiver * m_pReceiver; }; struct _ProfilerFileOutput { _ProfilerFileOutput( const char* szFileName ) { fp = NULL; fopen_s( &fp, szFileName, "a+" ); } ~_ProfilerFileOutput() { if( fp ) fclose( fp ); } void operator()( const char * szString, ... ) { char p[2048]; va_list ap; va_start(ap, szString); s_vsprintf(p, _countof(p), szString, ap); va_end(ap); if( fp ) fwrite( p, 1, strlen(p), fp ); } FILE *fp; }; bool _HerlockIntf::onCommand( const char* szTarget, const char* szFrom, const char *szFullCmd, std::vector< std::string > & vList, ArcadiaCommandResultReceiver & receiver ) { LOG::Log11N4S( LM_CHEAT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, szTarget, LOG::STR_NTS, szFrom, LOG::STR_NTS, "", LOG::STR_NTS, szFullCmd, LOG::STR_NTS ); if( !_stricmp( szFullCmd, "view" ) ) { return true; } else if( szFullCmd[0] == '#' ) { std::string strCmd = &szFullCmd[1]; XStringUtil::Trim( strCmd ); if( strCmd.size() > GameRule::CHAT_MAX_LENGTH ) { receiver.onWrite( "The submitted message is too long. (Limit is %u characters.)\n", GameRule::CHAT_MAX_LENGTH ); return false; } std::string strResult; LuaVM::GlobalInst()->RunString( strCmd.c_str(), &strResult ); if( !strResult.empty() && strResult != "nil" ) receiver.onWrite( strResult.c_str() ); return true; } else if( !_stricmp( vList[0].c_str(), "lua_do" ) ) { if( vList.size() > 1 ) { std::string strCmd = vList[1]; XStringUtil::Trim( strCmd ); if( strCmd.size() > GameRule::CHAT_MAX_LENGTH ) { receiver.onWrite( "The submitted message is too long. (Limit is %u characters.)\n", GameRule::CHAT_MAX_LENGTH ); return false; } std::string strResult; LuaVM::GlobalInst()->RunString( strCmd.c_str(), &strResult ); if( !strResult.empty() && strResult != "nil" ) receiver.onWrite( strResult.c_str() ); return true; } } else if( !_stricmp( vList[0].c_str(), "lua_run" ) ) { if( vList.size() > 1 ) { std::string strCmd = vList[1]; XStringUtil::Trim( strCmd ); LuaVM::GlobalInst()->LoadScript( strCmd.c_str(), true ); return true; } } else if( !_stricmp( vList[0].c_str(), "erase_auto" ) ) { if( vList.size() > 1 ) { StructPlayer::EraseFromAutoAccount( atoi( vList[1].c_str() ) ); } return true; } else if( !_stricmp( vList[0].c_str(), "connect" ) ) { if( vList.size() > 1 ) { if( vList[1] == "auth" ) { if( ENV().GetString( "game.loading" ) == "complete" || ENV().GetString( "auth.connect" ) == "complete" ) receiver.onWrite( "Already once connected to auth server.\n" ); else ENV().Set( "game.loading", "complete" ); } else if( vList[1] == "upload" ) { ConnectToUpload(); } } return true; } else if( !_stricmp( vList[0].c_str(), "show_process_usage" ) ) { receiver.onWrite( " - Network Processing Info - \n" ); auto it = g_NetworkReceiverPerformanceTracker.m_data.begin(); for( ; it != g_NetworkReceiverPerformanceTracker.m_data.end() ; ++it ) { // 총 처리 시간 1초 미만인 경우 보여주지 않음. if( (*it).second.m_totalTime < 1000 ) continue; receiver.onWrite( "Packet ID[%u] - Count:%u, ElapsedTime:%ums\n", (*it).first, (*it).second.m_count, (*it).second.m_totalTime ); } receiver.onWrite( " - Scheduling Processing Info - \n" ); receiver.onWrite( "Scheduling[Player] - Count:%u, ElapsedTime:%ums\n", g_PlayerPerformanceTracker.m_count, g_PlayerPerformanceTracker.m_totalTime ); receiver.onWrite( "Scheduling[Summon] - Count:%u, ElapsedTime:%ums\n", g_SummonPerformanceTracker.m_count, g_SummonPerformanceTracker.m_totalTime ); receiver.onWrite( "Scheduling[Monster] - Count:%u, ElapsedTime:%ums\n", g_MonsterPerformanceTracker.m_count, g_MonsterPerformanceTracker.m_totalTime ); return true; } return false; } XEnvStruct& CMD() { static XEnvStruct cmd; return cmd; } #define WIN32_LEAN_AND_MEAN #include #include #include #include int TestLinuxConnection() { _cprint("Attempt to test conenction to linux server...\n"); int PORT = 4000; const char* SERVER_HOST = "127.0.0.1"; WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { _cprint("WSAStartup failed\n"); return 1; } // use getaddrinfo to resolve domain -> IP addrinfo hints, *result = nullptr;; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; // force IPv4 (or use AF_UNSPEC for v4/v6) hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; std::string portStr = std::to_string(static_cast(PORT)); int rc = getaddrinfo(SERVER_HOST, portStr.c_str(), &hints, &result); if (rc != 0) { _cprint("getaddrinfo failed: %d\n", rc); WSACleanup(); return 1; } // Create socket ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { _cprint("Error at socket(): %d\n", WSAGetLastError() ); FILELOG("Error at socket(): %d", WSAGetLastError() ); freeaddrinfo(result); WSACleanup(); return 1; } // Connect to first resolved address if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) { _cprint("Unable to connect: %d\n", WSAGetLastError() ); //FILELOG("Unable to connect: %d", WSAGetLastError() ); closesocket(ConnectSocket); freeaddrinfo(result); WSACleanup(); return 1; } freeaddrinfo(result); // Sending a packet with specific string here std::string packet = "HELLO:GAME_SERVER"; send(ConnectSocket, packet.c_str(), (int)packet.size(), 0); _cprint("Sent packet: %s\n", packet.c_str()); //FILELOG("Sent packet: %s", packet.c_str()); // receive response char buffer[1024] = { 0 }; int bytesReceived = recv(ConnectSocket, buffer, sizeof(buffer), 0); if (bytesReceived > 0) { std::string response(buffer, bytesReceived); _cprint("Response: %s\n", response); //FILELOG("Response: %s", response); } else { _cprint("No Responce!\n"); //FILELOG("No Responce!"); return 1; } closesocket(ConnectSocket); WSACleanup(); return 0; } void onInitArcadiaFramework() { // Fraun linux server coordinator 9/23/2025 int nResult = 0; #ifdef FRAUN_COORDINATOR_SERVER nResult = TestLinuxConnection(); #endif if (nResult == 0) { _cprint("[Server start]: Authorized\n"); } else { _cprint("[Server start]: Unauthorized. Exit!\n"); ExitProcess(1); } // init default environment InitDefaultEnv(); // 파일에서 로드 CMD().LoadFromFile( "Commands.opt" ); ENV().LoadFromFile( "GameServer.eop", "*", true ); if(GameRule::bHardcore) { // hardcode server면 pkserver가 되어야한다 GameRule::bIsPKServer = true; GameRule::fHardcoreExpRate = 1.0f; } // Handle concurrent use of GameServer.opt // Only keys specified in game.local_setting_list are used. // The values in game.local_setting_list must be in the format: [type keyName]|[type keyName]|... // Example: game.local_setting_list: N game.max_level|S db.c.server|N db.c.port|S db.user.server|N db.user.port std::string strLocalSettingList = ENV().GetString( "game.local_setting_list", "" ); if( !strLocalSettingList.empty() ) { XEnvStruct envLocalSetting; if( envLocalSetting.LoadFromFile( "GameServer.opt" ) ) { std::vector< std::string > vLocalSetting; XStringUtil::Split( strLocalSettingList.c_str(), vLocalSetting, "|" ); for( std::vector< std::string >::const_iterator it = vLocalSetting.begin() ; it != vLocalSetting.end() ; ++it ) { const char * pszKey = (*it).c_str() + 2; if( !envLocalSetting.IsExist( pszKey ) ) continue; switch( *(*it).c_str() ) { case 'S': ENV().Set( pszKey, envLocalSetting.GetString( pszKey ) ); break; case 'F': ENV().Set( pszKey, envLocalSetting.GetFloat( pszKey ) ); break; case 'V': ENV().Set( pszKey, envLocalSetting.GetVector( pszKey ) ); break; case 'Q': ENV().Set( pszKey, envLocalSetting.GetQuaternion( pszKey ) ); break; case 'N': ENV().Set( pszKey, envLocalSetting.GetInt( pszKey ) ); break; case 'T': ENV().Set( pszKey, (short)envLocalSetting.GetInt( pszKey ) ); break; } } } ENV().Remove( "game.local_setting_list" ); } // 패스워드 삭제 CMD().Remove( "db.billing.account" ); CMD().Remove( "db.billing._password" ); CMD().Remove( "db.c.account" ); CMD().Remove( "db.c._password" ); CMD().Remove( "db.user.account" ); CMD().Remove( "db.user._password" ); ENV().Remove( "db.billing.account" ); ENV().Remove( "db.billing._password" ); ENV().Remove( "db.c.account" ); ENV().Remove( "db.c._password" ); ENV().Remove( "db.user.account" ); ENV().Remove( "db.user._password" ); myFrameworkIntf.SetConsoleEopFileName( "GameServer.eop" ); // 읽기 전용 필드 설정 ENV().SetReadOnly( "game.party_exp_rate" ); ENV().SetReadOnly( "game.no_collision_check" ); ENV().SetReadOnly( "game.disable_dungeon_raid_siege" ); ENV().SetReadOnly( "game.limit_game_time" ); ENV().SetReadOnly( "game.max_healthy_game_time" ); ENV().SetReadOnly( "game.max_tired_game_time" ); ENV().SetReadOnly( "game.log_required_state_list" ); ENV().SetReadOnly( "game.log_required_item_list" ); ENV().SetReadOnly( "game.farm_normal_summon_exp" ); ENV().SetReadOnly( "game.farm_growth_summon_exp" ); ArcadiaFrameworkIntf::SetFrameworkInterface( &myFrameworkIntf ); ArcadiaFrameworkIntf::AddWatchList( "game.server_version" ); ArcadiaFrameworkIntf::AddWatchList( "engine.ar_time" ); ArcadiaFrameworkIntf::AddWatchList( "engine.count_client" ); ArcadiaFrameworkIntf::AddWatchList( "engine.count_movable" ); ArcadiaFrameworkIntf::AddWatchList( "engine.count_static" ); ArcadiaFrameworkIntf::AddWatchList( "game.user_count" ); ArcadiaFrameworkIntf::AddWatchList( "game.item_count" ); ArcadiaFrameworkIntf::AddWatchList( "io.connection" ); ArcadiaFrameworkIntf::AddWatchList( "iocp.dis_count" ); ArcadiaFrameworkIntf::AddWatchList( "io.send_count" ); ArcadiaFrameworkIntf::AddWatchList( "iocp.send_rest_bytes" ); ArcadiaFrameworkIntf::AddWatchList( "iocp.max_alloc_size" ); ArcadiaFrameworkIntf::AddWatchList( "io.recv_count" ); ArcadiaFrameworkIntf::AddWatchList( "db.user.work_active" ); ArcadiaFrameworkIntf::AddWatchList( "db.user.work_pending" ); ArcadiaFrameworkIntf::AddWatchList( "db.user.work_total" ); ArcadiaFrameworkIntf::AddWatchList( "db.user.exec_query" ); ArcadiaFrameworkIntf::AddWatchList( "db.user.remain_query" ); } // 1초마다 서버 전체 성능을 기록 unsigned __stdcall performanceLogFunc( void* ) { while( b_performanceUpdate ) { if( g_bPerformanceTracing ) { // Scheduling Thread 관련 성능 기록 FileLogHandler::GetFileLogHandler()->LogStringToFileEx( NULL, "PerformanceTrackingLog", "%Y-%m-%d.log", "[Scheduling] Player Count[%u] Time[%ums]", g_PlayerPerformanceTracker.m_count, g_PlayerPerformanceTracker.m_totalTime ); FileLogHandler::GetFileLogHandler()->LogStringToFileEx( NULL, "PerformanceTrackingLog", "%Y-%m-%d.log", "[Scheduling] Summon Count[%u] Time[%ums]", g_SummonPerformanceTracker.m_count, g_SummonPerformanceTracker.m_totalTime ); FileLogHandler::GetFileLogHandler()->LogStringToFileEx( NULL, "PerformanceTrackingLog", "%Y-%m-%d.log", "[Scheduling] Monster Count[%u] Time[%ums]", g_MonsterPerformanceTracker.m_count, g_MonsterPerformanceTracker.m_totalTime ); // IOCP 관련 성능 기록 for( auto it = g_NetworkReceiverPerformanceTracker.m_data.begin() ; it != g_NetworkReceiverPerformanceTracker.m_data.end() ; ++it ) { // 최소 0ms 이상 처리한 것들만 찍어준다. if( (*it).second.m_totalTime == 0 ) continue; FileLogHandler::GetFileLogHandler()->LogStringToFileEx( NULL, "PerformanceTrackingLog", "%Y-%m-%d.log", "[IOCP] PacketID[%u] Count[%u] Time[%ums]", (*it).first, (*it).second.m_count, (*it).second.m_totalTime ); } // Thread CPU사용량 관련 기록 // 현재 vWatchingThreadList에 Lock이 없어 쓰레드가 소멸되면 iterator 무효화가 일어날 수 있다.. // 지금은 게임 서버 꺼질 때 말고는 vWatchingThreadList에 삭제 처리를 하지 않는다. 보수해야할 코드. { THREAD_SYNCRONIZE( &XThreadMonitor::xWatchingThreadListCS ); for( auto it = XThreadMonitor::vWatchingThreadList.begin() ; it != XThreadMonitor::vWatchingThreadList.end() ; ++it ) { FileLogHandler::GetFileLogHandler()->LogStringToFileEx( NULL, "PerformanceTrackingLog", "%Y-%m-%d.log", "[Thread] ThreadName[%s] BouncingCount[%u]", (*it).GetThreadName(), (*it).GetBouncingCount() ); } } } // 1초 후에 다시 수행 Sleep( g_nIntervalTimeToLogPerformance ); } return 0; }