Compare commits

...
53 Commits
Author SHA1 Message Date
Hide_D 673b7054aa 자동 로그인 (#196)
자동 로그인 구현

- login_token 테이블
- reqNonce -> loginByToken
- sha512(token + nonce)

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/196
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2021-11-08 04:23:07 +09:00
Hide_D 1472cbf257 game: 장비매매 시 도구 유니크 덮어지지 않게 2021-10-29 02:21:53 +09:00
Hide_D d806935c58 fix: 작위 보상이 군주인 경우 반영이 안되는 버그 수정 2021-10-27 02:04:10 +09:00
Hide_D 6b56eb79e1 fix: 403 페이지 redirect 버그 수정 2021-10-27 01:29:19 +09:00
Hide_D d2aea16744 balance: 초기 +5%, -2% 추가가 2021-10-16 21:50:41 +09:00
Hide_D bb800f032e balance: 쌍무쌍 적용 불가, 무쌍 중반 이후 대폭 너프프 2021-10-16 21:22:28 +09:00
Hide_D 64b9f9443e fix: 랜덤 임관 비중 계산식에서 u장 포함 2021-10-14 02:01:12 +09:00
Hide_D fd2d3a0e06 fix: 창 닫기가 필요한 창은 window.open으로 열어야함 2021-10-14 01:12:21 +09:00
Hide_D 08d678bdb8 fix: CreateManyNPC에서 npcCount가 0이면 fillCnt가 무시 2021-10-14 00:37:08 +09:00
Hide_D 418007e572 balance: 초반 NPC 생성 시 모든 국가를 채울 수 있을 정도로는 제공 2021-10-14 00:36:06 +09:00
Hide_D 4a1bccdf75 balance: 탈취량을 도시 내정치에 기반하도록 변경 2021-10-14 00:16:44 +09:00
Hide_D 00c0b59e9d balance: 랜임 시 의병장, 집합장 카운트는 제외 2021-10-13 02:05:04 +09:00
Hide_D ac82c8ff0b fix(misc): 상대가 치료시 '붉게' 표기 2021-10-13 02:01:41 +09:00
Hide_D f4bef8a090 fix: 인탐, 의병에서 숙련도가 지정되지 않는 버그 수정 2021-10-13 01:56:06 +09:00
Hide_D d8a1055bff fix: DummyGeneral에 유산 관련 포인트 함수가 누락된 부분 수정 2021-10-12 02:25:24 +09:00
Hide_D d672ce4d80 fix: set_error_handler를 못잡는 문제 해결
기타 소소한 버그
- 피장파장 입력시 warning을 계속 일으키는 버그(동작 문제는 없음)
- 토너먼트에서 승리,패배,무승부 외에 MustNotBeReachedException이 throw되지 않음(동작 문제는 없음)
2021-10-12 01:43:54 +09:00
Hide_D 43ec361d03 dep: update phan 2021-10-12 01:36:02 +09:00
Hide_D c3c99c5f76 fix: 공격자 전투력 판정 문제 수정 2021-10-12 01:31:16 +09:00
Hide_D eb1e1421ab fix(misc): phan 2021-10-12 01:30:37 +09:00
Hide_D e8a1d87919 Merge pull request 'balance: 무쌍 너프, NPC 출병 금지 불가' (#195) from balance_210923 into devel
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/195
2021-10-10 13:30:01 +09:00
Hide_D 921ba6811d balance: 무쌍 너프, NPC 출병 금지 불가 2021-09-23 03:59:08 +09:00
Hide_D 906dd241b4 fix: RootDB template 2021-09-23 03:08:49 +09:00
Hide_D 3f0cd2ad64 fix: illuminate 2021-09-21 03:13:07 +09:00
Hide_D 41420d1954 Illuminate: ready. (critical)
- DB에서 illuminate를 가져올 수 있도록 설정
- 업그레이듵 불가, RootDB, DB를 직접 수정해야함
2021-09-21 03:06:42 +09:00
Hide_D 6e5a72b170 fix: 자동 사령턴 조정이 되지 않는 버그 2021-09-19 15:44:49 +09:00
Hide_D 4b19e6aec8 fix: 명예의 전당 검색 2021-09-19 13:38:40 +09:00
Hide_D 58572cbc36 scenario: 쿠키런 킹덤 임시 구현 2021-09-19 03:03:05 +09:00
Hide_D 096d5766bf conf: vue-style-loader에 esbuild-loader적용 2021-09-18 04:53:26 +09:00
Hide_D f5c5b56492 dep: babel-loader + ts-loader => esbuild-loader 2021-09-18 04:31:31 +09:00
Hide_D 69c69d63e6 dep: package upgrade 2021-09-18 03:52:27 +09:00
Hide_D 3fd8b21867 misc: lint warning, 불필요 파일 정리 2021-09-18 03:49:04 +09:00
Hide_D 8660e8cd85 fix: NPC포상 설정 메시지 수정 2021-09-18 03:42:20 +09:00
Hide_D 8458f725f2 fix: 사망 시 유산 포인트 관련 환불/초기화가 없는 문제 2021-09-18 03:36:08 +09:00
Hide_D 366678c965 fix: 장수 생성창 보이기/숨기기, 턴 시간 고정 표기 수정 2021-09-18 02:49:47 +09:00
Hide_D 336b5668db fix & inheritAction: 랜덤 유니크 습득시 환불 가능하게 수정 2021-09-18 00:15:00 +09:00
Hide_D 55886269ea inheritAction: 설문조사에서는 특정 유니크 구입 기능 해제 2021-09-18 00:06:20 +09:00
Hide_D 0b3698595b fix: hash -> gitHash 2021-09-17 23:40:47 +09:00
Hide_D 05e43a39db fix: 턴 초기화, 전특 초기화 표기 방식 변경 2021-09-17 23:37:53 +09:00
Hide_D 5737ad3db2 fix: 턴 초기화, 특기 초기화 포인트 안내가 1스텝 늦음 2021-09-17 23:34:33 +09:00
Hide_D 4ac174eb9a fix: 반계시도에는 구분 코드가 동작하지 않았음 2021-09-17 23:17:13 +09:00
Hide_D 895eec10b4 fix: 비급 반계가 전특 반계와 같이 동작하지 않는 버그 수정 2021-09-17 23:07:45 +09:00
Hide_D e0d891e89a fix: 재야일 때에는 임관 년도 증가하지 않도록 2021-09-17 03:14:14 +09:00
Hide_D adf7734b85 fix: 생성하자마자 임관 1년차로 나오는 문제 수정 2021-09-17 03:12:38 +09:00
Hide_D 5362be9c21 inheritPoint: 로그 기록 2021-09-17 02:39:11 +09:00
Hide_D 847ece52f2 fix: summernote.css 2021-09-16 22:39:19 +09:00
Hide_D 851c59d22c fix: 유저전투장 긴급포상 쌀 2021-09-16 22:37:31 +09:00
Hide_D 0669534bba fix: 궁 유니크 저격 계수 2021-09-16 22:24:29 +09:00
Hide_D 05db47e62a fix: 설문조사에서 환불 불가능한 문제 수정 2021-09-16 22:06:57 +09:00
Hide_D 4a0e608d1c fix: itemTrials 삭제 후 통째로 array가 비면 array도 마저 삭제 2021-09-16 22:00:35 +09:00
Hide_D 45fe73af86 fix: eventColumn에 aux 추가 2021-09-16 21:47:32 +09:00
Hide_D 4d9fcd657f fix: vote에서 aux 2021-09-16 21:43:37 +09:00
Hide_D a057deb0fe fix: 유니크를 얻는 턴이 아니더라도 환불은 하도록 수정 2021-09-16 21:38:43 +09:00
Hide_D 4766210a7d 랜임 실패시 실행 턴. 요양 -> 인탐 2021-09-16 21:24:52 +09:00
1922 changed files with 154303 additions and 4557 deletions
+35 -29
View File
@@ -15,20 +15,34 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer // Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist. // that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options) // (See `backward_compatibility_checks` for additional options)
"target_php_version" => '7.4', "target_php_version" => '8.0',
'backward_compatibility_checks ' => true, 'backward_compatibility_checks ' => true,
'minimum_severity'=>\Phan\Issue::SEVERITY_CRITICAL, 'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
'file_list' => [ 'file_list' => [
'f_config/config.php', 'f_config/config.php',
'hwe/_119_b.php',
'hwe/_119.php',
'hwe/a_bestGeneral.php', 'hwe/a_bestGeneral.php',
'hwe/a_emperior.php', 'hwe/_admin1.php',
'hwe/_admin1_submit.php',
'hwe/_admin2.php',
'hwe/_admin2_submit.php',
'hwe/_admin4.php',
'hwe/_admin4_submit.php',
'hwe/_admin5.php',
'hwe/_admin5_submit.php',
'hwe/_admin7.php',
'hwe/_admin8.php',
'hwe/_admin_force_rehall.php',
'hwe/a_emperior_detail.php', 'hwe/a_emperior_detail.php',
'hwe/a_emperior.php',
'hwe/a_genList.php', 'hwe/a_genList.php',
'hwe/a_hallOfFame.php', 'hwe/a_hallOfFame.php',
'hwe/a_history.php', 'hwe/a_history.php',
'hwe/a_kingdomList.php', 'hwe/a_kingdomList.php',
'hwe/a_npcList.php', 'hwe/a_npcList.php',
'hwe/api.php',
'hwe/a_status.php', 'hwe/a_status.php',
'hwe/a_traffic.php', 'hwe/a_traffic.php',
'hwe/a_vote.php', 'hwe/a_vote.php',
@@ -41,13 +55,11 @@ return [
'hwe/b_dipcenter.php', 'hwe/b_dipcenter.php',
'hwe/b_diplomacy.php', 'hwe/b_diplomacy.php',
'hwe/b_genList.php', 'hwe/b_genList.php',
'hwe/v_inheritPoint.php',
'hwe/b_myBossInfo.php', 'hwe/b_myBossInfo.php',
'hwe/b_myCityInfo.php', 'hwe/b_myCityInfo.php',
'hwe/b_myGenInfo.php', 'hwe/b_myGenInfo.php',
'hwe/b_myKingdomInfo.php', 'hwe/b_myKingdomInfo.php',
'hwe/b_myPage.php', 'hwe/b_myPage.php',
'hwe/b_npc_control.php',
'hwe/b_processing.php', 'hwe/b_processing.php',
'hwe/b_tournament.php', 'hwe/b_tournament.php',
'hwe/b_troop.php', 'hwe/b_troop.php',
@@ -55,7 +67,6 @@ return [
'hwe/c_dipcenter.php', 'hwe/c_dipcenter.php',
'hwe/c_tournament.php', 'hwe/c_tournament.php',
'hwe/c_vote.php', 'hwe/c_vote.php',
'hwe/func.php',
'hwe/func_auction.php', 'hwe/func_auction.php',
'hwe/func_command.php', 'hwe/func_command.php',
'hwe/func_converter.php', 'hwe/func_converter.php',
@@ -64,16 +75,15 @@ return [
'hwe/func_legacy.php', 'hwe/func_legacy.php',
'hwe/func_map.php', 'hwe/func_map.php',
'hwe/func_message.php', 'hwe/func_message.php',
'hwe/func.php',
'hwe/func_process.php', 'hwe/func_process.php',
'hwe/func_string.php', 'hwe/func_string.php',
'hwe/func_template.php', 'hwe/func_template.php',
'hwe/func_time_event.php', 'hwe/func_time_event.php',
'hwe/func_tournament.php', 'hwe/func_tournament.php',
'hwe/index.php', 'hwe/index.php',
'hwe/install.php',
'hwe/install_db.php', 'hwe/install_db.php',
'hwe/join.php', 'hwe/install.php',
'hwe/join_post.php',
'hwe/j_adjust_icon.php', 'hwe/j_adjust_icon.php',
'hwe/j_autoreset.php', 'hwe/j_autoreset.php',
'hwe/j_basic_info.php', 'hwe/j_basic_info.php',
@@ -92,8 +102,8 @@ return [
'hwe/j_general_log_old.php', 'hwe/j_general_log_old.php',
'hwe/j_general_set_permission.php', 'hwe/j_general_set_permission.php',
'hwe/j_general_turn.php', 'hwe/j_general_turn.php',
'hwe/j_getChiefTurn.php',
'hwe/j_get_basic_general_list.php', 'hwe/j_get_basic_general_list.php',
'hwe/j_getChiefTurn.php',
'hwe/j_get_city_list.php', 'hwe/j_get_city_list.php',
'hwe/j_get_general_list.php', 'hwe/j_get_general_list.php',
'hwe/j_get_nation_general_list.php', 'hwe/j_get_nation_general_list.php',
@@ -101,11 +111,12 @@ return [
'hwe/j_get_select_npc_token.php', 'hwe/j_get_select_npc_token.php',
'hwe/j_get_select_pool.php', 'hwe/j_get_select_pool.php',
'hwe/j_image_upload.php', 'hwe/j_image_upload.php',
'hwe/j_install.php',
'hwe/j_install_db.php', 'hwe/j_install_db.php',
'hwe/j_install.php',
'hwe/j_load_scenarios.php', 'hwe/j_load_scenarios.php',
'hwe/j_map.php',
'hwe/j_map_history.php', 'hwe/j_map_history.php',
'hwe/j_map.php',
'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php', 'hwe/j_msg_contact_list.php',
'hwe/j_msg_decide_opt.php', 'hwe/j_msg_decide_opt.php',
'hwe/j_msg_delete.php', 'hwe/j_msg_delete.php',
@@ -123,26 +134,20 @@ return [
'hwe/j_set_npc_control.php', 'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php', 'hwe/j_simulate_battle.php',
'hwe/j_troop.php', 'hwe/j_troop.php',
'hwe/j_update_picked_general.php',
'hwe/j_vacation.php', 'hwe/j_vacation.php',
'hwe/lib.php', 'hwe/lib.php',
'hwe/process_war.php', 'hwe/process_war.php',
'hwe/proc.php',
'hwe/readme.php',
'hwe/recent_map.php',
'hwe/select_general_from_pool.php', 'hwe/select_general_from_pool.php',
'hwe/select_npc.php', 'hwe/select_npc.php',
'hwe/t_board.php',
'hwe/t_diplomacy.php', 'hwe/t_diplomacy.php',
'hwe/_119.php', 'hwe/v_board.php',
'hwe/_119_b.php', 'hwe/v_inheritPoint.php',
'hwe/_admin1.php', 'hwe/v_join.php',
'hwe/_admin1_submit.php', 'hwe/v_NPCControl.php',
'hwe/_admin2.php',
'hwe/_admin2_submit.php',
'hwe/_admin4.php',
'hwe/_admin4_submit.php',
'hwe/_admin5.php',
'hwe/_admin5_submit.php',
'hwe/_admin7.php',
'hwe/_admin8.php',
'hwe/_admin_force_rehall.php',
], ],
// A list of directories that should be parsed for class and // A list of directories that should be parsed for class and
@@ -153,9 +158,9 @@ return [
// Thus, both first-party and third-party code being used by // Thus, both first-party and third-party code being used by
// your application should be included in this list. // your application should be included in this list.
'directory_list' => [ 'directory_list' => [
'hwe/d_setting', 'hwe/d_setting',
'hwe/sammo', 'hwe/sammo',
'd_setting', 'd_setting',
'src/sammo', 'src/sammo',
'src/kakao', 'src/kakao',
'vendor' 'vendor'
@@ -179,6 +184,7 @@ return [
'suppress_issue_types' => [ 'suppress_issue_types' => [
'PhanUnreferencedUseNormal', 'PhanUnreferencedUseNormal',
'PhanTypeArraySuspiciousNullable',
], ],
// A list of plugin files to execute. // A list of plugin files to execute.
+1 -1
View File
@@ -5,7 +5,7 @@
<title>닫혀 있습니다.</title> <title>닫혀 있습니다.</title>
<script> <script>
setTimeout(function(){ setTimeout(function(){
window.location = window.location+'/../'; window.location.href = '../';
}, 5000); }, 5000);
</script> </script>
<style> <style>
+6 -2
View File
@@ -2,7 +2,11 @@
namespace sammo; namespace sammo;
include "lib.php"; require(__DIR__ . '/vendor/autoload.php');
include "func.php";
if (!class_exists('\\sammo\\RootDB')) {
Json::dieWithReason('No DB');
}
APIHelper::launch(dirname(__FILE__)); APIHelper::launch(dirname(__FILE__));
+3 -1
View File
@@ -28,7 +28,9 @@
"catfan/medoo": "^1.5", "catfan/medoo": "^1.5",
"phan/phan": "*", "phan/phan": "*",
"erusev/parsedown-extra": "^0.8.1", "erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0" "nette/caching": "^3.0",
"illuminate/database": "^8.61",
"illuminate/events": "^8.61"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
Generated
+987 -9
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "2aeb036fc53a6fdc343bd2707d4697ee", "content-hash": "317938cff7b30806f4e385a70f4943fc",
"packages": [ "packages": [
{ {
"name": "brandonwamboldt/utilphp", "name": "brandonwamboldt/utilphp",
@@ -265,6 +265,101 @@
], ],
"time": "2021-07-31T17:03:58+00:00" "time": "2021-07-31T17:03:58+00:00"
}, },
{
"name": "doctrine/inflector",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
"reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^7.0",
"phpstan/phpstan": "^0.11",
"phpstan/phpstan-phpunit": "^0.11",
"phpstan/phpstan-strict-rules": "^0.11",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.x"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"time": "2020-05-29T15:13:26+00:00"
},
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
"version": "1.7.4", "version": "1.7.4",
@@ -707,6 +802,497 @@
}, },
"time": "2021-04-26T09:17:50+00:00" "time": "2021-04-26T09:17:50+00:00"
}, },
{
"name": "illuminate/bus",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/bus.git",
"reference": "808097c0dfd893309bd77b00139586c516b965c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/bus/zipball/808097c0dfd893309bd77b00139586c516b965c9",
"reference": "808097c0dfd893309bd77b00139586c516b965c9",
"shasum": ""
},
"require": {
"illuminate/collections": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/pipeline": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"suggest": {
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Bus\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Bus package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-08-10T16:49:48+00:00"
},
{
"name": "illuminate/collections",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/18fa841df912ec56849351dd6ca8928e8a98b69d",
"reference": "18fa841df912ec56849351dd6ca8928e8a98b69d",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"php": "^7.3|^8.0"
},
"suggest": {
"symfony/var-dumper": "Required to use the dump method (^5.1.4)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Collections package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-08T12:48:16+00:00"
},
{
"name": "illuminate/container",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/862b64ea4ab56e307a1676104a1b93295d347ad0",
"reference": "862b64ea4ab56e307a1676104a1b93295d347ad0",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"php": "^7.3|^8.0",
"psr/container": "^1.0"
},
"provide": {
"psr/container-implementation": "1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Container\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Container package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-09T13:55:23+00:00"
},
{
"name": "illuminate/contracts",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
"reference": "ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0",
"psr/container": "^1.0",
"psr/simple-cache": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Contracts\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Contracts package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-08T12:09:40+00:00"
},
{
"name": "illuminate/database",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/database/zipball/acc11d6839ddb3b694bc6585177fa5141b70c693",
"reference": "acc11d6839ddb3b694bc6585177fa5141b70c693",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/collections": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0",
"symfony/console": "^5.1.4"
},
"suggest": {
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"illuminate/console": "Required to use the database commands (^8.0).",
"illuminate/events": "Required to use the observers with Eloquent (^8.0).",
"illuminate/filesystem": "Required to use the migrations (^8.0).",
"illuminate/pagination": "Required to paginate the result set (^8.0).",
"symfony/finder": "Required to use Eloquent model factories (^5.1.4)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Database\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Database package.",
"homepage": "https://laravel.com",
"keywords": [
"database",
"laravel",
"orm",
"sql"
],
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-13T18:43:43+00:00"
},
{
"name": "illuminate/events",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/events/zipball/7def78033f29cd0c0383513b27c291d233a7f90e",
"reference": "7def78033f29cd0c0383513b27c291d233a7f90e",
"shasum": ""
},
"require": {
"illuminate/bus": "^8.0",
"illuminate/collections": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Events\\": ""
},
"files": [
"functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Events package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-08-16T21:45:47+00:00"
},
{
"name": "illuminate/macroable",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/300aa13c086f25116b5f3cde3ca54ff5c822fb05",
"reference": "300aa13c086f25116b5f3cde3ca54ff5c822fb05",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Macroable package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2020-10-27T15:20:30+00:00"
},
{
"name": "illuminate/pipeline",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pipeline.git",
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/pipeline/zipball/23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
"reference": "23aeff5b26ae4aee3f370835c76bd0f4e93f71d2",
"shasum": ""
},
"require": {
"illuminate/contracts": "^8.0",
"illuminate/support": "^8.0",
"php": "^7.3|^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Pipeline\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Pipeline package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-03-26T18:39:16+00:00"
},
{
"name": "illuminate/support",
"version": "v8.61.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
"reference": "b0a21c41163381dd9a5abbd68fe85ed7b4247d30",
"shasum": ""
},
"require": {
"doctrine/inflector": "^1.4|^2.0",
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/collections": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"nesbot/carbon": "^2.31",
"php": "^7.3|^8.0",
"voku/portable-ascii": "^1.4.8"
},
"conflict": {
"tightenco/collect": "<5.5.33"
},
"suggest": {
"illuminate/filesystem": "Required to use the composer class (^8.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0).",
"ramsey/uuid": "Required to use Str::uuid() (^4.0).",
"symfony/process": "Required to use the composer class (^5.1.4).",
"symfony/var-dumper": "Required to use the dd function (^5.1.4).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.2)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-09-13T18:43:43+00:00"
},
{ {
"name": "league/plates", "name": "league/plates",
"version": "v3.4.0", "version": "v3.4.0",
@@ -902,6 +1488,100 @@
], ],
"time": "2021-05-28T08:32:12+00:00" "time": "2021-05-28T08:32:12+00:00"
}, },
{
"name": "nesbot/carbon",
"version": "2.53.1",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f4655858a784988f880c1b8c7feabbf02dfdf045",
"reference": "f4655858a784988f880c1b8c7feabbf02dfdf045",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
"doctrine/orm": "^2.7",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.54",
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"bin": [
"bin/carbon"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-3.x": "3.x-dev",
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
]
},
"phpstan": {
"includes": [
"extension.neon"
]
}
},
"autoload": {
"psr-4": {
"Carbon\\": "src/Carbon/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "https://markido.com"
},
{
"name": "kylekatarnls",
"homepage": "https://github.com/kylekatarnls"
}
],
"description": "An API extension for DateTime that supports 281 different languages.",
"homepage": "https://carbon.nesbot.com",
"keywords": [
"date",
"datetime",
"time"
],
"support": {
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
},
"funding": [
{
"url": "https://opencollective.com/Carbon",
"type": "open_collective"
},
{
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
"type": "tidelift"
}
],
"time": "2021-09-06T09:29:23+00:00"
},
{ {
"name": "netresearch/jsonmapper", "name": "netresearch/jsonmapper",
"version": "v4.0.0", "version": "v4.0.0",
@@ -1206,16 +1886,16 @@
}, },
{ {
"name": "phan/phan", "name": "phan/phan",
"version": "5.0.0", "version": "5.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phan/phan.git", "url": "https://github.com/phan/phan.git",
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90" "reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phan/phan/zipball/f36b6b9a2f4143a25f35ce94d712ceb0527e9d90", "url": "https://api.github.com/repos/phan/phan/zipball/d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90", "reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1232,7 +1912,7 @@
"symfony/console": "^3.2|^4.0|^5.0", "symfony/console": "^3.2|^4.0|^5.0",
"symfony/polyfill-mbstring": "^1.11.0", "symfony/polyfill-mbstring": "^1.11.0",
"symfony/polyfill-php80": "^1.20.0", "symfony/polyfill-php80": "^1.20.0",
"tysonandre/var_representation_polyfill": "^0.0.2" "tysonandre/var_representation_polyfill": "^0.0.2|^0.1.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^8.5.0" "phpunit/phpunit": "^8.5.0"
@@ -1279,9 +1959,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/phan/phan/issues", "issues": "https://github.com/phan/phan/issues",
"source": "https://github.com/phan/phan/tree/5.0.0" "source": "https://github.com/phan/phan/tree/5.2.1"
}, },
"time": "2021-08-01T18:17:28+00:00" "time": "2021-09-15T00:08:40+00:00"
}, },
{ {
"name": "php-extended/php-system", "name": "php-extended/php-system",
@@ -1684,6 +2364,57 @@
}, },
"time": "2021-05-03T11:20:27+00:00" "time": "2021-05-03T11:20:27+00:00"
}, },
{
"name": "psr/simple-cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/master"
},
"time": "2017-10-23T01:57:42+00:00"
},
{ {
"name": "ralouphie/getallheaders", "name": "ralouphie/getallheaders",
"version": "3.0.3", "version": "3.0.3",
@@ -2970,6 +3701,179 @@
], ],
"time": "2021-06-27T11:44:38+00:00" "time": "2021-06-27T11:44:38+00:00"
}, },
{
"name": "symfony/translation",
"version": "v5.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
"reference": "4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation-contracts": "^2.3"
},
"conflict": {
"symfony/config": "<4.4",
"symfony/dependency-injection": "<5.0",
"symfony/http-kernel": "<5.0",
"symfony/twig-bundle": "<5.0",
"symfony/yaml": "<4.4"
},
"provide": {
"symfony/translation-implementation": "2.3"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0",
"symfony/console": "^4.4|^5.0",
"symfony/dependency-injection": "^5.0",
"symfony/finder": "^4.4|^5.0",
"symfony/http-kernel": "^5.0",
"symfony/intl": "^4.4|^5.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/service-contracts": "^1.1.2|^2",
"symfony/yaml": "^4.4|^5.0"
},
"suggest": {
"psr/log-implementation": "To use logging capability in translator",
"symfony/config": "",
"symfony/yaml": ""
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\Translation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.3.7"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-08-26T08:22:53+00:00"
},
{
"name": "symfony/translation-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95",
"shasum": ""
},
"require": {
"php": ">=7.2.5"
},
"suggest": {
"symfony/translation-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Translation\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to translation",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
},
{ {
"name": "tysonandre/var_representation_polyfill", "name": "tysonandre/var_representation_polyfill",
"version": "0.0.2", "version": "0.0.2",
@@ -3080,6 +3984,80 @@
], ],
"time": "2021-07-08T16:18:03+00:00" "time": "2021-07-08T16:18:03+00:00"
}, },
{
"name": "voku/portable-ascii",
"version": "1.5.6",
"source": {
"type": "git",
"url": "https://github.com/voku/portable-ascii.git",
"reference": "80953678b19901e5165c56752d087fc11526017c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/80953678b19901e5165c56752d087fc11526017c",
"reference": "80953678b19901e5165c56752d087fc11526017c",
"shasum": ""
},
"require": {
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
},
"suggest": {
"ext-intl": "Use Intl for transliterator_transliterate() support"
},
"type": "library",
"autoload": {
"psr-4": {
"voku\\": "src/voku/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lars Moelleken",
"homepage": "http://www.moelleken.org/"
}
],
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
"homepage": "https://github.com/voku/portable-ascii",
"keywords": [
"ascii",
"clean",
"php"
],
"support": {
"issues": "https://github.com/voku/portable-ascii/issues",
"source": "https://github.com/voku/portable-ascii/tree/1.5.6"
},
"funding": [
{
"url": "https://www.paypal.me/moelleken",
"type": "custom"
},
{
"url": "https://github.com/voku",
"type": "github"
},
{
"url": "https://opencollective.com/portable-ascii",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/voku",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
"type": "tidelift"
}
],
"time": "2020-11-12T00:07:28+00:00"
},
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.10.0", "version": "1.10.0",
@@ -3203,7 +4181,7 @@
"platform": [], "platform": [],
"platform-dev": [], "platform-dev": [],
"platform-overrides": { "platform-overrides": {
"php": "7.3" "php": "7.4"
}, },
"plugin-api-version": "2.0.0" "plugin-api-version": "2.0.0"
} }
+26 -1
View File
@@ -134,7 +134,7 @@ function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, in
getExceptionTraceAsString($e) getExceptionTraceAsString($e)
); );
} }
set_error_handler("\sammo\logErrorByCustomHandler"); set_error_handler("\\sammo\\logErrorByCustomHandler");
function logExceptionByCustomHandler(\Throwable $e) function logExceptionByCustomHandler(\Throwable $e)
@@ -151,3 +151,28 @@ function logExceptionByCustomHandler(\Throwable $e)
throw $e; throw $e;
} }
set_exception_handler('\\sammo\\logExceptionByCustomHandler'); set_exception_handler('\\sammo\\logExceptionByCustomHandler');
function getAPIExecutorClass($path){
static $basePath = __NAMESPACE__.'\\API\\';
if(is_string($path)){
}
else if(is_array($path)){
$path = join('\\', $path);
}
else{
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = str_replace('/', '\\', $basePath.$path);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{
$class = getAPIExecutorClass($type);
return new $class($rootPath, $args);
}
+17 -2
View File
@@ -58,7 +58,7 @@ CREATE TABLE `member_log` (
INDEX `action` (`member_no`, `action_type`, `date`), INDEX `action` (`member_no`, `action_type`, `date`),
INDEX `member` (`member_no`, `date`) INDEX `member` (`member_no`, `date`)
) )
ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; ENGINE=Aria DEFAULT CHARSET=utf8mb4;
################### ###################
# KV storage # KV storage
@@ -72,4 +72,19 @@ CREATE TABLE if not exists `storage` (
UNIQUE INDEX `key` (`namespace`, `key`) UNIQUE INDEX `key` (`namespace`, `key`)
) )
COLLATE='utf8mb4_general_ci' COLLATE='utf8mb4_general_ci'
ENGINE=MyISAM ENGINE=Aria;
CREATE TABLE `login_token` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`base_token` VARCHAR(20) NOT NULL COLLATE 'utf8mb4_general_ci',
`reg_ip` VARCHAR(40) NOT NULL COLLATE 'utf8mb4_general_ci',
`reg_date` DATETIME NOT NULL,
`expire_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `by_token` (`base_token`),
INDEX `by_date` (`user_id`, `expire_date`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria
;
+31
View File
@@ -2,9 +2,15 @@
namespace sammo; namespace sammo;
//https://hub.packtpub.com/eloquent-without-laravel/
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class RootDB class RootDB
{ {
private static $uDB = null; private static $uDB = null;
private static ?Capsule $uIlluminate = null;
private static $host = '_tK_host_'; private static $host = '_tK_host_';
private static $user = '_tK_user_'; private static $user = '_tK_user_';
@@ -12,6 +18,8 @@ class RootDB
private static $dbName = '_tK_dbName_'; private static $dbName = '_tK_dbName_';
private static $port = _tK_port_; private static $port = _tK_port_;
private static $encoding = 'utf8mb4'; private static $encoding = 'utf8mb4';
private static $collation = 'utf8mb4_general_ci';
private static $globalSalt = '_tK_globalSalt_'; private static $globalSalt = '_tK_globalSalt_';
@@ -19,6 +27,29 @@ class RootDB
{ {
} }
public static function illuminate(): Capsule
{
if(self::$uIlluminate !== null){
return self::$uIlluminate;
}
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => self::$host,
'database' => self::$dbName,
'username' => self::$user,
'password' => self::$password,
'charset' => self::$encoding,
'collation' => self::$collation,
], 'root');
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->bootEloquent();
self::$uIlluminate = $capsule;
return $capsule;
}
/** /**
* DB 객체 생성 * DB 객체 생성
* *
+1
View File
@@ -342,6 +342,7 @@ switch ($btn) {
} }
break; break;
case "랜덤턴": case "랜덤턴":
$turnterm = $gameStor->turnterm;
foreach ($genlist as $generalID) { foreach ($genlist as $generalID) {
$turntime = getRandTurn($turnterm); $turntime = getRandTurn($turnterm);
$db->update('general', [ $db->update('general', [
+1 -1
View File
@@ -28,7 +28,7 @@ $scenarioList = (function(){
if($scenarioIdx !== null && key_exists($scenarioIdx, $scenarioList)){ if($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx]??[])){
$searchScenarioName = $scenarioList[$seasonIdx][$scenarioIdx]['name']; $searchScenarioName = $scenarioList[$seasonIdx][$scenarioIdx]['name'];
$searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx); $searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx);
} }
+1
View File
@@ -64,6 +64,7 @@ var storedData = <?=Json::encode([
<?=WebUtil::printJS('dist_js/vendors.js')?> <?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/dipcenter.js')?> <?=WebUtil::printJS('dist_js/dipcenter.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/summernote/summernote-bs4.css')?>
<?=WebUtil::printCSS('dist_css/vendors.css')?> <?=WebUtil::printCSS('dist_css/vendors.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('css/common.css')?>
+1 -1
View File
@@ -24,7 +24,7 @@ $admin = $gameStor->getValues(['develcost', 'cost', 'vote_title', 'vote', 'votec
$generalID = Session::getGeneralID(); $generalID = Session::getGeneralID();
$general = General::createGeneralObjFromDB($generalID, ['vote','horse','weapon','book','item','npc'], 2); $general = General::createGeneralObjFromDB($generalID, ['vote','horse','weapon','book','item','npc','imgsvr','picture','aux'], 2);
if($btn == "투표" && $general->getVar('vote') == 0 && $sel > 0) { if($btn == "투표" && $general->getVar('vote') == 0 && $sel > 0) {
$develcost = $admin['develcost'] * 5; $develcost = $admin['develcost'] * 5;
+41 -6
View File
@@ -1,8 +1,16 @@
<?php <?php
namespace sammo; namespace sammo;
class DB{ //https://hub.packtpub.com/eloquent-without-laravel/
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class DB
{
private static $uDB = null; private static $uDB = null;
private static ?Capsule $uIlluminate = null;
private static $host = '_tK_host_'; private static $host = '_tK_host_';
private static $user = '_tK_user_'; private static $user = '_tK_user_';
@@ -10,11 +18,36 @@ class DB{
private static $dbName = '_tK_dbName_'; private static $dbName = '_tK_dbName_';
private static $port = _tK_port_; private static $port = _tK_port_;
private static $encoding = 'utf8mb4'; private static $encoding = 'utf8mb4';
private static $collation = 'utf8mb4_general_ci';
private static $prefix = '_tK_prefix_'; private static $prefix = '_tK_prefix_';
private function __construct(){ private function __construct()
{
}
public static function illuminate(): Capsule
{
if(self::$uIlluminate !== null){
return self::$uIlluminate;
}
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => self::$host,
'database' => self::$dbName,
'username' => self::$user,
'password' => self::$password,
'charset' => self::$encoding,
'collation' => self::$collation,
]);
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();
self::$uIlluminate = $capsule;
return $capsule;
} }
/** /**
@@ -23,12 +56,14 @@ class DB{
* @return \MeekroDB * @return \MeekroDB
* @suppress PhanTypeMismatchProperty * @suppress PhanTypeMismatchProperty
*/ */
public static function db(){ public static function db()
if(self::$uDB === null){ {
self::$uDB = new \MeekroDB(self::$host,self::$user,self::$password,self::$dbName,self::$port,self::$encoding); if (self::$uDB === null) {
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler= function(){}; self::$uDB->error_handler = function () {
};
self::$uDB->throw_exception_on_error = true; self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true; self::$uDB->throw_exception_on_nonsql_error = true;
} }
+16 -16
View File
@@ -1,22 +1,22 @@
<div class="buttonPlate bg1"> <div class="buttonPlate bg1">
<div> <div>
<a href="a_status.php" target="_blank"><button class="toolbarButton">세력도</button></a> <a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
<a href="a_kingdomList.php" target="_blank"><button class="toolbarButton">세력일람</button></a> <a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank"><button class="toolbarButton">장수일람</button></a> <a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
<a href="a_bestGeneral.php" target="_blank"><button class="toolbarButton">명장일람</button></a> <a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명장일람</button></a>
<a href="a_history.php" target="_blank"><button class="toolbarButton">연감</button></a> <a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
<a href="a_hallOfFame.php" target="_blank"><button class="toolbarButton">명예의전당</button></a> <a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank"><button class="toolbarButton">왕조일람</button></a> <a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank"><button class="toolbarButton">접속량정보</button></a> <a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
</div> </div>
<div> <div>
<a href="/bbs/board" target="_blank"><button class="toolbarButton2">삼모게시판</button></a> <a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
<a href="/bbs/tip" target="_blank"><button class="toolbarButton">팁/강좌</button></a> <a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">팁/강좌</button></a>
<a href="/bbs/news" target="_blank"><button class="toolbarButton">삼국 일보</button></a> <a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
<a href="/bbs/history2" target="_blank"><button class="toolbarButton">개인 열전</button></a> <a href="/bbs/history2" target="_blank"><button type="button" class="toolbarButton">개인 열전</button></a>
<a href="/bbs/history3" target="_blank"><button class="toolbarButton">국가 열전</button></a> <a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
<a href="/bbs/patch" target="_blank"><button class="toolbarButton">패치 내역</button></a> <a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="../i_other/help.php" target="_blank"><button class="toolbarButton">튜토리얼</button></a> <a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?=$site?>" target="_blank"><button class="toolbarButton"><?=$call?></button></a> <a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
</div> </div>
</div> </div>
+44 -13
View File
@@ -1256,9 +1256,12 @@ function addAge()
//나이와 호봉 증가 //나이와 호봉 증가
$db->update('general', [ $db->update('general', [
'age' => $db->sqleval('age+1'), 'age' => $db->sqleval('age+1'),
'belong' => $db->sqleval('belong+1')
], true); ], true);
$db->update('general', [
'belong' => $db->sqleval('belong+1')
], 'nation != 0');
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']); [$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
if ($year >= $startYear + 3) { if ($year >= $startYear + 3) {
@@ -1286,12 +1289,11 @@ function addAge()
$generalAux = Json::decode($general['aux']); $generalAux = Json::decode($general['aux']);
$updateVars = []; $updateVars = [];
if(key_exists('inheritSpecificSpecialWar', $generalAux)){ if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
$special2 = $generalAux['inheritSpecificSpecialWar']; $special2 = $generalAux['inheritSpecificSpecialWar'];
unset($generalAux['inheritSpecificSpecialWar']); unset($generalAux['inheritSpecificSpecialWar']);
$updateVars['aux'] = Json::encode($generalAux); $updateVars['aux'] = Json::encode($generalAux);
} } else {
else{
$special2 = SpecialityHelper::pickSpecialWar( $special2 = SpecialityHelper::pickSpecialWar(
$general, $general,
($generalAux['prev_types_special2']) ?? [] ($generalAux['prev_types_special2']) ?? []
@@ -1592,9 +1594,19 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
} }
if (!$availableUnique) { if (!$availableUnique) {
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("얻을 유니크가 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
return false; return false;
} }
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
}
[$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique); [$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique);
$nationName = $general->getStaticNation()['name']; $nationName = $general->getStaticNation()['name'];
@@ -1628,22 +1640,29 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
$itemTrials = $general->getAuxVar('inheritUniqueTrial'); $itemTrials = $general->getAuxVar('inheritUniqueTrial');
LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]); LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]);
unset($itemTrials[$itemKey]); unset($itemTrials[$itemKey]);
if(count($itemTrials) == 0){
$itemTrials = null;
}
$general->setAuxVar('inheritUniqueTrial', $itemTrials); $general->setAuxVar('inheritUniqueTrial', $itemTrials);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); $trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$ownTrial = $trialStor->getValue("u{$ownerID}"); $ownTrial = $trialStor->getValue("u{$ownerID}");
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
if ($ownTrial) { if ($ownTrial) {
//두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자 //두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자
[,, $amount] = $ownTrial; [,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$ownerID}"); $trialStor->deleteValue("u{$ownerID}");
$general->increaseInheritancePoint('previous', $amount); $general->increaseInheritancePoint('previous', $amount);
LogText("선택유니크 롤백포인트:{$ownerID}", $amount); LogText("선택유니크 롤백포인트:{$ownerID}", $amount);
$userLogger = new UserLogger($ownerID);
$userLogger->push("{$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
} }
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
//메시지 //메시지
$staticNation = $general->getStaticNation(); $staticNation = $general->getStaticNation();
@@ -1662,11 +1681,16 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
[] []
); );
$msg->send(true);
$general->applyDB($db); $general->applyDB($db);
$msg->send(true);
} }
function tryInheritUniqueItem(General $general, string $acquireType = '아이템'): bool function tryRollbackInheritUniqueItem(General $general): void
{
tryInheritUniqueItem($general, 'Rollback', true);
}
function tryInheritUniqueItem(General $general, string $acquireType = '아이템', bool $justRollback = false): bool
{ {
$ownerID = $general->getVar('owner'); $ownerID = $general->getVar('owner');
if (!$ownerID) { if (!$ownerID) {
@@ -1769,6 +1793,9 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
if ($ownTarget === null) { if ($ownTarget === null) {
return false; return false;
} }
if ($justRollback) {
return false;
}
LogText("선택유니크획득{$ownerID}", $ownTarget); LogText("선택유니크획득{$ownerID}", $ownTarget);
@@ -1814,7 +1841,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
} }
$inheritUnique = $general->getAuxVar('inheritUniqueTrial'); $inheritUnique = $general->getAuxVar('inheritUniqueTrial');
if ($inheritUnique && count($inheritUnique)) { if ($acquireType != '설문조사' && $inheritUnique && count($inheritUnique)) {
LogText("유니크 준비?? {$general->getID()}", $inheritUnique); LogText("유니크 준비?? {$general->getID()}", $inheritUnique);
$trialResult = tryInheritUniqueItem($general, $acquireType); $trialResult = tryInheritUniqueItem($general, $acquireType);
if ($trialResult) { if ($trialResult) {
@@ -1833,6 +1860,12 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
if ($trialCnt <= 0) { if ($trialCnt <= 0) {
LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt); LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt);
if ($general->getAuxVar('inheritRandomUnique')) {
$general->setAuxVar('inheritRandomUnique', null);
$general->increaseInheritancePoint('previous', GameConst::$inheritItemRandomPoint);
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("유니크를 얻을 공간이 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
return false; return false;
} }
@@ -1859,13 +1892,11 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$result = false; $result = false;
$prob /= sqrt(2); $prob /= sqrt(2);
$moreProb = pow(2, 1/4); $moreProb = pow(2, 1 / 4);
if($general->getAuxVar('inheritRandomUnique')){ if ($general->getAuxVar('inheritRandomUnique')) {
//포인트로 랜덤 유니크 획득 //포인트로 랜덤 유니크 획득
$prob = 1; $prob = 1;
LogText("{$general->getName()}, {$general->getID()} 유산 포인트 유니크", $prob);
$general->setAuxVar('inheritRandomUnique', null);
} }
foreach (Util::range($trialCnt) as $_idx) { foreach (Util::range($trialCnt) as $_idx) {
-25
View File
@@ -357,31 +357,6 @@ function buildNationCommandClass(?string $type, General $generalObj, array $env,
return new $class($generalObj, $env, $lastTurn, $arg); return new $class($generalObj, $env, $lastTurn, $arg);
} }
function getAPIExecutorClass($path){
static $basePath = __NAMESPACE__.'\\API\\';
if(is_string($path)){
}
else if(is_array($path)){
$path = join('\\', $path);
}
else{
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = str_replace('/', '\\', $basePath.$path);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass($type, string $rootPath, array $args):\sammo\BaseAPI{
$class = getAPIExecutorClass($type);
return new $class($rootPath, $args);
}
function getWarUnitTriggerClass(string $type){ function getWarUnitTriggerClass(string $type){
static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\'; static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\';
$classPath = ($basePath.$type); $classPath = ($basePath.$type);
+15 -3
View File
@@ -624,12 +624,12 @@ function updateNationState()
$targetKillTurn $targetKillTurn
); );
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2); $nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
$chiefObj = null; $chiefID = null;
$uniqueLotteryWeightList = []; $uniqueLotteryWeightList = [];
foreach ($nationGenList as $nationGen) { foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) { if ($nationGen->getVar('officer_level') == 12) {
$chiefObj = $nationGen; $chiefID = $nationGen->getID();
} }
$trialCnt = count(GameConst::$allItems); $trialCnt = count(GameConst::$allItems);
@@ -670,8 +670,10 @@ function updateNationState()
$winnerObj->applyDB($db); $winnerObj->applyDB($db);
} }
if($chiefObj){ if($chiefID){
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
$chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff); $chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
$chiefObj->applyDB($db);
} }
} }
} }
@@ -1166,13 +1168,23 @@ function resetInheritanceUser(int $userID, bool $isRebirth=false):float{
//이미 리셋되었으므로 리셋 안함 //이미 리셋되었으므로 리셋 안함
return $allPoints['previous'][0]; return $allPoints['previous'][0];
} }
$userLogger = new UserLogger($userID);
$previousPoint = ($allPoints['previous']??[0,0])[0];
foreach($allPoints as $key=>[$value,]){ foreach($allPoints as $key=>[$value,]){
if($isRebirth && key_exists($key, $rebirthDegraded)){ if($isRebirth && key_exists($key, $rebirthDegraded)){
$value *= $rebirthDegraded[$key]; $value *= $rebirthDegraded[$key];
} }
$keyText = General::INHERITANCE_KEY[$key][2];
$userLogger->push("{$keyText} 포인트 {$value} 증가", "inheritPoint");
$totalPoint += $value; $totalPoint += $value;
} }
$totalPoint = Util::toInt($totalPoint); $totalPoint = Util::toInt($totalPoint);
$userLogger->push("포인트 {$previousPoint} => {$totalPoint}", "inheritPoint");
$userLogger->flush();
$inheritStor->resetValues(); $inheritStor->resetValues();
$inheritStor->setValue('previous', [$totalPoint, null]); $inheritStor->setValue('previous', [$totalPoint, null]);
return $totalPoint; return $totalPoint;
+1 -1
View File
@@ -1132,7 +1132,7 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type) {
$gen1resKey = 'd'; $gen1resKey = 'd';
$gen2resKey = 'd'; $gen2resKey = 'd';
break; break;
default: new MustNotBeReachedException(); default: throw new MustNotBeReachedException();
} }
$db->update('rank_data', [ $db->update('rank_data', [
+1 -1
View File
@@ -47,7 +47,7 @@ else{
'name', 'leadership', 'strength', 'intel', 'gold','rice', 'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr', 'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype', 'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
], 1); ], 1);
if($general instanceof DummyGeneral){ if($general instanceof DummyGeneral){
+3 -9
View File
@@ -39,7 +39,7 @@ $db = DB::db();
$me = General::createGeneralObjFromDB($generalID); $me = General::createGeneralObjFromDB($generalID);
if($defence_train != $me->getVar('defence_train')){ if($defence_train !== $me->getVar('defence_train')){
if($defence_train == 999){ if($defence_train == 999){
$me->increaseVar('myset', -1); $me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train); $me->setVar('defence_train', $defence_train);
@@ -53,14 +53,8 @@ if($defence_train != $me->getVar('defence_train')){
} }
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100)); $me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){ $me->setVar('tnmt', $tnmt);
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
}
if($me->getVar('tnmt') != $tnmt){
$me->setVar('tnmt', $tnmt);
}
if($me->getNPCType() == 1 && $detachNPC){ if($me->getNPCType() == 1 && $detachNPC){
$turnterm = $gameStor->turnterm; $turnterm = $gameStor->turnterm;
+65 -53
View File
@@ -1,4 +1,5 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
@@ -21,18 +22,18 @@ $availableTypes = [
'nationPolicy', 'nationPolicy',
]; ];
if(!in_array($type, $availableTypes)){ if (!in_array($type, $availableTypes)) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'올바른 타입이 아닙니다.', 'reason' => '올바른 타입이 아닙니다.',
]); ]);
} }
$data = Json::decode($data); $data = Json::decode($data);
if(!$data || !is_array($data)){ if (!$data || !is_array($data)) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'올바른 입력이 아닙니다.', 'reason' => '올바른 입력이 아닙니다.',
]); ]);
} }
@@ -44,89 +45,90 @@ $me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con
$nationID = $me['nation']; $nationID = $me['nation'];
if (!$nationID) { if (!$nationID) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'국가에 소속되어있지 않습니다.', 'reason' => '국가에 소속되어있지 않습니다.',
]); ]);
} }
$permission = checkSecretPermission($me); $permission = checkSecretPermission($me);
if ($permission < 3) { if ($permission < 3) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.' 'reason' => '권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.'
]); ]);
} }
function applyNationPolicy($policy, $nationID, $generalName):?string{ function applyNationPolicy($policy, $nationID, $generalName): ?string
{
$db = DB::db(); $db = DB::db();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$defaultPolicy = AutorunNationPolicy::$defaultPolicy; $defaultPolicy = AutorunNationPolicy::$defaultPolicy;
$troopCache = null; $troopCache = null;
foreach($db->queryFirstColumn('SELECT troop_leader FROM troop WHERE nation=%i',$nationID) as $troopID){ foreach ($db->queryFirstColumn('SELECT troop_leader FROM troop WHERE nation=%i', $nationID) as $troopID) {
$troopCache[$troopID] = 'Neutral'; $troopCache[$troopID] = 'Neutral';
} }
$cityList = CityConst::all(); $cityList = CityConst::all();
$nationPolicyRoot = $nationStor->npc_nation_policy; $nationPolicyRoot = $nationStor->npc_nation_policy;
$nationPolicy = $nationPolicyRoot['values']??[]; $nationPolicy = $nationPolicyRoot['values'] ?? [];
foreach($policy as $key=>$val){ foreach ($policy as $key => $val) {
if($key === 'CombatForce'){ if ($key === 'CombatForce') {
if(!is_array($val)){ if (!is_array($val)) {
return "{$key}는 올바른 정책값이 아닙니다."; return "{$key}는 올바른 정책값이 아닙니다.";
} }
foreach($val as $troopID=>$troopTarget){ foreach ($val as $troopID => $troopTarget) {
if(!key_exists($troopID, $troopCache)){ if (!key_exists($troopID, $troopCache)) {
return "{$troopID}는 국가의 부대가 아닙니다."; return "{$troopID}는 국가의 부대가 아닙니다.";
} }
if($troopCache[$troopID] != 'Neutral'){ if ($troopCache[$troopID] != 'Neutral') {
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다."; return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
} }
if(!is_array($troopTarget) || count($troopTarget)!=2){ if (!is_array($troopTarget) || count($troopTarget) != 2) {
return "{$troopID}의 입력양식이 올바르지 않습니다."; return "{$troopID}의 입력양식이 올바르지 않습니다.";
} }
[$fromCity, $toCity] = $troopCache; [$fromCity, $toCity] = $troopCache;
if(!key_exists($fromCity, $cityList) || !key_exists($toCity, $cityList)){ if (!key_exists($fromCity, $cityList) || !key_exists($toCity, $cityList)) {
return "{$troopID}의 도시 {$fromCity}, {$toCity}가 올바른 도시 번호가 아닙니다."; return "{$troopID}의 도시 {$fromCity}, {$toCity}가 올바른 도시 번호가 아닙니다.";
} }
$troopCache[$troopID]=$key; $troopCache[$troopID] = $key;
} }
$nationPolicy[$key]=$val; $nationPolicy[$key] = $val;
continue; continue;
} }
if(in_array($key, ['SupportForce', 'DevelopForce'])){ if (in_array($key, ['SupportForce', 'DevelopForce'])) {
if(!is_array($val)){ if (!is_array($val)) {
return "{$key}는 올바른 정책값이 아닙니다."; return "{$key}는 올바른 정책값이 아닙니다.";
} }
foreach($val as $troopID){ foreach ($val as $troopID) {
if(!key_exists($troopID, $troopCache)){ if (!key_exists($troopID, $troopCache)) {
return "{$troopID}는 국가의 부대가 아닙니다."; return "{$troopID}는 국가의 부대가 아닙니다.";
} }
if($troopCache[$troopID] != 'Neutral'){ if ($troopCache[$troopID] != 'Neutral') {
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다."; return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
} }
$troopCache[$troopID]=$key; $troopCache[$troopID] = $key;
} }
$nationPolicy[$key]=array_values($val); $nationPolicy[$key] = array_values($val);
continue; continue;
} }
if(!key_exists($key, $defaultPolicy)){ if (!key_exists($key, $defaultPolicy)) {
return "{$key}는 올바른 정책값이 아닙니다."; return "{$key}는 올바른 정책값이 아닙니다.";
} }
$defaultValue = $defaultPolicy[$key]; $defaultValue = $defaultPolicy[$key];
if(is_numeric($defaultValue) != is_numeric($val)){ if (is_numeric($defaultValue) != is_numeric($val)) {
return "{$key}는 올바른 값이 아닙니다."; return "{$key}는 올바른 값이 아닙니다.";
} }
if(is_integer($defaultValue) != is_integer($val)){ if (is_integer($defaultValue) != is_integer($val)) {
return "{$key}는 올바른 값이 아닙니다."; return "{$key}는 올바른 값이 아닙니다.";
} }
if(is_array($defaultValue) != is_array($val)){ if (is_array($defaultValue) != is_array($val)) {
return "{$key}는 올바른 값이 아닙니다."; return "{$key}는 올바른 값이 아닙니다.";
} }
if(is_integer($val) && $val < 0){ if (is_integer($val) && $val < 0) {
$val = 0; $val = 0;
} }
$nationPolicy[$key] = $val; $nationPolicy[$key] = $val;
@@ -139,14 +141,15 @@ function applyNationPolicy($policy, $nationID, $generalName):?string{
return null; return null;
} }
function applyNationPriority($priority, $nationID, $generalName):?string{ function applyNationPriority($priority, $nationID, $generalName): ?string
{
$db = DB::db(); $db = DB::db();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationPolicyRoot = $nationStor->npc_nation_policy; $nationPolicyRoot = $nationStor->npc_nation_policy;
$defaultPriority = AutorunNationPolicy::$defaultPriority; $defaultPriority = AutorunNationPolicy::$defaultPriority;
foreach($priority as $item){ foreach ($priority as $item) {
if(!in_array($item, $defaultPriority)){ if (!in_array($item, $defaultPriority)) {
return "{$item}은 올바른 명령이 아닙니다."; return "{$item}은 올바른 명령이 아닙니다.";
} }
} }
@@ -157,17 +160,29 @@ function applyNationPriority($priority, $nationID, $generalName):?string{
return null; return null;
} }
function applyGeneralPriority($priority, $nationID, $generalName):?string{ function applyGeneralPriority($priority, $nationID, $generalName): ?string
{
$db = DB::db(); $db = DB::db();
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$generalPolicyRoot = $nationStor->npc_general_policy; $generalPolicyRoot = $nationStor->npc_general_policy;
$defaultPriority = AutorunGeneralPolicy::$default_priority; $defaultPriority = AutorunGeneralPolicy::$default_priority;
foreach($priority as $item){ $mustHaveActions = ['출병' => 1];
if(!in_array($item, $defaultPriority)){ foreach ($priority as $item) {
if (key_exists($item, $mustHaveActions)) {
$mustHaveActions[$item] = 0;
}
if (!in_array($item, $defaultPriority)) {
return "{$item}은 올바른 명령이 아닙니다."; return "{$item}은 올바른 명령이 아닙니다.";
} }
} }
foreach ($mustHaveActions as $actionKey => $unset) {
if ($unset) {
return "{$actionKey}은 항상 사용해야 합니다.";
}
}
$generalPolicyRoot['priority'] = $priority; $generalPolicyRoot['priority'] = $priority;
$generalPolicyRoot['prioritySetter'] = $generalName; $generalPolicyRoot['prioritySetter'] = $generalName;
$generalPolicyRoot['prioritySetTime'] = TimeUtil::now(); $generalPolicyRoot['prioritySetTime'] = TimeUtil::now();
@@ -175,26 +190,23 @@ function applyGeneralPriority($priority, $nationID, $generalName):?string{
return null; return null;
} }
if($type == 'nationPolicy'){ if ($type == 'nationPolicy') {
$result = applyNationPolicy($data, $nationID, $me['name']); $result = applyNationPolicy($data, $nationID, $me['name']);
} } else if ($type == 'generalPriority') {
else if($type == 'generalPriority'){
$result = applyGeneralPriority($data, $nationID, $me['name']); $result = applyGeneralPriority($data, $nationID, $me['name']);
} } else if ($type == 'nationPriority') {
else if($type == 'nationPriority'){
$result = applyNationPriority($data, $nationID, $me['name']); $result = applyNationPriority($data, $nationID, $me['name']);
} } else {
else{
throw new MustNotBeReachedException(); throw new MustNotBeReachedException();
} }
if($result!==null){ if ($result !== null) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>$result, 'reason' => $result,
]); ]);
} }
Json::die([ Json::die([
'result'=>true, 'result' => true,
'reason'=>'success', 'reason' => 'success',
]); ]);
+15 -2
View File
@@ -16,6 +16,7 @@ use sammo\Session;
use sammo\SpecialityHelper; use sammo\SpecialityHelper;
use sammo\StringUtil; use sammo\StringUtil;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\UserLogger;
use sammo\Util; use sammo\Util;
use sammo\Validator; use sammo\Validator;
use sammo\WebUtil; use sammo\WebUtil;
@@ -152,11 +153,13 @@ class Join extends \sammo\BaseAPI
} }
} }
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']); $admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year', 'month']);
$inheritTotalPoint = resetInheritanceUser($userID); $inheritTotalPoint = resetInheritanceUser($userID);
$inheritRequiredPoint = 0; $inheritRequiredPoint = 0;
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
if ($inheritCity !== null) { if ($inheritCity !== null) {
$inheritRequiredPoint += GameConst::$inheritBornCityPoint; $inheritRequiredPoint += GameConst::$inheritBornCityPoint;
} }
@@ -183,6 +186,8 @@ class Join extends \sammo\BaseAPI
} }
if ($inheritSpecial) { if ($inheritSpecial) {
$speicalText = getGeneralSpecialWarName($inheritSpecial);
$userLogger->push("{$speicalText} 전투 특기를 가진 천재 생성", "inheritPoint");
$genius = true; $genius = true;
} else { } else {
// 현재 1% // 현재 1%
@@ -196,6 +201,8 @@ class Join extends \sammo\BaseAPI
} }
if ($inheritCity !== null) { if ($inheritCity !== null) {
$cityname = CityConst::byID($inheritCity)->name;
$userLogger->push("{$cityname}에 장수 생성", "inheritPoint");
$city = $inheritCity; $city = $inheritCity;
} else { } else {
// 공백지에서만 태어나게 // 공백지에서만 태어나게
@@ -207,6 +214,7 @@ class Join extends \sammo\BaseAPI
if ($inheritBonusStat) { if ($inheritBonusStat) {
[$pleadership, $pstrength, $pintel] = $inheritBonusStat; [$pleadership, $pstrength, $pintel] = $inheritBonusStat;
$userLogger->push("{$pleadership}, {$pstrength}, {$pintel} 보너스 능력치로 생성", "inheritPoint");
} else { } else {
$pleadership = 0; $pleadership = 0;
$pstrength = 0; $pstrength = 0;
@@ -276,8 +284,10 @@ class Join extends \sammo\BaseAPI
} }
if ($inheritTurntime !== null) { if ($inheritTurntime !== null) {
//FIXME: 오동작함
$inheritTurntime = $inheritTurntime % ($admin['turnterm'] * 60); $inheritTurntime = $inheritTurntime % ($admin['turnterm'] * 60);
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime%60), "inheritPoint");
$inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm'])); $turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm']));
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime)); $turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
@@ -372,9 +382,12 @@ class Join extends \sammo\BaseAPI
]); ]);
$cityname = CityConst::byID($city)->name; $cityname = CityConst::byID($city)->name;
if ($inheritRequiredPoint > 0) { if ($inheritRequiredPoint > 0) {
$userLogger->push("장수 생성으로 포인트 {$inheritRequiredPoint} 소모", "inheritPoint");
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}"); $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]); $inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]);
$userLogger->flush();
} }
$me = [ $me = [
@@ -10,6 +10,7 @@ use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\TriggerInheritBuff; use sammo\TriggerInheritBuff;
use sammo\UserLogger;
use sammo\Validator; use sammo\Validator;
class BuyHiddenBuff extends \sammo\BaseAPI class BuyHiddenBuff extends \sammo\BaseAPI
@@ -50,6 +51,7 @@ class BuyHiddenBuff extends \sammo\BaseAPI
if ($userID != $general->getVar('owner')) { if ($userID != $general->getVar('owner')) {
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.'; return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
} }
$userLogger = new UserLogger($userID);
$inheritBuffList = $general->getAuxVar('inheritBuff') ?? []; $inheritBuffList = $general->getAuxVar('inheritBuff') ?? [];
$prevLevel = $inheritBuffList[$type] ?? 0; $prevLevel = $inheritBuffList[$type] ?? 0;
@@ -70,6 +72,11 @@ class BuyHiddenBuff extends \sammo\BaseAPI
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$buffTypeText = TriggerInheritBuff::BUFF_KEY_TEXT[$type];
$moreText = $prevLevel > 0 ? "추가":"";
$userLogger->push("{$reqAmount} 포인트로 {$buffTypeText} {$level} 단계 {$moreText}구입", "inheritPoint");
$userLogger->flush();
$inheritBuffList[$type] = $level; $inheritBuffList[$type] = $level;
$general->setAuxVar('inheritBuff', $inheritBuffList); $general->setAuxVar('inheritBuff', $inheritBuffList);
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]); $inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
@@ -9,6 +9,7 @@ use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\UserLogger;
class BuyRandomUnique extends \sammo\BaseAPI class BuyRandomUnique extends \sammo\BaseAPI
{ {
@@ -40,12 +41,17 @@ class BuyRandomUnique extends \sammo\BaseAPI
$db = DB::db(); $db = DB::db();
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
$previousPoint = ($inheritStor->getValue('previous')??[0, 0])[0]; $previousPoint = ($inheritStor->getValue('previous')??[0, 0])[0];
if($previousPoint < GameConst::$inheritItemRandomPoint){ $reqAmount = GameConst::$inheritItemRandomPoint;
if($previousPoint < $reqAmount){
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$userLogger = new UserLogger($userID);
$userLogger->push("{$reqAmount} 포인트로 랜덤 유니크 구입", "inheritPoint");
$userLogger->flush();
$general->setAuxVar('inheritRandomUnique', TimeUtil::now()); $general->setAuxVar('inheritRandomUnique', TimeUtil::now());
$inheritStor->setValue('previous', [$previousPoint - GameConst::$inheritItemRandomPoint, null]); $inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->applyDB($db); $general->applyDB($db);
return null; return null;
} }
@@ -8,12 +8,16 @@ use sammo\DB;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator; use sammo\Validator;
use function sammo\buildItemClass;
class BuySpecificUnique extends \sammo\BaseAPI class BuySpecificUnique extends \sammo\BaseAPI
{ {
public function validateArgs(): ?string public function validateArgs(): ?string
{ {
$availableItems = [];
foreach (GameConst::$allItems as $items) { foreach (GameConst::$allItems as $items) {
foreach ($items as $itemKey => $amount) { foreach ($items as $itemKey => $amount) {
if ($amount == 0) { if ($amount == 0) {
@@ -70,6 +74,11 @@ class BuySpecificUnique extends \sammo\BaseAPI
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$itemObj = buildItemClass($itemKey);
$userLogger = new UserLogger($userID);
$userLogger->push("{$amount} 포인트로 유니크 {$itemObj->getName()} 구입 시도", "inheritPoint");
$userLogger->flush();
$itemTrials[$itemKey] = $amount; $itemTrials[$itemKey] = $amount;
$general->setAuxVar('inheritUniqueTrial', $itemTrials); $general->setAuxVar('inheritUniqueTrial', $itemTrials);
$inheritStor->setValue('previous', [$previousPoint - $amount, null]); $inheritStor->setValue('previous', [$previousPoint - $amount, null]);
@@ -8,6 +8,7 @@ use sammo\DB;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator; use sammo\Validator;
class ResetSpecialWar extends \sammo\BaseAPI class ResetSpecialWar extends \sammo\BaseAPI
@@ -55,6 +56,10 @@ class ResetSpecialWar extends \sammo\BaseAPI
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$userLogger = new UserLogger($userID);
$userLogger->push("{$reqPoint} 포인트로 전투 특기 초기화", "inheritPoint");
$userLogger->flush();
$oldTypeKey = 'prev_types_special2'; $oldTypeKey = 'prev_types_special2';
$oldSpecialList = $general->getAuxVar($oldTypeKey) ?? []; $oldSpecialList = $general->getAuxVar($oldTypeKey) ?? [];
$oldSpecialList[] = $currentSpecialWar; $oldSpecialList[] = $currentSpecialWar;
@@ -10,6 +10,7 @@ use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\TimeUtil; use sammo\TimeUtil;
use sammo\UserLogger;
use sammo\Util; use sammo\Util;
class ResetTurnTime extends \sammo\BaseAPI class ResetTurnTime extends \sammo\BaseAPI
@@ -59,6 +60,15 @@ class ResetTurnTime extends \sammo\BaseAPI
$afterTurn = Util::randRange($turnTerm * -60 / 2, $turnTerm * 60 / 2); $afterTurn = Util::randRange($turnTerm * -60 / 2, $turnTerm * 60 / 2);
$userLogger = new UserLogger($userID);
if($afterTurn >= 0){
$userLogger->push(sprintf("{$reqPoint} 포인트로 턴 시간을 바꾼 결과 %02d:%02d 뒤로 밀림", intdiv(Util::toInt($afterTurn), 60), $afterTurn%60), "inheritPoint");
}
else{
$userLogger->push(sprintf("{$reqPoint} 포인트로 턴 시간을 바꾼 결과 %02d:%02d 앞으로 당김", intdiv(Util::toInt(-$afterTurn), 60), (-$afterTurn)%60), "inheritPoint");
}
$userLogger->flush();
$turnTime = $currTurnTime->add(TimeUtil::secondsToDateInterval($afterTurn)); $turnTime = $currTurnTime->add(TimeUtil::secondsToDateInterval($afterTurn));
if ($turnTime <= $serverTurnTimeObj && $serverTurnTimeObj <= $currTurnTime) { if ($turnTime <= $serverTurnTimeObj && $serverTurnTimeObj <= $currTurnTime) {
$turnTime = $turnTime->add(TimeUtil::secondsToDateInterval($turnTerm * 60)); $turnTime = $turnTime->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
@@ -8,8 +8,11 @@ use sammo\DB;
use sammo\GameConst; use sammo\GameConst;
use sammo\General; use sammo\General;
use sammo\KVStorage; use sammo\KVStorage;
use sammo\UserLogger;
use sammo\Validator; use sammo\Validator;
use function sammo\buildGeneralSpecialWarClass;
class SetNextSpecialWar extends \sammo\BaseAPI class SetNextSpecialWar extends \sammo\BaseAPI
{ {
public function validateArgs(): ?string public function validateArgs(): ?string
@@ -67,6 +70,11 @@ class SetNextSpecialWar extends \sammo\BaseAPI
return '충분한 유산 포인트를 가지고 있지 않습니다.'; return '충분한 유산 포인트를 가지고 있지 않습니다.';
} }
$userLogger = new UserLogger($userID);
$specialWarObj = buildGeneralSpecialWarClass($type);
$userLogger->push("{$reqAmount} 포인트로 다음 전투 특기로 {$specialWarObj->getName()} 지정", "inheritPoint");
$userLogger->flush();
$general->setAuxVar('inheritSpecificSpecialWar', $type); $general->setAuxVar('inheritSpecificSpecialWar', $type);
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]); $inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
$general->applyDB($db); $general->applyDB($db);
@@ -19,7 +19,7 @@ class che_무기_09_동호비궁 extends \sammo\BaseStatItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.15, 20, 40), new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.2, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM) new che_저격발동($unit, che_저격발동::TYPE_ITEM)
); );
} }
@@ -19,7 +19,7 @@ class che_무기_13_양유기궁 extends \sammo\BaseStatItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.05, 20, 40), new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.1, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM) new che_저격발동($unit, che_저격발동::TYPE_ITEM)
); );
} }
@@ -11,25 +11,29 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
protected $id = 61; protected $id = 61;
protected $rawName = '비급'; protected $rawName = '비급';
protected $name = '비급(무쌍)'; protected $name = '비급(무쌍)';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)'; protected $info = '[전투] 대미지 +5%, 피해 -2%, 공격 시 필살 확률 +10%p, <br>승리 수의 로그 비례로 대미지 상승(10회 ⇒ +5%, 40회 ⇒ +15%)<br>승리 수의 로그 비례로 피해 감소(10회 ⇒ -2%, 40회 ⇒ -6%)';
protected $cost = 100; protected $cost = 100;
protected $buyable = true; protected $buyable = true;
protected $consumable = false; protected $consumable = false;
protected $reqSecu = 3000; protected $reqSecu = 3000;
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){ if($statName === 'warCriticalRatio' && ($aux['isAttacker']??false)){
return $value += 0.1; return $value += 0.1;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1; $generalWarSpecial = $unit->getGeneral()->getSpecialWar();
$defenceMultiplier = 0.95; if($generalWarSpecial !== null && $generalWarSpecial->getName() == '무쌍'){
return [1, 1];
}
$attackMultiplier = 1.05;
$defenceMultiplier = 0.98;
$killnum = $unit->getGeneral()->getRankVar('killnum'); $killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4); $attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3); $defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
return [$attackMultiplier, $defenceMultiplier]; return [$attackMultiplier, $defenceMultiplier];
} }
} }
@@ -38,7 +38,7 @@ class event_전투특기_반계 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_반계시도($unit), new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_반계발동($unit) new che_반계발동($unit)
); );
} }
@@ -10,7 +10,7 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
protected $id = 61; protected $id = 61;
protected $name = '무쌍'; protected $name = '무쌍';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)'; protected $info = '[전투] 대미지 +5%, 피해 -2%, 공격 시 필살 확률 +10%p, <br>승리 수의 로그 비례로 대미지 상승(10회 ⇒ +5%, 40회 ⇒ +15%)<br>승리 수의 로그 비례로 피해 감소(10회 ⇒ -2%, 40회 ⇒ -6%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
@@ -19,18 +19,22 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
]; ];
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){ if($statName === 'warCriticalRatio' && ($aux['isAttacker']??false)){
return $value += 0.1; return $value += 0.1;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1; $generalWarSpecial = $unit->getGeneral()->getSpecialWar();
$defenceMultiplier = 1; if($generalWarSpecial !== null && $generalWarSpecial->getName() == '무쌍'){
return [1, 1];
}
$attackMultiplier = 1.05;
$defenceMultiplier = 0.98;
$killnum = $unit->getGeneral()->getRankVar('killnum'); $killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4); $attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3); $defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
return [$attackMultiplier, $defenceMultiplier]; return [$attackMultiplier, $defenceMultiplier];
} }
} }
+6 -6
View File
@@ -10,7 +10,7 @@ class che_무쌍 extends \sammo\BaseSpecial{
protected $id = 61; protected $id = 61;
protected $name = '무쌍'; protected $name = '무쌍';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)'; protected $info = '[전투] 대미지 +5%, 피해 -2%, 공격 시 필살 확률 +10%p, <br>승리 수의 로그 비례로 대미지 상승(10회 ⇒ +5%, 40회 ⇒ +15%)<br>승리 수의 로그 비례로 피해 감소(10회 ⇒ -2%, 40회 ⇒ -6%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM; static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1; static $selectWeight = 1;
@@ -19,18 +19,18 @@ class che_무쌍 extends \sammo\BaseSpecial{
]; ];
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){ if($statName === 'warCriticalRatio' && ($aux['isAttacker']??false)){
return $value += 0.1; return $value += 0.1;
} }
return $value; return $value;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1; $attackMultiplier = 1.05;
$defenceMultiplier = 0.95; $defenceMultiplier = 0.98;
$killnum = $unit->getGeneral()->getRankVar('killnum'); $killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4); $attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3); $defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
return [$attackMultiplier, $defenceMultiplier]; return [$attackMultiplier, $defenceMultiplier];
} }
} }
+3 -3
View File
@@ -3,9 +3,9 @@ namespace sammo;
class CityHelper{ class CityHelper{
//Just Helper //Just Helper
private static $list = null; private static ?array $list = null;
private static $listInv = null; private static ?array $listInv = null;
private static $listByNation = null; private static ?array $listByNation = null;
private function __construct(){ private function __construct(){
+2 -1
View File
@@ -13,6 +13,7 @@ use \sammo\{
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_NPC능동 extends Command\GeneralCommand{ class che_NPC능동 extends Command\GeneralCommand{
static protected $actionName = 'NPC능동'; static protected $actionName = 'NPC능동';
@@ -97,7 +98,7 @@ class che_NPC능동 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
} }
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
@@ -182,13 +182,13 @@ class che_랜덤임관 extends Command\GeneralCommand
$generalsCnt = []; $generalsCnt = [];
if ($notIn) { if ($notIn) {
$rawGeneralsCnt = $db->query( $rawGeneralsCnt = $db->query(
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc != 9 AND nation.gennum < %i AND nation.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc', 'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE (npc < 4 OR npc = 6) AND nation.gennum < %i AND nation.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc',
$genLimit, $genLimit,
$notIn $notIn
); );
} else { } else {
$rawGeneralsCnt = $db->query( $rawGeneralsCnt = $db->query(
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc != 9 AND nation.gennum < %i AND nation.scout=0 GROUP BY general.nation, general.npc', 'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE (npc < 4 OR npc = 6) AND nation.gennum < %i AND nation.scout=0 GROUP BY general.nation, general.npc',
$genLimit $genLimit
); );
} }
@@ -234,7 +234,7 @@ class che_랜덤임관 extends Command\GeneralCommand
if (!$destNation) { if (!$destNation) {
//임관 가능한 국가가 없다! //임관 가능한 국가가 없다!
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>"); $logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
$this->alternative = new che_요양($general, $this->env, null); $this->alternative = new che_인재탐색($general, $this->env, null);
return false; return false;
} }
@@ -14,6 +14,8 @@ use \sammo\{
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_모반시도 extends Command\GeneralCommand{ class che_모반시도 extends Command\GeneralCommand{
static protected $actionName = '모반시도'; static protected $actionName = '모반시도';
@@ -95,6 +97,7 @@ class che_모반시도 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
$lordGeneral->applyDB($db); $lordGeneral->applyDB($db);
+2 -1
View File
@@ -15,7 +15,7 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst; use sammo\CityConst;
use function sammo\DeleteConflict; use function sammo\DeleteConflict;
use function sammo\refreshNationStaticInfo; use function sammo\refreshNationStaticInfo;
use function sammo\tryRollbackInheritUniqueItem;
class che_방랑 extends Command\GeneralCommand{ class che_방랑 extends Command\GeneralCommand{
static protected $actionName = '방랑'; static protected $actionName = '방랑';
@@ -123,6 +123,7 @@ class che_방랑 extends Command\GeneralCommand{
refreshNationStaticInfo(); refreshNationStaticInfo();
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+2
View File
@@ -20,6 +20,7 @@ use function\sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_선양 extends Command\GeneralCommand class che_선양 extends Command\GeneralCommand
{ {
@@ -136,6 +137,7 @@ class che_선양 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
$destGeneral->applyDB($db); $destGeneral->applyDB($db);
@@ -13,6 +13,8 @@ use \sammo\{
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_소집해제 extends Command\GeneralCommand{ class che_소집해제 extends Command\GeneralCommand{
static protected $actionName = '소집해제'; static protected $actionName = '소집해제';
@@ -80,6 +82,7 @@ class che_소집해제 extends Command\GeneralCommand{
$general->addDedication($ded); $general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+2 -1
View File
@@ -13,7 +13,7 @@ use \sammo\{
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use function sammo\tryRollbackInheritUniqueItem;
class che_요양 extends Command\GeneralCommand{ class che_요양 extends Command\GeneralCommand{
static protected $actionName = '요양'; static protected $actionName = '요양';
@@ -71,6 +71,7 @@ class che_요양 extends Command\GeneralCommand{
$general->addDedication($ded); $general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
@@ -89,7 +89,7 @@ class che_장비매매 extends Command\GeneralCommand{
else if($itemCode == $general->getVar($itemType)){ else if($itemCode == $general->getVar($itemType)){
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 가지고 있습니다.'); $this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 가지고 있습니다.');
} }
else if($itemType != 'item' && !buildItemClass($general->getVar($itemType))->isBuyable()){ else if(!buildItemClass($general->getVar($itemType))->isBuyable()){
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 진귀한 것을 가지고 있습니다.'); $this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 진귀한 것을 가지고 있습니다.');
} }
} }
+2
View File
@@ -15,6 +15,7 @@ use \sammo\Json;
use function \sammo\searchDistance; use function \sammo\searchDistance;
use function \sammo\printCitiesBasedOnDistance; use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryRollbackInheritUniqueItem;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
@@ -217,6 +218,7 @@ class che_첩보 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1); $general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+6 -4
View File
@@ -31,10 +31,12 @@ class che_탈취 extends che_화계{
$commandName = $this->getName(); $commandName = $this->getName();
$db = DB::db(); $db = DB::db();
// 탈취 최대 800 * 8 * sqrt(1 + (year - startyear) / 5) / 2 // 탈취 최대 800 * 8 * sqrt(1 + (year - startyear) / 4) / 2
$yearCoef = sqrt(1 + ($this->env['year'] - $this->env['startyear']) / 5) / 2; $yearCoef = sqrt(1 + ($this->env['year'] - $this->env['startyear']) / 4) / 2;
$gold = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef; $commRatio = $destCity['comm'] / $destCity['comm_max'];
$rice = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef; $agriRatio = $destCity['agri'] / $destCity['agri_max'];
$gold = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $commRatio / 4);
$rice = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $agriRatio / 4);
if($destCity['supply']){ if($destCity['supply']){
[$destNationGold, $destNationRice] = $db->queryFirstList('SELECT gold,rice FROM nation WHERE nation=%i', $destNationID); [$destNationGold, $destNationRice] = $db->queryFirstList('SELECT gold,rice FROM nation WHERE nation=%i', $destNationID);
+2 -1
View File
@@ -14,7 +14,7 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst; use sammo\CityConst;
use function sammo\tryRollbackInheritUniqueItem;
class che_하야 extends Command\GeneralCommand{ class che_하야 extends Command\GeneralCommand{
static protected $actionName = '하야'; static protected $actionName = '하야';
@@ -104,6 +104,7 @@ class che_하야 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+2 -3
View File
@@ -16,8 +16,7 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst; use sammo\CityConst;
use function sammo\refreshNationStaticInfo; use function sammo\refreshNationStaticInfo;
use function sammo\deleteNation; use function sammo\deleteNation;
use function sammo\tryRollbackInheritUniqueItem;
class che_해산 extends Command\GeneralCommand{ class che_해산 extends Command\GeneralCommand{
static protected $actionName = '해산'; static protected $actionName = '해산';
@@ -96,7 +95,7 @@ class che_해산 extends Command\GeneralCommand{
$oldGeneral->setVar('makelimit', 12); $oldGeneral->setVar('makelimit', 12);
$oldGeneral->applyDB($db); $oldGeneral->applyDB($db);
} }
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+3
View File
@@ -14,6 +14,7 @@ use \sammo\Command;
use function \sammo\searchDistance; use function \sammo\searchDistance;
use function \sammo\printCitiesBasedOnDistance; use function \sammo\printCitiesBasedOnDistance;
use function sammo\tryRollbackInheritUniqueItem;
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
@@ -294,6 +295,7 @@ class che_화계 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return false; return false;
} }
@@ -327,6 +329,7 @@ class che_화계 extends Command\GeneralCommand
$general->increaseRankVar('firenum', 1); $general->increaseRankVar('firenum', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryRollbackInheritUniqueItem($general);
$general->applyDB($db); $general->applyDB($db);
return true; return true;
+3 -1
View File
@@ -7,6 +7,8 @@ use \sammo\JosaUtil;
use \sammo\LastTurn; use \sammo\LastTurn;
use \sammo\DB; use \sammo\DB;
use function sammo\tryRollbackInheritUniqueItem;
class 휴식 extends Command\GeneralCommand{ class 휴식 extends Command\GeneralCommand{
static protected $actionName = '휴식'; static protected $actionName = '휴식';
@@ -39,7 +41,7 @@ class 휴식 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("아무것도 실행하지 않았습니다. <1>$date</>"); $logger->pushGeneralActionLog("아무것도 실행하지 않았습니다. <1>$date</>");
$this->setResultTurn(new LastTurn()); $this->setResultTurn(new LastTurn());
tryRollbackInheritUniqueItem($general);
$general->applyDB(DB::db()); $general->applyDB(DB::db());
return true; return true;
} }
@@ -218,7 +218,7 @@ class che_물자원조 extends Command\NationCommand{
} }
$josaRoSrc = JosaUtil::pick($nationName, '로'); $josaRoSrc = JosaUtil::pick($nationName, '로');
$destNationLogger = new ActionLogger(0, $destChiefID, $year, $month); $destNationLogger = new ActionLogger(0, $destNationID, $year, $month);
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음"); $destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env'); $destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
@@ -33,6 +33,9 @@ class che_피장파장 extends Command\NationCommand{
if(!key_exists('destNationID', $this->arg)){ if(!key_exists('destNationID', $this->arg)){
return false; return false;
} }
if(!key_exists('commandType', $this->arg)){
return false;
}
$destNationID = $this->arg['destNationID']; $destNationID = $this->arg['destNationID'];
$commandType = $this->arg['commandType']; $commandType = $this->arg['commandType'];
+16
View File
@@ -42,6 +42,22 @@ class DummyGeneral extends General{
return $value; return $value;
} }
public function getInheritancePoint(string $key, &$aux = null, bool $forceCalc = false){
return 0;
}
public function setInheritancePoint(string $key, $value, $aux = null){
return;
}
public function increaseInheritancePoint(string $key, $value, $aux = null){
return;
}
public function mergeTotalInheritancePoint(){
return;
}
function applyDB($db):bool{ function applyDB($db):bool{
if($this->logger){ if($this->logger){
$this->initLogger(1, 1); $this->initLogger(1, 1);
+15 -3
View File
@@ -9,9 +9,11 @@ use function sammo\pickGeneralFromPool;
//기존 event_3.php //기존 event_3.php
class CreateManyNPC extends \sammo\Event\Action{ class CreateManyNPC extends \sammo\Event\Action{
protected $npcCount; protected $npcCount;
protected $fillCnt;
protected $avgGen; protected $avgGen;
public function __construct($npcCount = 10){ public function __construct($npcCount = 10, $fillCnt = 0){
$this->npcCount = $npcCount; $this->npcCount = $npcCount;
$this->fillCnt = $fillCnt;
} }
protected function generateNPC($env, int $cnt){ protected function generateNPC($env, int $cnt){
@@ -44,10 +46,20 @@ class CreateManyNPC extends \sammo\Event\Action{
public function run(array $env){ public function run(array $env){
if($this->npcCount <= 0){ if($this->npcCount <= 0 && $this->fillCnt <= 0){
return [__CLASS__, []]; return [__CLASS__, []];
} }
$result = $this->generateNPC($env, $this->npcCount);
$moreGenCnt = 0;
if($this->fillCnt){
$db = DB::db();
$nations = $db->queryFirstColumn('SELECT nation FROM general WHERE npc < 2 AND officer_level = 12');
$regGens = $db->queryFirstField('SELECT count(*) FROM general WHERE nation IN %li AND npc < 4', $nations);
$moreGenCnt = count($nations) * $this->fillCnt - $regGens;
}
$result = $this->generateNPC($env, $this->npcCount + $moreGenCnt);
$logger = new \sammo\ActionLogger(0, 0, $env['year'], $env['month']); $logger = new \sammo\ActionLogger(0, 0, $env['year'], $env['month']);
$genCnt = count($result); $genCnt = count($result);
+451 -343
View File
@@ -5,7 +5,8 @@ namespace sammo;
use sammo\Command\GeneralCommand; use sammo\Command\GeneralCommand;
use sammo\WarUnitTrigger as WarUnitTrigger; use sammo\WarUnitTrigger as WarUnitTrigger;
class General implements iAction{ class General implements iAction
{
use LazyVarUpdater; use LazyVarUpdater;
protected $raw = []; protected $raw = [];
@@ -42,28 +43,28 @@ class General implements iAction{
protected $resultTurn = null; protected $resultTurn = null;
const RANK_COLUMN = [ const RANK_COLUMN = [
'firenum'=>1, 'warnum'=>1, 'killnum'=>1, 'deathnum'=>1, 'killcrew'=>1, 'deathcrew'=>1, 'firenum' => 1, 'warnum' => 1, 'killnum' => 1, 'deathnum' => 1, 'killcrew' => 1, 'deathcrew' => 1,
'ttw'=>1, 'ttd'=>1, 'ttl'=>1, 'ttg'=>1, 'ttp'=>1, 'ttw' => 1, 'ttd' => 1, 'ttl' => 1, 'ttg' => 1, 'ttp' => 1,
'tlw'=>1, 'tld'=>1, 'tll'=>1, 'tlg'=>1, 'tlp'=>1, 'tlw' => 1, 'tld' => 1, 'tll' => 1, 'tlg' => 1, 'tlp' => 1,
'tsw'=>1, 'tsd'=>1, 'tsl'=>1, 'tsg'=>1, 'tsp'=>1, 'tsw' => 1, 'tsd' => 1, 'tsl' => 1, 'tsg' => 1, 'tsp' => 1,
'tiw'=>1, 'tid'=>1, 'til'=>1, 'tig'=>1, 'tip'=>1, 'tiw' => 1, 'tid' => 1, 'til' => 1, 'tig' => 1, 'tip' => 1,
'betwin'=>1, 'betgold'=>1, 'betwingold'=>1, 'betwin' => 1, 'betgold' => 1, 'betwingold' => 1,
'killcrew_person'=>1, 'deathcrew_person'=>1, 'killcrew_person' => 1, 'deathcrew_person' => 1,
'occupied'=>1, 'occupied' => 1,
]; ];
const INHERITANCE_KEY = [ const INHERITANCE_KEY = [
'previous'=>[true, 1, '기존 포인트'], 'previous' => [true, 1, '기존 포인트'],
'lived_month'=>[true, 1, '생존'], 'lived_month' => [true, 1, '생존'],
'max_belong'=>[false, 10, '최대 임관년 수'], 'max_belong' => [false, 10, '최대 임관년 수'],
'max_domestic_critical'=>[true, 1, '최대 연속 내정 성공'], 'max_domestic_critical' => [true, 1, '최대 연속 내정 성공'],
'snipe_combat'=>[true, 10, '병종 상성 우위 횟수'], 'snipe_combat' => [true, 10, '병종 상성 우위 횟수'],
'combat'=>[['rank', 'warnum'], 5, '전투 횟수'], 'combat' => [['rank', 'warnum'], 5, '전투 횟수'],
'sabotage'=>[['rank', 'firenum'], 20, '계략 성공 횟수'], 'sabotage' => [['rank', 'firenum'], 20, '계략 성공 횟수'],
'unifier'=>[true, 1, '천통 기여'], 'unifier' => [true, 1, '천통 기여'],
'dex'=>[false, 0.001, '숙련도'], 'dex' => [false, 0.001, '숙련도'],
'tournament'=>[true, 1, '토너먼트'], 'tournament' => [true, 1, '토너먼트'],
'betting'=>[false, 10, '베팅 당첨'], 'betting' => [false, 10, '베팅 당첨'],
]; ];
const TURNTIME_FULL_MS = -1; const TURNTIME_FULL_MS = -1;
@@ -75,19 +76,19 @@ class General implements iAction{
protected static $prohibitedDirectUpdateVars = [ protected static $prohibitedDirectUpdateVars = [
//Reason: iAction //Reason: iAction
'leadership'=>1, 'leadership' => 1,
'power'=>1, 'power' => 1,
'intel'=>1, 'intel' => 1,
'nation'=>2, 'nation' => 2,
'officer_level'=>1, 'officer_level' => 1,
//NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남. //NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남.
'special'=>1, 'special' => 1,
'special2'=>1, 'special2' => 1,
'personal'=>1, 'personal' => 1,
'horse'=>1, 'horse' => 1,
'weapon'=>1, 'weapon' => 1,
'book'=>1, 'book' => 1,
'item'=>1 'item' => 1
]; ];
@@ -98,10 +99,11 @@ class General implements iAction{
* @param int|null $month 게임 월 * @param int|null $month 게임 월
* @param bool $fullConstruct iAction, 및 ActionLogger 초기화 여부, false인 경우 no, name, city, nation, officer_level 정도로 초기화 가능 * @param bool $fullConstruct iAction, 및 ActionLogger 초기화 여부, false인 경우 no, name, city, nation, officer_level 정도로 초기화 가능
*/ */
public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct=true){ public function __construct(array $raw, ?array $rawRank, ?array $city, ?array $nation, ?int $year, ?int $month, bool $fullConstruct = true)
{
//TODO: 밖에서 가져오도록 하면 버그 확률이 높아짐. 필요한 raw 값을 직접 구해야함. //TODO: 밖에서 가져오도록 하면 버그 확률이 높아짐. 필요한 raw 값을 직접 구해야함.
if($nation === null){ if ($nation === null) {
$nation = getNationStaticInfo($raw['nation']); $nation = getNationStaticInfo($raw['nation']);
} }
@@ -109,20 +111,20 @@ class General implements iAction{
$this->rawCity = $city; $this->rawCity = $city;
$this->resultTurn = new LastTurn(); $this->resultTurn = new LastTurn();
if(key_exists('last_turn', $this->raw)){ if (key_exists('last_turn', $this->raw)) {
$this->lastTurn = LastTurn::fromJson($this->raw['last_turn']); $this->lastTurn = LastTurn::fromJson($this->raw['last_turn']);
$this->resultTurn = $this->lastTurn->duplicate(); $this->resultTurn = $this->lastTurn->duplicate();
} }
if($year !== null && $month !== null){ if ($year !== null && $month !== null) {
$this->initLogger($year, $month); $this->initLogger($year, $month);
} }
if($rawRank){ if ($rawRank) {
$this->rankVarRead = $rawRank; $this->rankVarRead = $rawRank;
} }
if(!$fullConstruct){ if (!$fullConstruct) {
return; return;
} }
@@ -139,15 +141,16 @@ class General implements iAction{
$this->itemObjs['book'] = buildItemClass($raw['book']); $this->itemObjs['book'] = buildItemClass($raw['book']);
$this->itemObjs['item'] = buildItemClass($raw['item']); $this->itemObjs['item'] = buildItemClass($raw['item']);
if(key_exists('aux', $this->raw)){ if (key_exists('aux', $this->raw)) {
$rawInheritBuff = $this->getAuxVar('inheritBuff'); $rawInheritBuff = $this->getAuxVar('inheritBuff');
if($rawInheritBuff !== null){ if ($rawInheritBuff !== null) {
$this->inheritBuffObj = new TriggerInheritBuff($rawInheritBuff); $this->inheritBuffObj = new TriggerInheritBuff($rawInheritBuff);
} }
} }
} }
function initLogger(int $year, int $month){ function initLogger(int $year, int $month)
{
$this->logger = new ActionLogger( $this->logger = new ActionLogger(
$this->getVar('no'), $this->getVar('no'),
$this->getVar('nation'), $this->getVar('nation'),
@@ -157,17 +160,27 @@ class General implements iAction{
); );
} }
function getTurnTime(int $short=self::TURNTIME_FULL_MS){ function getTurnTime(int $short = self::TURNTIME_FULL_MS)
{
return [ return [
self::TURNTIME_FULL_MS=>function($turntime){return $turntime;}, self::TURNTIME_FULL_MS => function ($turntime) {
self::TURNTIME_FULL=>function($turntime){return substr($turntime, 0, 19);}, return $turntime;
self::TURNTIME_HMS=>function($turntime){return substr($turntime, 11, 8);}, },
self::TURNTIME_HM=>function($turntime){return substr($turntime, 11, 5);}, self::TURNTIME_FULL => function ($turntime) {
return substr($turntime, 0, 19);
},
self::TURNTIME_HMS => function ($turntime) {
return substr($turntime, 11, 8);
},
self::TURNTIME_HM => function ($turntime) {
return substr($turntime, 11, 5);
},
][$short]($this->getVar('turntime')); ][$short]($this->getVar('turntime'));
} }
function setItem(string $itemKey='item', ?string $itemCode){ function setItem(string $itemKey = 'item', ?string $itemCode)
if($itemCode === null){ {
if ($itemCode === null) {
$this->deleteItem($itemKey); $this->deleteItem($itemKey);
} }
@@ -175,50 +188,61 @@ class General implements iAction{
$this->itemObjs[$itemKey] = buildItemClass($itemCode); $this->itemObjs[$itemKey] = buildItemClass($itemCode);
} }
function deleteItem(string $itemKey='item'){ function deleteItem(string $itemKey = 'item')
{
$this->setVar($itemKey, 'None'); $this->setVar($itemKey, 'None');
$this->itemObjs[$itemKey] = new ActionItem\None(); $this->itemObjs[$itemKey] = new ActionItem\None();
} }
function getItem(string $itemKey='item'):BaseItem{ function getItem(string $itemKey = 'item'): BaseItem
{
return $this->itemObjs[$itemKey]; return $this->itemObjs[$itemKey];
} }
function getNPCType():int{ function getNPCType(): int
{
return $this->raw['npc']; return $this->raw['npc'];
} }
/** @return BaseItem[] */ /** @return BaseItem[] */
function getItems():array{ function getItems(): array
{
return $this->itemObjs; return $this->itemObjs;
} }
function getPersonality():iAction{ function getPersonality(): iAction
{
return $this->personalityObj; return $this->personalityObj;
} }
function getSpecialDomestic():iAction{ function getSpecialDomestic(): iAction
{
return $this->specialDomesticObj; return $this->specialDomesticObj;
} }
function getSpecialWar():iAction{ function getSpecialWar(): iAction
{
return $this->specialWarObj; return $this->specialWarObj;
} }
function getLastTurn():LastTurn{ function getLastTurn(): LastTurn
{
return $this->lastTurn; return $this->lastTurn;
} }
function _setResultTurn(LastTurn $resultTurn){ function _setResultTurn(LastTurn $resultTurn)
{
$this->resultTurn = $resultTurn; $this->resultTurn = $resultTurn;
} }
function getResultTurn():LastTurn{ function getResultTurn(): LastTurn
{
return $this->resultTurn; return $this->resultTurn;
} }
function clearActivatedSkill(){ function clearActivatedSkill()
foreach ($this->activatedSkill as $skillName=>$state) { {
foreach ($this->activatedSkill as $skillName => $state) {
if (!$state) { if (!$state) {
continue; continue;
} }
@@ -232,86 +256,103 @@ class General implements iAction{
$this->activatedSkill = []; $this->activatedSkill = [];
} }
function getActivatedSkillLog():array{ function getActivatedSkillLog(): array
{
return $this->logActivatedSkill; return $this->logActivatedSkill;
} }
function hasActivatedSkill(string $skillName):bool{ function hasActivatedSkill(string $skillName): bool
{
return $this->activatedSkill[$skillName] ?? false; return $this->activatedSkill[$skillName] ?? false;
} }
function activateSkill(... $skillNames){ function activateSkill(...$skillNames)
foreach($skillNames as $skillName){ {
foreach ($skillNames as $skillName) {
$this->activatedSkill[$skillName] = true; $this->activatedSkill[$skillName] = true;
} }
} }
function deactivateSkill(... $skillNames){ function deactivateSkill(...$skillNames)
foreach($skillNames as $skillName){ {
foreach ($skillNames as $skillName) {
$this->activatedSkill[$skillName] = false; $this->activatedSkill[$skillName] = false;
} }
} }
function getName():string{ function getName(): string
{
return $this->raw['name']; return $this->raw['name'];
} }
function getInfo():string{ function getInfo(): string
{
//iAction용 info로는 적절하지 않음 //iAction용 info로는 적절하지 않음
return ''; return '';
} }
function getID():int{ function getID(): int
{
return $this->raw['no']; return $this->raw['no'];
} }
function getRawCity():?array{ function getRawCity(): ?array
{
return $this->rawCity; return $this->rawCity;
} }
function setRawCity(?array $city){ function setRawCity(?array $city)
{
$this->rawCity = $city; $this->rawCity = $city;
} }
function getCityID():int{ function getCityID(): int
{
return $this->raw['city']; return $this->raw['city'];
} }
function getNationID():int{ function getNationID(): int
{
return $this->raw['nation']; return $this->raw['nation'];
} }
function getStaticNation():array{ function getStaticNation(): array
{
return getNationStaticInfo($this->raw['nation']); return getNationStaticInfo($this->raw['nation']);
} }
function getLogger():?ActionLogger{ function getLogger(): ?ActionLogger
{
return $this->logger; return $this->logger;
} }
public function getNationTypeObj():iAction{ public function getNationTypeObj(): iAction
{
return $this->nationType; return $this->nationType;
} }
public function getOfficerLevelObj():iAction{ public function getOfficerLevelObj(): iAction
{
return $this->officerLevelObj; return $this->officerLevelObj;
} }
function getCrewTypeObj():GameUnitDetail{ function getCrewTypeObj(): GameUnitDetail
{
$crewType = GameUnitConst::byID($this->getVar('crewtype')); $crewType = GameUnitConst::byID($this->getVar('crewtype'));
if($crewType === null){ if ($crewType === null) {
throw new \InvalidArgumentException('Invalid CrewType:'.$this->getVar('crewtype')); throw new \InvalidArgumentException('Invalid CrewType:' . $this->getVar('crewtype'));
} }
return $crewType; return $crewType;
} }
function calcRecentWarTurn(int $turnTerm):int{ function calcRecentWarTurn(int $turnTerm): int
{
$cacheKey = "recent_war_turn_{$turnTerm}"; $cacheKey = "recent_war_turn_{$turnTerm}";
if(key_exists($cacheKey, $this->calcCache)){ if (key_exists($cacheKey, $this->calcCache)) {
return $this->calcCache[$cacheKey]; return $this->calcCache[$cacheKey];
} }
if(!$this->getVar('recent_war')){ if (!$this->getVar('recent_war')) {
$result = 12*1000; $result = 12 * 1000;
$this->calcCache[$cacheKey] = $result; $this->calcCache[$cacheKey] = $result;
return $result; return $result;
} }
@@ -319,7 +360,7 @@ class General implements iAction{
$turnNow = new \DateTimeImmutable($this->getVar('turntime')); $turnNow = new \DateTimeImmutable($this->getVar('turntime'));
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow)); $secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow));
if($secDiff <= 0){ if ($secDiff <= 0) {
$this->calcCache[$cacheKey] = 0; $this->calcCache[$cacheKey] = 0;
return 0; return 0;
} }
@@ -329,13 +370,14 @@ class General implements iAction{
return $result; return $result;
} }
function getReservedTurn(int $turnIdx, array $env):GeneralCommand{ function getReservedTurn(int $turnIdx, array $env): GeneralCommand
{
$db = DB::db(); $db = DB::db();
$rawCmd = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND turn_idx = %i', $this->getID(), $turnIdx); $rawCmd = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND turn_idx = %i', $this->getID(), $turnIdx);
if(!$rawCmd){ if (!$rawCmd) {
return buildGeneralCommandClass(null, $this, $env); return buildGeneralCommandClass(null, $this, $env);
} }
return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null)); return buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg'] ?? null));
} }
/** /**
@@ -345,13 +387,14 @@ class General implements iAction{
* @param array $env * @param array $env
* @return GeneralCommand[] * @return GeneralCommand[]
*/ */
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env){ public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env)
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){ {
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom); if ($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn) {
throw new \OutOfRangeException('$turnIdxFrom 범위 초과' . $turnIdxFrom);
} }
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){ if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo); throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
} }
$db = DB::db(); $db = DB::db();
@@ -362,15 +405,15 @@ class General implements iAction{
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND %i <= turn_idx AND turn_idx < %i ORDER BY turn_idx ASC', $generalID, $turnIdxFrom, $turnIdxTo); $rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id = %i AND %i <= turn_idx AND turn_idx < %i ORDER BY turn_idx ASC', $generalID, $turnIdxFrom, $turnIdxTo);
if(!$rawCmds){ if (!$rawCmds) {
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){ foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
$result[$turnIdx] = buildGeneralCommandClass(null, $this, $env); $result[$turnIdx] = buildGeneralCommandClass(null, $this, $env);
} }
return $result; return $result;
} }
foreach($rawCmds as $turnIdx=>$rawCmd){ foreach ($rawCmds as $turnIdx => $rawCmd) {
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null)); $result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg'] ?? null));
} }
return $result; return $result;
@@ -388,11 +431,12 @@ class General implements iAction{
* @return int|float 계산된 능력치 * @return int|float 계산된 능력치
*/ */
protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{ protected function getStatValue(string $statName, $withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
$cKey = "{$statName}_{$withInjury}_{$withIActionObj}_{$withStatAdjust}"; $cKey = "{$statName}_{$withInjury}_{$withIActionObj}_{$withStatAdjust}";
if(key_exists($cKey, $this->calcCache)){ if (key_exists($cKey, $this->calcCache)) {
$statValue = $this->calcCache[$cKey]; $statValue = $this->calcCache[$cKey];
if($useFloor){ if ($useFloor) {
return Util::toInt($statValue); return Util::toInt($statValue);
} }
return $statValue; return $statValue;
@@ -400,35 +444,34 @@ class General implements iAction{
$statValue = $this->getVar($statName); $statValue = $this->getVar($statName);
if($withInjury){ if ($withInjury) {
$statValue *= (100 - $this->getVar('injury')) / 100; $statValue *= (100 - $this->getVar('injury')) / 100;
} }
if($withStatAdjust){ if ($withStatAdjust) {
if($statName === 'strength'){ if ($statName === 'strength') {
$statValue += Util::round($this->getStatValue('intel', $withInjury, $withIActionObj, false, false) / 4); $statValue += Util::round($this->getStatValue('intel', $withInjury, $withIActionObj, false, false) / 4);
} } else if ($statName === 'intel') {
else if($statName === 'intel'){
$statValue += Util::round($this->getStatValue('strength', $withInjury, $withIActionObj, false, false) / 4); $statValue += Util::round($this->getStatValue('strength', $withInjury, $withIActionObj, false, false) / 4);
} }
} }
if($withIActionObj){ if ($withIActionObj) {
foreach([ foreach ([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
$this->specialWarObj, $this->specialWarObj,
$this->personalityObj, $this->personalityObj,
$this->inheritBuffObj, $this->inheritBuffObj,
] as $actionObj){ ] as $actionObj) {
if($actionObj !== null){ if ($actionObj !== null) {
$statValue = $actionObj->onCalcStat($this, $statName, $statValue); $statValue = $actionObj->onCalcStat($this, $statName, $statValue);
} }
} }
foreach($this->itemObjs as $actionObj){ foreach ($this->itemObjs as $actionObj) {
if($actionObj !== null){ if ($actionObj !== null) {
$statValue = $actionObj->onCalcStat($this, $statName, $statValue); $statValue = $actionObj->onCalcStat($this, $statName, $statValue);
} }
} }
@@ -436,54 +479,58 @@ class General implements iAction{
$this->calcCache[$cKey] = $statValue; $this->calcCache[$cKey] = $statValue;
if($useFloor){ if ($useFloor) {
return Util::toInt($statValue); return Util::toInt($statValue);
} }
return $statValue; return $statValue;
} }
function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{ function getLeadership($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('leadership', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); return $this->getStatValue('leadership', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
} }
function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{ function getStrength($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('strength', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); return $this->getStatValue('strength', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
} }
function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true):float{ function getIntel($withInjury = true, $withIActionObj = true, $withStatAdjust = true, $useFloor = true): float
{
return $this->getStatValue('intel', $withInjury, $withIActionObj, $withStatAdjust, $useFloor); return $this->getStatValue('intel', $withInjury, $withIActionObj, $withStatAdjust, $useFloor);
} }
function getDex(GameUnitDetail $crewType){ function getDex(GameUnitDetail $crewType)
{
$armType = $crewType->armType; $armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){ if ($armType == GameUnitConst::T_CASTLE) {
$armType = GameUnitConst::T_SIEGE; $armType = GameUnitConst::T_SIEGE;
} }
return $this->getVar("dex{$armType}"); return $this->getVar("dex{$armType}");
} }
function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos=false){ function addDex(GameUnitDetail $crewType, float $exp, bool $affectTrainAtmos = false)
{
$armType = $crewType->armType; $armType = $crewType->armType;
if($armType == GameUnitConst::T_CASTLE){ if ($armType == GameUnitConst::T_CASTLE) {
$armType = GameUnitConst::T_SIEGE; $armType = GameUnitConst::T_SIEGE;
} }
if($armType < 0){ if ($armType < 0) {
return; return;
} }
if($armType == GameUnitConst::T_WIZARD) { if ($armType == GameUnitConst::T_WIZARD) {
$exp *= 0.9; $exp *= 0.9;
} } else if ($armType == GameUnitConst::T_SIEGE) {
else if($armType == GameUnitConst::T_SIEGE) {
$exp *= 0.9; $exp *= 0.9;
} }
if($affectTrainAtmos){ if ($affectTrainAtmos) {
$exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200; $exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200;
} }
@@ -492,39 +539,39 @@ class General implements iAction{
$this->increaseVar($dexType, $exp); $this->increaseVar($dexType, $exp);
} }
function addExperience(float $experience, bool $affectTrigger=true){ function addExperience(float $experience, bool $affectTrigger = true)
if($affectTrigger){ {
if ($affectTrigger) {
$experience = $this->onCalcStat($this, 'experience', $experience); $experience = $this->onCalcStat($this, 'experience', $experience);
} }
$this->increaseVar('experience', $experience); $this->increaseVar('experience', $experience);
$nextExpLevel = getExpLevel($this->getVar('experience')); $nextExpLevel = getExpLevel($this->getVar('experience'));
$comp = $nextExpLevel <=> $this->getVar('explevel'); $comp = $nextExpLevel <=> $this->getVar('explevel');
if($comp === 0){ if ($comp === 0) {
return; return;
} }
$this->updateVar('explevel', $nextExpLevel); $this->updateVar('explevel', $nextExpLevel);
$josaRo = JosaUtil::pick($nextExpLevel, '로'); $josaRo = JosaUtil::pick($nextExpLevel, '로');
if($comp > 0){ if ($comp > 0) {
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN); $this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN);
} } else {
else{
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN); $this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN);
} }
} }
function addDedication(float $dedication, bool $affectTrigger=true){ function addDedication(float $dedication, bool $affectTrigger = true)
if($affectTrigger){ {
if ($affectTrigger) {
$dedication = $this->onCalcStat($this, 'dedication', $dedication); $dedication = $this->onCalcStat($this, 'dedication', $dedication);
} }
$this->increaseVar('dedication', $dedication); $this->increaseVar('dedication', $dedication);
$nextDedLevel = getDedLevel($this->getVar('dedication')); $nextDedLevel = getDedLevel($this->getVar('dedication'));
$comp = $nextDedLevel <=> $this->getVar('dedlevel'); $comp = $nextDedLevel <=> $this->getVar('dedlevel');
if($comp === 0){ if ($comp === 0) {
return; return;
} }
@@ -534,20 +581,19 @@ class General implements iAction{
$billText = number_format(getBillByLevel($nextDedLevel)); $billText = number_format(getBillByLevel($nextDedLevel));
$josaRoDed = JosaUtil::pick($dedLevelText, '로'); $josaRoDed = JosaUtil::pick($dedLevelText, '로');
$josaRoBill = JosaUtil::pick($billText, '로'); $josaRoBill = JosaUtil::pick($billText, '로');
if($comp > 0){ if ($comp > 0) {
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <C>승급</>하여 봉록이 <C>{$billText}</>{$josaRoBill} <C>상승</>했습니다!", ActionLogger::PLAIN); $this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <C>승급</>하여 봉록이 <C>{$billText}</>{$josaRoBill} <C>상승</>했습니다!", ActionLogger::PLAIN);
} } else {
else{
$this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <R>강등</>되어 봉록이 <C>{$billText}</>{$josaRoBill} <R>하락</>했습니다!", ActionLogger::PLAIN); $this->getLogger()->pushGeneralActionLog("<Y>{$dedLevelText}</>{$josaRoDed} <R>강등</>되어 봉록이 <C>{$billText}</>{$josaRoBill} <R>하락</>했습니다!", ActionLogger::PLAIN);
} }
} }
function updateVar(string $key, $value){ function updateVar(string $key, $value)
if(($this->raw[$key]??null) === $value){ {
if (($this->raw[$key] ?? null) === $value) {
return; return;
} }
if(!key_exists($key, $this->updatedVar)){ if (!key_exists($key, $this->updatedVar)) {
$this->updatedVar[$key] = true; $this->updatedVar[$key] = true;
} }
$this->raw[$key] = $value; $this->raw[$key] = $value;
@@ -557,39 +603,81 @@ class General implements iAction{
/** /**
* @param \MeekroDB $db * @param \MeekroDB $db
*/ */
function kill($db, bool $sendDyingMessage=true, ?string $dyingMessage=null){ function kill($db, bool $sendDyingMessage = true, ?string $dyingMessage = null)
{
$generalID = $this->getID(); $generalID = $this->getID();
$logger = $this->getLogger(); $logger = $this->getLogger();
$generalName = $this->getName(); $generalName = $this->getName();
$this->mergeTotalInheritancePoint(); //유산포인트 관련 항목 환불
if ($this->getNPCType() < 2) {
$refundPoint = 0;
$userID = $this->getVar('owner');
$userLogger = new UserLogger($userID);
if ($this->getAuxVar('inheritRandomUnique')) {
$this->setAuxVar('inheritRandomUnique', null);
$userLogger->push(sprintf("사망으로 랜덤 유니크 구입 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
$refundPoint += GameConst::$inheritItemRandomPoint;
}
$itemTrials = $this->getAuxVar('inheritUniqueTrial') ?? [];
foreach (array_keys($itemTrials) as $itemKey) {
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
$ownTrial = $trialStor->getValue("u{$userID}");
$itemObj = buildItemClass($itemKey);
$itemName = $itemObj->getName();
if (!$ownTrial) {
continue;
}
[,, $amount] = $ownTrial;
$trialStor->deleteValue("u{$userID}");
$userLogger->push("사망으로 {$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
$refundPoint += $amount;
}
if($this->getAuxVar('inheritSpecificSpecialWar')){
$this->setAuxVar('inheritSpecificSpecialWar', null);
$userLogger->push(sprintf("사망으로 전투 특기 지정 %d 포인트 반환", GameConst::$inheritSpecificSpecialPoint), "inheritPoint");
$refundPoint += GameConst::$inheritSpecificSpecialPoint;
}
if ($refundPoint > 0) {
$this->increaseInheritancePoint('previous', $refundPoint);
}
$this->mergeTotalInheritancePoint();
}
// 군주였으면 유지 이음 // 군주였으면 유지 이음
$officerLevel = $this->getVar('officer_level'); $officerLevel = $this->getVar('officer_level');
if($officerLevel == 12) { if ($officerLevel == 12) {
nextRuler($this); nextRuler($this);
$this->setVar('officer_level', 1); $this->setVar('officer_level', 1);
} }
// 부대 처리 // 부대 처리
$troopLeaderID = $this->getVar('troop'); $troopLeaderID = $this->getVar('troop');
if($troopLeaderID == $generalID){ if ($troopLeaderID == $generalID) {
//부대장일 경우 //부대장일 경우
// 모두 탈퇴 // 모두 탈퇴
$db->update('general', [ $db->update('general', [
'troop'=>0 'troop' => 0
], 'troop=%i', $troopLeaderID); ], 'troop=%i', $troopLeaderID);
// 부대 삭제 // 부대 삭제
$db->delete('troop', 'troop_leader=%i', $troopLeaderID); $db->delete('troop', 'troop_leader=%i', $troopLeaderID);
} }
if($sendDyingMessage){ if ($sendDyingMessage) {
if($dyingMessage){ if ($dyingMessage) {
$logger->pushGlobalActionLog($dyingMessage); $logger->pushGlobalActionLog($dyingMessage);
} } else {
else{
$dyingMessageObj = new TextDecoration\DyingMessage($this); $dyingMessageObj = new TextDecoration\DyingMessage($this);
$logger->pushGlobalActionLog($dyingMessageObj->getText()); $logger->pushGlobalActionLog($dyingMessageObj->getText());
} }
@@ -597,9 +685,9 @@ class General implements iAction{
} }
$db->update('select_pool', [ $db->update('select_pool', [
'general_id'=>null, 'general_id' => null,
'owner'=>null, 'owner' => null,
'reserved_until'=>null, 'reserved_until' => null,
], 'general_id=%i', $generalID); ], 'general_id=%i', $generalID);
$db->delete('general', 'no=%i', $generalID); $db->delete('general', 'no=%i', $generalID);
@@ -609,17 +697,18 @@ class General implements iAction{
$this->updatedVar = []; $this->updatedVar = [];
$db->update('nation', [ $db->update('nation', [
'gennum'=>$db->sqleval('gennum - 1') 'gennum' => $db->sqleval('gennum - 1')
], 'nation=%i', $this->getVar('nation')); ], 'nation=%i', $this->getVar('nation'));
} }
function rebirth(){ function rebirth()
{
$logger = $this->getLogger(); $logger = $this->getLogger();
$generalName = $this->getName(); $generalName = $this->getName();
$ownerID = $this->getVar('owner'); $ownerID = $this->getVar('owner');
if($ownerID){ if ($ownerID) {
$this->mergeTotalInheritancePoint(); $this->mergeTotalInheritancePoint();
resetInheritanceUser($ownerID, true); resetInheritanceUser($ownerID, true);
} }
@@ -639,7 +728,7 @@ class General implements iAction{
$this->multiplyVar('dex4', 0.5); $this->multiplyVar('dex4', 0.5);
$this->multiplyVar('dex5', 0.5); $this->multiplyVar('dex5', 0.5);
foreach(array_keys(static::RANK_COLUMN) as $rankKey){ foreach (array_keys(static::RANK_COLUMN) as $rankKey) {
$this->setRankVar($rankKey, 0); $this->setRankVar($rankKey, 0);
} }
@@ -649,23 +738,24 @@ class General implements iAction{
$logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌'); $logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌');
} }
function increaseRankVar(string $key, int $value){ function increaseRankVar(string $key, int $value)
if(!key_exists($key, static::RANK_COLUMN)){ {
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
} }
if(key_exists($key, $this->rankVarSet)){ if (key_exists($key, $this->rankVarSet)) {
$this->rankVarSet[$key] += $value; $this->rankVarSet[$key] += $value;
return; return;
} }
if(key_exists($key, $this->rankVarRead)){ if (key_exists($key, $this->rankVarRead)) {
$this->rankVarSet[$key] = $this->rankVarRead[$key] + $value; $this->rankVarSet[$key] = $this->rankVarRead[$key] + $value;
unset($this->rankVarRead[$key]); unset($this->rankVarRead[$key]);
return; return;
} }
if(key_exists($key, $this->rankVarIncrease)){ if (key_exists($key, $this->rankVarIncrease)) {
$this->rankVarIncrease[$key] += $value; $this->rankVarIncrease[$key] += $value;
return; return;
} }
@@ -673,31 +763,32 @@ class General implements iAction{
$this->rankVarIncrease[$key] = $value; $this->rankVarIncrease[$key] = $value;
} }
function setRankVar(string $key, int $value){ function setRankVar(string $key, int $value)
if(!key_exists($key, static::RANK_COLUMN)){ {
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
} }
if(key_exists($key, $this->rankVarRead)){ if (key_exists($key, $this->rankVarRead)) {
unset($this->rankVarRead[$key]); unset($this->rankVarRead[$key]);
} } else if (key_exists($key, $this->rankVarIncrease)) {
else if(key_exists($key, $this->rankVarIncrease)){
unset($this->rankVarIncrease[$key]); unset($this->rankVarIncrease[$key]);
} }
$this->rankVarSet[$key]=$value; $this->rankVarSet[$key] = $value;
} }
function getRankVar(string $key):int{ function getRankVar(string $key): int
if(!key_exists($key, static::RANK_COLUMN)){ {
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key); if (!key_exists($key, static::RANK_COLUMN)) {
throw new \InvalidArgumentException('올바르지 않은 인자 :' . $key);
} }
if(key_exists($key, $this->rankVarSet)){ if (key_exists($key, $this->rankVarSet)) {
return $this->rankVarSet[$key]; return $this->rankVarSet[$key];
} }
if(!key_exists($key, $this->rankVarRead)){ if (!key_exists($key, $this->rankVarRead)) {
throw new \RuntimeException('인자가 없음 : '.$key); throw new \RuntimeException('인자가 없음 : ' . $key);
} }
return $this->rankVarRead[$key]; return $this->rankVarRead[$key];
@@ -706,8 +797,9 @@ class General implements iAction{
/** /**
* @param \MeekroDB $db * @param \MeekroDB $db
*/ */
function applyDB($db):bool{ function applyDB($db): bool
if($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()){ {
if ($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()) {
$this->setVar('last_turn', $this->getResultTurn()->toJson()); $this->setVar('last_turn', $this->getResultTurn()->toJson());
} }
$updateVals = $this->getUpdatedValues(); $updateVals = $this->getUpdatedValues();
@@ -716,31 +808,31 @@ class General implements iAction{
$generalID = $this->getID(); $generalID = $this->getID();
$result = false; $result = false;
if($updateVals){ if ($updateVals) {
$db->update('general', $updateVals, 'no=%i', $generalID); $db->update('general', $updateVals, 'no=%i', $generalID);
$result = $result || $db->affectedRows() > 0; $result = $result || $db->affectedRows() > 0;
if(key_exists('nation', $updateVals)){ if (key_exists('nation', $updateVals)) {
$db->update('rank_data', [ $db->update('rank_data', [
'nation_id'=>$updateVals['nation'] 'nation_id' => $updateVals['nation']
], 'general_id = %i', $generalID); ], 'general_id = %i', $generalID);
$result = true; $result = true;
} }
$this->flushUpdateValues(); $this->flushUpdateValues();
} }
if($this->rankVarIncrease){ if ($this->rankVarIncrease) {
foreach($this->rankVarIncrease as $rankKey => $rankVal){ foreach ($this->rankVarIncrease as $rankKey => $rankVal) {
$db->update('rank_data', [ $db->update('rank_data', [
'value'=>$db->sqleval('value + %i', $rankVal) 'value' => $db->sqleval('value + %i', $rankVal)
], 'general_id = %i AND type = %s', $generalID, $rankKey); ], 'general_id = %i AND type = %s', $generalID, $rankKey);
} }
$result = true; $result = true;
} }
if($this->rankVarSet){ if ($this->rankVarSet) {
foreach($this->rankVarSet as $rankKey => $rankVal){ foreach ($this->rankVarSet as $rankKey => $rankVal) {
$db->update('rank_data', [ $db->update('rank_data', [
'value'=>$rankVal 'value' => $rankVal
], 'general_id = %i AND type = %s', $generalID, $rankKey); ], 'general_id = %i AND type = %s', $generalID, $rankKey);
$this->rankVarRead[$rankKey] = $rankVal; $this->rankVarRead[$rankKey] = $rankVal;
} }
@@ -754,7 +846,8 @@ class General implements iAction{
return $result; return $result;
} }
function checkStatChange():bool{ function checkStatChange(): bool
{
$logger = $this->getLogger(); $logger = $this->getLogger();
$limit = GameConst::$upgradeLimit; $limit = GameConst::$upgradeLimit;
@@ -766,16 +859,15 @@ class General implements iAction{
$result = false; $result = false;
foreach($table as [$statNickName, $statName]){ foreach ($table as [$statNickName, $statName]) {
$statExpName = $statName.'_exp'; $statExpName = $statName . '_exp';
if($this->getVar($statExpName) < 0){ if ($this->getVar($statExpName) < 0) {
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN); $logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, $limit); $this->increaseVar($statExpName, $limit);
$this->increaseVar($statName, -1); $this->increaseVar($statName, -1);
$result = true; $result = true;
} } else if ($this->getVar($statExpName) >= $limit) {
else if($this->getVar($statExpName) >= $limit){
$logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN); $logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
$this->increaseVar($statExpName, -$limit); $this->increaseVar($statExpName, -$limit);
$this->increaseVar($statName, 1); $this->increaseVar($statName, 1);
@@ -786,9 +878,10 @@ class General implements iAction{
return $result; return $result;
} }
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
{
$caller = new GeneralTriggerCaller(); $caller = new GeneralTriggerCaller();
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -796,9 +889,9 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -807,8 +900,9 @@ class General implements iAction{
return $caller; return $caller;
} }
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
foreach(array_merge([ {
foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -816,8 +910,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -826,9 +920,10 @@ class General implements iAction{
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){ public function onCalcStat(General $general, string $statName, $value, $aux = null)
{
//xxx: $general? //xxx: $general?
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -836,8 +931,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -846,9 +941,10 @@ class General implements iAction{
return $value; return $value;
} }
public function onCalcOpposeStat(General $general, string $statName, $value, $aux=null){ public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
{
//xxx: $general? //xxx: $general?
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -856,8 +952,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -866,8 +962,9 @@ class General implements iAction{
return $value; return $value;
} }
public function onCalcStrategic(string $turnType, string $varType, $value){ public function onCalcStrategic(string $turnType, string $varType, $value)
foreach(array_merge([ {
foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -875,8 +972,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -885,8 +982,9 @@ class General implements iAction{
return $value; return $value;
} }
public function onCalcNationalIncome(string $type, $amount){ public function onCalcNationalIncome(string $type, $amount)
foreach(array_merge([ {
foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -894,8 +992,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -904,11 +1002,12 @@ class General implements iAction{
return $amount; return $amount;
} }
public function getWarPowerMultiplier(WarUnit $unit):array{ public function getWarPowerMultiplier(WarUnit $unit): array
{
//xxx:$unit //xxx:$unit
$att = 1; $att = 1;
$def = 1; $def = 1;
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -916,8 +1015,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -927,9 +1026,10 @@ class General implements iAction{
} }
return [$att, $def]; return [$att, $def];
} }
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
$caller = new WarUnitTriggerCaller(); $caller = new WarUnitTriggerCaller();
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -937,8 +1037,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -947,7 +1047,8 @@ class General implements iAction{
return $caller; return $caller;
} }
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
{
$caller = new WarUnitTriggerCaller( $caller = new WarUnitTriggerCaller(
new WarUnitTrigger\che_필살시도($unit), new WarUnitTrigger\che_필살시도($unit),
new WarUnitTrigger\che_필살발동($unit), new WarUnitTrigger\che_필살발동($unit),
@@ -957,7 +1058,7 @@ class General implements iAction{
new WarUnitTrigger\che_계략발동($unit), new WarUnitTrigger\che_계략발동($unit),
new WarUnitTrigger\che_계략실패($unit) new WarUnitTrigger\che_계략실패($unit)
); );
foreach(array_merge([ foreach (array_merge([
$this->nationType, $this->nationType,
$this->officerLevelObj, $this->officerLevelObj,
$this->specialDomesticObj, $this->specialDomesticObj,
@@ -965,8 +1066,8 @@ class General implements iAction{
$this->personalityObj, $this->personalityObj,
$this->getCrewTypeObj(), $this->getCrewTypeObj(),
$this->inheritBuffObj, $this->inheritBuffObj,
], $this->itemObjs) as $iObj){ ], $this->itemObjs) as $iObj) {
if(!$iObj){ if (!$iObj) {
continue; continue;
} }
/** @var iAction $iObj */ /** @var iAction $iObj */
@@ -976,12 +1077,13 @@ class General implements iAction{
return $caller; return $caller;
} }
static public function mergeQueryColumn(?array $reqColumns=null, int $constructMode=2):array{ static public function mergeQueryColumn(?array $reqColumns = null, int $constructMode = 2): array
{
$minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city']; $minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city'];
$defaultEventColumn = [ $defaultEventColumn = [
'no', 'name', 'owner', 'city', 'nation', 'officer_level', 'officer_city', 'no', 'name', 'owner', 'city', 'nation', 'officer_level', 'officer_city',
'special', 'special2', 'personal', 'special', 'special2', 'personal',
'horse', 'weapon', 'book', 'item', 'last_turn' 'horse', 'weapon', 'book', 'item', 'last_turn', 'aux',
]; ];
$fullColumn = [ $fullColumn = [
'no', 'name', 'owner', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity', 'no', 'name', 'owner', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity',
@@ -994,22 +1096,21 @@ class General implements iAction{
'specage', 'specage2', 'con', 'connect', 'aux', 'lastrefresh', 'specage', 'specage2', 'con', 'connect', 'aux', 'lastrefresh',
]; ];
if($reqColumns === null){ if ($reqColumns === null) {
return [$fullColumn, array_keys(static::RANK_COLUMN)]; return [$fullColumn, array_keys(static::RANK_COLUMN)];
} }
$rankColumn = []; $rankColumn = [];
$subColumn = []; $subColumn = [];
foreach($reqColumns as $column){ foreach ($reqColumns as $column) {
if(key_exists($column, static::RANK_COLUMN)){ if (key_exists($column, static::RANK_COLUMN)) {
$rankColumn[] = $column; $rankColumn[] = $column;
} } else {
else{
$subColumn[] = $column; $subColumn[] = $column;
} }
} }
if($constructMode > 1){ if ($constructMode > 1) {
return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn]; return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn];
} }
@@ -1023,31 +1124,30 @@ class General implements iAction{
* @return \sammo\General[] * @return \sammo\General[]
* @throws MustNotBeReachedException * @throws MustNotBeReachedException
*/ */
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column=null, int $constructMode=2):array{ static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column = null, int $constructMode = 2): array
if($generalIDList === []){ {
if ($generalIDList === []) {
return []; return [];
} }
$db = DB::db(); $db = DB::db();
if($constructMode > 0){ if ($constructMode > 0) {
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']); [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
} } else {
else{
$year = null; $year = null;
$month = null; $month = null;
} }
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode); [$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
if($generalIDList === null){ if ($generalIDList === null) {
$rawGenerals = Util::convertArrayToDict( $rawGenerals = Util::convertArrayToDict(
$db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)), $db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)),
'no' 'no'
); );
$generalIDList = array_keys($rawGenerals); $generalIDList = array_keys($rawGenerals);
} } else {
else{
$rawGenerals = Util::convertArrayToDict( $rawGenerals = Util::convertArrayToDict(
$db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList), $db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList),
'no' 'no'
@@ -1056,14 +1156,14 @@ class General implements iAction{
$rawRanks = []; $rawRanks = [];
if($rankColumn){ if ($rankColumn) {
$rawValue = $db->queryAllLists( $rawValue = $db->queryAllLists(
'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls', 'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls',
$generalIDList, $generalIDList,
$rankColumn $rankColumn
); );
foreach($rawValue as [$generalID, $rankType, $rankValue]){ foreach ($rawValue as [$generalID, $rankType, $rankValue]) {
if(!key_exists($generalID, $rawRanks)){ if (!key_exists($generalID, $rawRanks)) {
$rawRanks[$generalID] = []; $rawRanks[$generalID] = [];
} }
$rawRanks[$generalID][$rankType] = $rankValue; $rawRanks[$generalID][$rankType] = $rankValue;
@@ -1071,27 +1171,27 @@ class General implements iAction{
} }
$result = []; $result = [];
foreach($generalIDList as $generalID){ foreach ($generalIDList as $generalID) {
if(!key_exists($generalID, $rawGenerals)){ if (!key_exists($generalID, $rawGenerals)) {
$result[$generalID] = new DummyGeneral($constructMode > 0); $result[$generalID] = new DummyGeneral($constructMode > 0);
continue; continue;
} }
if(key_exists($generalID, $rawRanks) && count($rawRanks[$generalID]??[]) !== count($rankColumn)){ if (key_exists($generalID, $rawRanks) && count($rawRanks[$generalID] ?? []) !== count($rankColumn)) {
throw new \RuntimeException('column의 수가 일치하지 않음 : '.$generalID); throw new \RuntimeException('column의 수가 일치하지 않음 : ' . $generalID);
} }
$result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID]??null, null, null, $year, $month, $constructMode > 1); $result[$generalID] = new static($rawGenerals[$generalID], $rawRanks[$generalID] ?? null, null, null, $year, $month, $constructMode > 1);
} }
return $result; return $result;
} }
static public function createGeneralObjFromDB(int $generalID, ?array $column=null, int $constructMode=2):self{ static public function createGeneralObjFromDB(int $generalID, ?array $column = null, int $constructMode = 2): self
{
$db = DB::db(); $db = DB::db();
if($constructMode > 0){ if ($constructMode > 0) {
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']); [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
} } else {
else{
$year = null; $year = null;
$month = null; $month = null;
} }
@@ -1099,14 +1199,14 @@ class General implements iAction{
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode); [$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
$rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID); $rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
if(!$rawGeneral){ if (!$rawGeneral) {
return new DummyGeneral($constructMode > 0); return new DummyGeneral($constructMode > 0);
} }
$rawRankValues = []; $rawRankValues = [];
if($rankColumn){ if ($rankColumn) {
$rawValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $generalID, $rankColumn); $rawValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $generalID, $rankColumn);
foreach($rawValue as [$rankType, $rankValue]){ foreach ($rawValue as [$rankType, $rankValue]) {
$rawRankValues[$rankType] = $rankValue; $rawRankValues[$rankType] = $rankValue;
} }
} }
@@ -1123,21 +1223,22 @@ class General implements iAction{
* @param array $env * @param array $env
* @return GeneralCommand[] * @return GeneralCommand[]
*/ */
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env){ static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env)
if(!$generalList){ {
if (!$generalList) {
return []; return [];
} }
$generalIDList = array_map(function(General $general){ $generalIDList = array_map(function (General $general) {
return $general->getID(); return $general->getID();
}, $generalList); }, $generalList);
$db = DB::db(); $db = DB::db();
$result = []; $result = [];
$rawCmds = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = %i', $generalIDList, $turnIdx), 'general_id'); $rawCmds = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = %i', $generalIDList, $turnIdx), 'general_id');
foreach($generalList as $general){ foreach ($generalList as $general) {
$generalID = $general->getID(); $generalID = $general->getID();
if(!key_exists($generalID, $rawCmds)){ if (!key_exists($generalID, $rawCmds)) {
$result[$generalID] = buildGeneralCommandClass(null, $general, $env); $result[$generalID] = buildGeneralCommandClass(null, $general, $env);
continue; continue;
} }
@@ -1154,21 +1255,22 @@ class General implements iAction{
* @param array $env * @param array $env
* @return GeneralCommand[][] * @return GeneralCommand[][]
*/ */
static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env){ static public function getReservedTurnListByGeneralList(array $generalList, int $turnIdxFrom, int $turnIdxTo, array $env)
{
//XXX: static인데 return값이 General이 아니라고?? GeneralCommandHelper같은게 있어야하지 않을까? //XXX: static인데 return값이 General이 아니라고?? GeneralCommandHelper같은게 있어야하지 않을까?
if(!$generalList){ if (!$generalList) {
return []; return [];
} }
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){ if ($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn) {
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom); throw new \OutOfRangeException('$turnIdxFrom 범위 초과' . $turnIdxFrom);
} }
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){ if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo); throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
} }
$generalIDList = array_map(function(General $general){ $generalIDList = array_map(function (General $general) {
return $general->getID(); return $general->getID();
}, $generalList); }, $generalList);
@@ -1176,26 +1278,26 @@ class General implements iAction{
$rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id IN %i AND %i <= turn_idx AND turn_idx < %i ORDER BY general_id ASC, turn_idx ASC', $generalIDList, $turnIdxFrom, $turnIdxTo); $rawCmds = $db->queryFirstRow('SELECT * FROM general_turn WHERE general_id IN %i AND %i <= turn_idx AND turn_idx < %i ORDER BY general_id ASC, turn_idx ASC', $generalIDList, $turnIdxFrom, $turnIdxTo);
$orderedRawCmds = []; $orderedRawCmds = [];
foreach($rawCmds as $rawCmd){ foreach ($rawCmds as $rawCmd) {
$generalID = $rawCmd['general_id']; $generalID = $rawCmd['general_id'];
$turnIdx = $rawCmd['turn_idx']; $turnIdx = $rawCmd['turn_idx'];
if(!key_exists($generalID, $orderedRawCmds)){ if (!key_exists($generalID, $orderedRawCmds)) {
$orderedRawCmds[$generalID] = []; $orderedRawCmds[$generalID] = [];
} }
$orderedRawCmds[$generalID][$turnIdx] = $rawCmd; $orderedRawCmds[$generalID][$turnIdx] = $rawCmd;
} }
$result = []; $result = [];
foreach($generalList as $general){ foreach ($generalList as $general) {
$generalID = $general->getID(); $generalID = $general->getID();
$result[$generalID] = []; $result[$generalID] = [];
if(!key_exists($generalID, $orderedRawCmds)){ if (!key_exists($generalID, $orderedRawCmds)) {
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){ foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
$result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env); $result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env);
} }
continue; continue;
} }
foreach($orderedRawCmds[$generalID] as $turnIdx=>$rawCmd){ foreach ($orderedRawCmds[$generalID] as $turnIdx => $rawCmd) {
$result[$generalID][$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg'])); $result[$generalID][$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $general, $env, Json::decode($rawCmd['arg']));
} }
} }
@@ -1205,109 +1307,113 @@ class General implements iAction{
/** /**
* @return int|float * @return int|float
*/ */
public function getInheritancePoint(string $key, &$aux=null, bool $forceCalc=false){ public function getInheritancePoint(string $key, &$aux = null, bool $forceCalc = false)
$inheritType = static::INHERITANCE_KEY[$key]??null; {
if($inheritType === null){ $inheritType = static::INHERITANCE_KEY[$key] ?? null;
if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님"); throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
} }
$ownerID = $this->getVar('owner'); $ownerID = $this->getVar('owner');
if(!$ownerID){ if (!$ownerID) {
return 0; return 0;
} }
if($this->getVar('npc') != 0){ if ($this->getVar('npc') != 0) {
return 0; return 0;
} }
[$storeType, $multiplier, ] = $inheritType; [$storeType, $multiplier,] = $inheritType;
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)){ if ($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)) {
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}"); $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
[$value, $aux] = $inheritStor->getValue($key); [$value, $aux] = $inheritStor->getValue($key);
return $value; return $value;
} }
if(is_array($storeType)){ if (is_array($storeType)) {
[$storSubType, $storSubKey] = $storeType; [$storSubType, $storSubKey] = $storeType;
if($storSubType === 'rank'){ if ($storSubType === 'rank') {
return $this->getRankVar($storSubKey) * $multiplier; return $this->getRankVar($storSubKey) * $multiplier;
} }
if($storSubType === 'raw'){ if ($storSubType === 'raw') {
return $this->getVar($storSubKey) * $multiplier; return $this->getVar($storSubKey) * $multiplier;
} }
if($storSubType === 'aux'){ if ($storSubType === 'aux') {
return ($this->getAuxVar($storSubKey)??0) * $multiplier; return ($this->getAuxVar($storSubKey) ?? 0) * $multiplier;
} }
throw new \InvalidArgumentException("{$storSubType}은 참조 할 수 없는 유산 세부키임"); throw new \InvalidArgumentException("{$storSubType}은 참조 할 수 없는 유산 세부키임");
} }
if($storeType !== false){ if ($storeType !== false) {
throw new \InvalidArgumentException("{$storeType}은 올바르지 않은 유산 키임"); throw new \InvalidArgumentException("{$storeType}은 올바르지 않은 유산 키임");
} }
$extractFn = function(){ return [0, null];}; $extractFn = function () {
switch($key){ return [0, null];
case 'dex': };
$extractFn = function() use ($multiplier){ switch ($key) {
$totalDex = 0; case 'dex':
foreach(array_keys(GameUnitConst::allType()) as $armType){ $extractFn = function () use ($multiplier) {
$totalDex += $this->getVar("dex{$armType}"); $totalDex = 0;
} foreach (array_keys(GameUnitConst::allType()) as $armType) {
return [$totalDex * $multiplier, null]; $totalDex += $this->getVar("dex{$armType}");
}; }
break; return [$totalDex * $multiplier, null];
case 'betting': };
$extractFn = function() use ($multiplier){ break;
$betWin = $this->getRankVar('betwin'); case 'betting':
$betWinRate = $this->getRankVar('betwingold')/max(1, $this->getRankVar('betgold')); $extractFn = function () use ($multiplier) {
$betWin = $this->getRankVar('betwin');
$betWinRate = $this->getRankVar('betwingold') / max(1, $this->getRankVar('betgold'));
return [$betWin * $multiplier * pow($betWinRate, 2), null]; return [$betWin * $multiplier * pow($betWinRate, 2), null];
}; };
break; break;
case 'max_belong': case 'max_belong':
$extractFn = function() use ($multiplier){ $extractFn = function () use ($multiplier) {
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong')??0); $maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong') ?? 0);
return [$maxBelong * $multiplier, null]; return [$maxBelong * $multiplier, null];
}; };
break; break;
default: default:
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음"); throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
} }
[$value, $aux] = ($extractFn)(); [$value, $aux] = ($extractFn)();
return $value; return $value;
} }
public function setInheritancePoint(string $key, $value, $aux=null){ public function setInheritancePoint(string $key, $value, $aux = null)
if(!is_int($value) && !is_float($value)){ {
if (!is_int($value) && !is_float($value)) {
throw new \InvalidArgumentException("{$value}는 숫자가 아님"); throw new \InvalidArgumentException("{$value}는 숫자가 아님");
} }
$inheritType = static::INHERITANCE_KEY[$key]??null; $inheritType = static::INHERITANCE_KEY[$key] ?? null;
if($inheritType === null){ if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님"); throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
} }
[$storeType, $multiplier, ] = $inheritType; [$storeType, $multiplier,] = $inheritType;
if($storeType !== true){ if ($storeType !== true) {
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님"); throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
} }
if($multiplier != 1 && $value != 0){ if ($multiplier != 1 && $value != 0) {
throw new \InvalidArgumentException("{$key}는 1:1 유산 포인트가 아님"); throw new \InvalidArgumentException("{$key}는 1:1 유산 포인트가 아님");
} }
$ownerID = $this->getVar('owner'); $ownerID = $this->getVar('owner');
if(!$ownerID){ if (!$ownerID) {
return; return;
} }
if($this->getVar('npc') != 0){ if ($this->getVar('npc') != 0) {
return; return;
} }
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($gameStor->isunited != 0){ if ($gameStor->isunited != 0) {
return; return;
} }
@@ -1315,39 +1421,40 @@ class General implements iAction{
$inheritStor->setValue($key, [$value, $aux]); $inheritStor->setValue($key, [$value, $aux]);
} }
public function increaseInheritancePoint(string $key, $value, $aux=null){ public function increaseInheritancePoint(string $key, $value, $aux = null)
if(!is_int($value) && !is_float($value)){ {
if (!is_int($value) && !is_float($value)) {
throw new \InvalidArgumentException("{$value}는 숫자가 아님"); throw new \InvalidArgumentException("{$value}는 숫자가 아님");
} }
$inheritType = static::INHERITANCE_KEY[$key]??null; $inheritType = static::INHERITANCE_KEY[$key] ?? null;
if($inheritType === null){ if ($inheritType === null) {
throw new \OutOfRangeException("{$key}는 유산 타입이 아님"); throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
} }
[$storeType, $multiplier, ] = $inheritType; [$storeType, $multiplier,] = $inheritType;
if($storeType !== true){ if ($storeType !== true) {
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님"); throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
} }
$ownerID = $this->getVar('owner'); $ownerID = $this->getVar('owner');
if(!$ownerID){ if (!$ownerID) {
return; return;
} }
if($this->getVar('npc') != 0){ if ($this->getVar('npc') != 0) {
return; return;
} }
$gameStor = KVStorage::getStorage(DB::db(), 'game_env'); $gameStor = KVStorage::getStorage(DB::db(), 'game_env');
if($gameStor->isunited != 0){ if ($gameStor->isunited != 0) {
return; return;
} }
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}"); $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
[$oldValue, $oldAux] = $inheritStor->getValue($key)??[0, null]; [$oldValue, $oldAux] = $inheritStor->getValue($key) ?? [0, null];
if($oldAux !== $aux){ if ($oldAux !== $aux) {
$oldValue = 0; $oldValue = 0;
} }
@@ -1355,22 +1462,23 @@ class General implements iAction{
$inheritStor->setValue($key, [$newValue, $aux]); $inheritStor->setValue($key, [$newValue, $aux]);
} }
public function mergeTotalInheritancePoint(){ public function mergeTotalInheritancePoint()
{
$ownerID = $this->getVar('owner'); $ownerID = $this->getVar('owner');
if(!$ownerID){ if (!$ownerID) {
return; return;
} }
if($this->getVar('npc') != 0){ if ($this->getVar('npc') != 0) {
return; return;
} }
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}"); $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
$inheritStor->cacheAll(); $inheritStor->cacheAll();
foreach(static::INHERITANCE_KEY as $key=>[$storType, ,]){ foreach (static::INHERITANCE_KEY as $key => [$storType,,]) {
$aux = null; $aux = null;
$point = $this->getInheritancePoint($key, $aux, true); $point = $this->getInheritancePoint($key, $aux, true);
if($storType === true){ if ($storType === true) {
continue; continue;
} }
$inheritStor->setValue($key, [$point, $aux]); $inheritStor->setValue($key, [$point, $aux]);
+771 -789
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -459,7 +459,7 @@ class GeneralBuilder{
} }
} }
if(!$this->dex1 && in_array('dex_t', $avgGen)){ if(!$this->dex1 && key_exists('dex_t', $avgGen)){
$dexTotal = $avgGen['dex_t']; $dexTotal = $avgGen['dex_t'];
if ($pickType == '무') { if ($pickType == '무') {
$dexVal = Util::choiceRandom([ $dexVal = Util::choiceRandom([
@@ -681,7 +681,7 @@ class GeneralBuilder{
'turntime'=>$turntime, 'turntime'=>$turntime,
'killturn'=>$killturn, 'killturn'=>$killturn,
'age'=>$age, 'age'=>$age,
'belong'=>1, 'belong'=>0,
'personal'=>$this->ego, 'personal'=>$this->ego,
'special'=>$this->specialDomestic, 'special'=>$this->specialDomestic,
'specage'=>$this->specAge, 'specage'=>$this->specAge,
+89
View File
@@ -0,0 +1,89 @@
<?php
namespace sammo;
class UserLogger
{
protected $userID;
protected $year;
protected $month;
protected $autoFlush;
protected $log = [];
function __construct(int $userID, ?int $year = null, ?int $month = null, bool $autoFlush = true)
{
$this->userID = $userID;
if ($year === null || $month === null) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year', 'month']);
if ($year === null) {
$year = $gameStor->year;
}
if ($month === null) {
$month = $gameStor->month;
}
}
$this->year = $year;
$this->month = $month;
$this->autoFlush = $autoFlush;
}
public function __destruct()
{
if ($this->autoFlush) {
$this->flush();
}
}
public function rollback()
{
$backup = $this->log;
$this->log = [];
return $backup;
}
public function flush()
{
if(!$this->log){
return;
}
if(!$this->userID){
return;
}
$db = DB::db();
$date = TimeUtil::now();
$serverID = UniqueConst::$serverID;
$request = array_map(function ($textAndType) use ($date, $serverID) {
[$text, $type] = $textAndType;
return [
'user_id' => $this->userID,
'server_id' => $serverID,
'log_type' => $type,
'year' => $this->year,
'month' => $this->month,
'date' => $date,
'text' => $text
];
}, array_values($this->log));
$db->insert('user_record', $request);
$this->log = [];
}
public function push($text, string $type)
{
if (!$text) {
return;
}
if (is_array($text)) {
foreach ($text as $textItem) {
$this->log[] = [$textItem, $type];
}
return;
}
$this->log[] = [$text, $type];
}
}
+4 -1
View File
@@ -56,6 +56,9 @@ class WarUnitGeneral extends WarUnit
$semiTurn = $general->getTurnTime(); $semiTurn = $general->getTurnTime();
} else if ($oppose !== null) { } else if ($oppose !== null) {
$semiTurn = $oppose->getGeneral()->getTurnTime(); $semiTurn = $oppose->getGeneral()->getTurnTime();
} else {
LogText("WarUnitGeneral::setOppose", "defender인데 oppose가 null {$general->getID()}, {$general->getTurnTime()}");
$semiTurn = $general->getTurnTime();
} }
$phase = $this->getRealPhase(); $phase = $this->getRealPhase();
$semiTurn = substr($semiTurn, 0, strlen($semiTurn) - 2); $semiTurn = substr($semiTurn, 0, strlen($semiTurn) - 2);
@@ -205,7 +208,7 @@ class WarUnitGeneral extends WarUnit
if ($this->isAttacker) { if ($this->isAttacker) {
if ($officerLevel == 12) { if ($officerLevel == 12) {
$warPower *= 1.10; $warPower *= 1.10;
} else if ($officerLevel == 11 | $officerLevel == 10 || $officerLevel == 8 || $officerLevel == 6) { } else if ($officerLevel == 11 || $officerLevel == 10 || $officerLevel == 8 || $officerLevel == 6) {
$warPower *= 1.05; $warPower *= 1.05;
} }
} else { } else {
@@ -14,6 +14,7 @@ class che_반계시도 extends BaseWarUnitTrigger{
public function __construct(WarUnit $unit, int $raiseType = 0, float $prob = 0.4){ public function __construct(WarUnit $unit, int $raiseType = 0, float $prob = 0.4){
$this->object = $unit; $this->object = $unit;
$this->raiseType = $raiseType;
$this->prob = $prob; $this->prob = $prob;
} }
@@ -22,7 +22,7 @@ class che_전투치료발동 extends BaseWarUnitTrigger{
} }
$selfEnv['치료발동'] = true; $selfEnv['치료발동'] = true;
$oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <C>치료</>했다!", ActionLogger::PLAIN); $oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <R>치료</>했다!", ActionLogger::PLAIN);
$self->getLogger()->pushGeneralBattleDetailLog("<C>치료</>했다!", ActionLogger::PLAIN); $self->getLogger()->pushGeneralBattleDetailLog("<C>치료</>했다!", ActionLogger::PLAIN);
$oppose->multiplyWarPowerMultiply(0.5); $oppose->multiplyWarPowerMultiply(0.5);
+1 -1
View File
@@ -9,7 +9,7 @@
"events":[ "events":[
[ [
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]], ["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
["CreateManyNPC", 30], ["CreateManyNPC", 10, 10],
["DeleteEvent"] ["DeleteEvent"]
], ],
[ [
+1 -1
View File
@@ -12,7 +12,7 @@
"events":[ "events":[
[ [
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]], ["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
["CreateManyNPC", 30], ["CreateManyNPC", 10, 10],
["DeleteEvent"] ["DeleteEvent"]
], ],
[ [
+1 -1
View File
@@ -16,7 +16,7 @@
"events":[ "events":[
[ [
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]], ["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
["CreateManyNPC", 30], ["CreateManyNPC", 10, 10],
["DeleteEvent"] ["DeleteEvent"]
], ],
[ [
+1 -1
View File
@@ -2,7 +2,7 @@
"title": "【가상모드19b】 진유저무쌍! (대형 지도)", "title": "【가상모드19b】 진유저무쌍! (대형 지도)",
"startYear": 180, "startYear": 180,
"history": [ "history": [
"<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>", "<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>",
"<C>●</>180년 1월:<L><b>【이벤트】</b></>고대장수 다 덤벼라! 유저가 최강이다!" "<C>●</>180년 1월:<L><b>【이벤트】</b></>고대장수 다 덤벼라! 유저가 최강이다!"
], ],
"stat": { "stat": {
+113
View File
@@ -0,0 +1,113 @@
{
"title": "【가상모드23】 CookieRun : Kingdom",
"startYear": 180,
"history": [
"<C>●</>180년 1월:<L><b>【가상모드23】</b>CookieRun : Kingdom</>",
"<C>●</>180년 1월:<L><b>【이벤트】</b></>쿠키들과 함께하는 삼모전"
],
"stat": {
"total": 200,
"min": 10,
"max": 90,
"npcTotal":180,
"npcMax":70,
"npcMin":10,
"chiefMin": 60
},
"iconPath": "쿠키런킹덤",
"fiction": 1,
"nation":[
],
"map":{
"mapName":"miniche",
"unitSet":"che"
},
"diplomacy":[],
"general":[
[30, "커스터드3세", null, 0, null, 60, 60, 60, 0, 160, 300, null, null, "새로운 백성이로구나. 반가워!"],
[30, "클로버", null, 0, null, 71, 49, 71, 0, 160, 300, null, null, "여러분의 모험에 행운이 깃들길..."],
[50, "마들렌", null, 0, null, 73, 57, 73, 0, 160, 300, null, null, "빛의 신께 세상을 구하라는 명을 받은 쿠키가 바로 나다!"],
[50, "호밀", null, 0, null, 73, 65, 65, 0, 160, 300, null, null, "애송이들! 그렇게 부드러워서야 되겠어?"],
[50, "에스프레소", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "커피마법이라고 다를 것 없습니다?"],
[50, "라떼", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "쓰디 쓴 실패라도 부드러운 우유 몇 방울이면 달콤해질거야"],
[50, "아몬드", null, 0, null, 69, 30, 100, 0, 160, 300, null, null, "당신을 마법 행정 규약 위반으로 체포합니다"],
[50, "블랙레이즌", null, 0, null, 65, 70, 60, 0, 160, 300, null, null, "깜깜한 어둠 속도 상관 없어. 난 전부 보이니까!"],
[60, "감초", null, 0, null, 70, 10, 120, 0, 160, 300, null, null, "나도 할 땐 하는 쿠키야!"],
[60, "독버섯", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "버서엇...?"],
[60, "딸기크레페", null, 0, null, 70, 60, 70, 0, 160, 300, null, null],
[70, "퓨어바닐라", null, 0, null, 90, 45, 90, 0, 160, 300, null, null, "힘들 땐 힘들다고 말해도 괜찮아요."],
[60, "다크초코", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "그저… 영웅이 되고 싶었을 뿐…"],
[60, "석류", null, 0, null, 75, 55, 75, 0, 160, 300, null, null, "영원히 그분만을 섬기리…"],
[999, "설탕노움", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[10, "The브레이브", null, 0, null, 69, 51, 69, 0, 160, 300, null, null, "모험은 이제부터 시작이야!"],
[10, "스트로베리", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "쿠키생은 혼자야…"],
[10, "매지션", null, 0, null, 66, 54, 66, 0, 160, 300, null, null, "가슴은 뜨겁게 머리는 앗 차거!"],
[10, "에인절", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "새처럼 날아가 볼까요…"],
[10, "비트", null, 0, null, 64, 56, 64, 0, 160, 300, null, null, "벌써 이곳에서 1000일을 버텼지!"],
[10, "The머슬", null, 0, null, 70, 50, 70, 0, 160, 300, null, null, "이번엔 스쿼트다! 하나! 둘!"],
[10, "닌자", null, 0, null, 63, 57, 63, 0, 160, 300, null, null, "허공을 가르고 바람을 밟는다!"],
[30, "용사", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "더 강해져야 해!"],
[30, "알케미스트", null, 0, null, 61, 64, 61, 0, 160, 300, null, null, "내가 어떤 걸 만들어 내는지 잘 보라구~!"],
[30, "체리", null, 0, null, 66, 59, 66, 0, 160, 300, null, null, "어랏? 터져버렸네~? 미안...일부러 그랬어~ 헤헷!"],
[30, "버블껌", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "껌은 씹는 것 보다 쏘는 게 더 재밌어!"],
[30, "블랙베리", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "맡기실 일이 있다면 뭐든 말씀하세요."],
[30, "팬케이크", null, 0, null, 52, 73, 52, 0, 160, 300, null, null, "나 도토리젤리 안 줄 거야?"],
[30, "The프린세스", null, 0, null, 60, 65, 60, 0, 160, 300, null, null, "나들이하기 좋은 날이네~!"],
[30, "아보카도", null, 0, null, 67, 58, 67, 0, 160, 300, null, null, "가장 맛있는 싸움은? 보쌈! 와하하!"],
[30, "어니언", null, 0, null, 72, 53, 72, 0, 160, 300, null, null, "으아아아아앙~"],
[30, "익스플로러", null, 0, null, 65, 60, 65, 0, 160, 300, null, null, "가보고 싶은 곳이 너무 많아!"],
[30, "캐롯", null, 0, null, 71, 54, 71, 0, 160, 300, null, null, "밭일하러 나갈 시간이야!"],
[60, "뱀파이어", null, 0, null, 58, 72, 58, 0, 160, 300, null, null, "나랑 포도주스 한 잔 어때?"],
[50, "스파클링", null, 0, null, 70, 60, 70, 0, 160, 300, null, null, "승리를 위한 한 잔이 필요하겠군요!"],
[50, "칠리", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "어이! 주머니 조심하라구!"],
[50, "자색고구마", null, 0, null, 65, 65, 65, 0, 160, 300, null, null, "나랑 싸울 쿠키 다 나와!"],
[50, "눈설탕", null, 0, null, 79, 51, 79, 0, 160, 300, null, null, "안녕? 반가워~ 나랑... 눈싸움할래?"],
[50, "정글전사", null, 0, null, 80, 50, 80, 0, 160, 300, null, null, "친구…들을… 지켜야… 해…"],
[50, "민트초코", null, 0, null, 76, 54, 76, 0, 160, 300, null, null, "어떤 음악을 들려드릴까요?"],
[50, "허브", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "무럭무럭 자라렴~"],
[50, "우유", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "평화를 위해 어둠과 맞서 싸우리라!"],
[50, "웨어울프", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "다가오지 마… 다쳐…"],
[50, "구미호", null, 0, null, 72, 58, 72, 0, 160, 300, null, null, "나한테 반하면 어떻게 되는지 궁금해?"],
[50, "슈크림", null, 0, null, 71, 59, 71, 0, 160, 300, null, null, "저도 이제 어엿한 마법사라구요!"],
[150, "케이크들개", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
[999, "곰젤리", null, 0, null, 40, 80, 40, 0, 160, 300, null, null],
[999, "곰젤리역장", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "후르츠칸앵무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "순례자", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "은행강도", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "무녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[150, "역사선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "오늘 확실히 가르쳐 주겠습니다! 도서관의 규칙을!"],
[150, "화학선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "화학실에 멋대로 침입한 벌을 내리겠다!!"],
[150, "전술선생님", null, 0, null, 85, 45, 85, 0, 160, 300, null, null, "으하하하!! 그럼 어디 한 번 시험해 볼까! 너의 전술을!"],
[150, "꿈꾸는 바할로모트", null, 0, null, 90, 40, 90, 0, 160, 300, null, "환술", "난 이 학교의 교장이니까 말일세!"],
[999, "치료사", null, 0, null, 65, 55, 65, 0, 160, 300, null, null],
[999, "커스터드총리", null, 0, null, 63, 63, 63, 0, 160, 300, null, null],
[150, "3단케이크마녀", null, 0, null, 70, 70, 70, 0, 160, 300, null, null]
],
"general_ex":[
[999, "바람궁수", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "달빛술사", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "바다요정", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "불꽃정령", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[150, "어둠마녀", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "천년나무", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "다크카카오", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "세인트릴리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "홀리베리", null, 0, null, 60, 60, 60, 0, 160, 300, null, null],
[999, "골드치즈", null, 0, null, 60, 60, 60, 0, 160, 300, null, null]
],
"events":[
[
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
["CreateManyNPC", 10, 10],
["DeleteEvent"]
],
[
["Date", "==", 181, 1],
["RaiseNPCNation"],
["DeleteEvent"]
]
]
}
+1 -1
View File
@@ -60,7 +60,7 @@
"events":[ "events":[
[ [
["Date", "==", null, 12], ["Date", "==", null, 12],
["CreateManyNPC", 30], ["CreateManyNPC", 10, 10],
["DeleteEvent"] ["DeleteEvent"]
], ],
[ [
+1 -1
View File
@@ -12,7 +12,7 @@
"events": [ "events": [
[ [
["Date", "==", null, 12], ["Date", "==", null, 12],
["CreateManyNPC", 100], ["CreateManyNPC", 100, 0],
["DeleteEvent"] ["DeleteEvent"]
], ],
[ [
+9 -9
View File
@@ -1,13 +1,13 @@
<div class="buttonPlate bg1"> <div class="buttonPlate bg1">
<div> <div>
<a href="a_status.php" target="_blank"><button type="button" class="toolbarButton">세력도</button></a> <a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
<a href="a_kingdomList.php" target="_blank"><button type="button" class="toolbarButton">세력일람</button></a> <a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
<a href="a_genList.php" target="_blank"><button type="button" class="toolbarButton">장수일람</button></a> <a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
<a href="a_bestGeneral.php" target="_blank"><button type="button" class="toolbarButton">명장일람</button></a> <a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명장일람</button></a>
<a href="a_history.php" target="_blank"><button type="button" class="toolbarButton">연감</button></a> <a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
<a href="a_hallOfFame.php" target="_blank"><button type="button" class="toolbarButton">명예의전당</button></a> <a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
<a href="a_emperior.php" target="_blank"><button type="button" class="toolbarButton">왕조일람</button></a> <a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
<a href="a_traffic.php" target="_blank"><button type="button" class="toolbarButton">접속량정보</button></a> <a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
</div> </div>
<div> <div>
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a> <a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
@@ -17,6 +17,6 @@
<a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a> <a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a> <a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a> <a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
<a href="<?=$site?>" target="_blank"><button type="button" class="toolbarButton"><?=$call?></button></a> <a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
</div> </div>
</div> </div>
+5 -5
View File
@@ -8,18 +8,18 @@
<a href='b_dipcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 무 부</button></a> <a href='b_dipcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 무 부</button></a>
<a href='b_chiefcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>사 령 부</button></a> <a href='b_chiefcenter.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>사 령 부</button></a>
<a href='v_NPCControl.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>NPC 정책</button></a> <a href='v_NPCControl.php'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>NPC 정책</button></a>
<a href='b_genList.php' target='_blank'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>암 행 부</button></a> <a href='b_genList.php' target='_blank' class="open-window"><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>암 행 부</button></a>
<a href='b_tournament.php' target='_blank'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>토 너 먼 트</button></a> <a href='b_tournament.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>토 너 먼 트</button></a>
<a href='b_myKingdomInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 정보</button></a> <a href='b_myKingdomInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 정보</button></a>
<a href='b_myCityInfo.php'><button type="button" class='commandButton' <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 도시</button></a> <a href='b_myCityInfo.php'><button type="button" class='commandButton' <?=($meLevel>=1&&$nationLevel>=1)?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 도시</button></a>
<a href='b_myGenInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 장수</button></a> <a href='b_myGenInfo.php'><button type="button" class='commandButton' <?=$meLevel>=1?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>세력 장수</button></a>
<a href='b_diplomacy.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>중원 정보</button></a> <a href='b_diplomacy.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>중원 정보</button></a>
<a href='b_currentCity.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>현재 도시</button></a> <a href='b_currentCity.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>현재 도시</button></a>
<a href='b_battleCenter.php' target='_blank'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>감 찰 부</button></a> <a href='b_battleCenter.php' target='_blank' class="open-window"><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>감 찰 부</button></a>
<a href='v_inheritPoint.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>유산 관리</button></a> <a href='v_inheritPoint.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>유산 관리</button></a>
<a href='b_myPage.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 정보&amp;설정</button></a> <a href='b_myPage.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 정보&amp;설정</button></a>
<a href='b_auction.php' target='_blank'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>거 래 장</button></a> <a href='b_auction.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>거 래 장</button></a>
<a href='b_betting.php' target='_blank'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>베 팅 장</button></a> <a href='b_betting.php' target='_blank' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>베 팅 장</button></a>
</div> </div>
</div> </div>
+5 -5
View File
@@ -149,7 +149,7 @@
<div class="col col-md-1 col-3"> <div class="col col-md-1 col-3">
<label <label
><input type="checkbox" v-model="displayInherit" />{{ ><input type="checkbox" v-model="displayInherit" />{{
displayTable ? "숨기기" : "보이기" displayInherit ? "숨기기" : "보이기"
}}</label }}</label
> >
</div> </div>
@@ -305,7 +305,7 @@ import {
CTableRow, CTableRow,
CTableHeaderCell, CTableHeaderCell,
CTableDataCell, CTableDataCell,
} from "@coreui/vue/src"; } from "@coreui/vue/src/components/table";
import { getIconPath } from "./util/getIconPath"; import { getIconPath } from "./util/getIconPath";
import { isBrightColor } from "./util/isBrightColor"; import { isBrightColor } from "./util/isBrightColor";
import { import {
@@ -458,21 +458,21 @@ export default defineComponent({
}, },
inheritTurnTimeMinute(newValue: number) { inheritTurnTimeMinute(newValue: number) {
if (!this.inheritTurnTimeSet) { if (!this.inheritTurnTimeSet) {
this.args.inheritTurntime = 0; this.args.inheritTurntime = undefined;
return; return;
} }
this.args.inheritTurntime = newValue * 60 + this.inheritTurnTimeSecond; this.args.inheritTurntime = newValue * 60 + this.inheritTurnTimeSecond;
}, },
inheritTurnTimeSecond(newValue: number) { inheritTurnTimeSecond(newValue: number) {
if (!this.inheritTurnTimeSet) { if (!this.inheritTurnTimeSet) {
this.args.inheritTurntime = 0; this.args.inheritTurntime = undefined;
return; return;
} }
this.args.inheritTurntime = this.inheritTurnTimeMinute * 60 + newValue; this.args.inheritTurntime = this.inheritTurnTimeMinute * 60 + newValue;
}, },
inheritTurnTimeSet(newValue: boolean) { inheritTurnTimeSet(newValue: boolean) {
if (!newValue) { if (!newValue) {
this.args.inheritTurntime = 0; this.args.inheritTurntime = undefined;
return; return;
} }
this.args.inheritTurntime = this.args.inheritTurntime =
+1 -1
View File
@@ -50,7 +50,7 @@
<NumberInputWithInfo <NumberInputWithInfo
v-model="nationPolicy.reqHumanWarUrgentRice" v-model="nationPolicy.reqHumanWarUrgentRice"
:step="100" :step="100"
title="유저전투장 긴급포상 " title="유저전투장 긴급포상 "
>유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br />0이면 >유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br />0이면
기본 병종으로 {{ (defaultStatMax * 100).toLocaleString() }} * 6 사살 기본 병종으로 {{ (defaultStatMax * 100).toLocaleString() }} * 6 사살
가능한 쌀을 기준으로 하며, 수치는 현재 가능한 쌀을 기준으로 하며, 수치는 현재
+3 -3
View File
@@ -893,7 +893,7 @@ $(function ($) {
} }
showBattleResult(result); showBattleResult(result);
}, function (result) { }, function () {
alert('전투 개시 실패!'); alert('전투 개시 실패!');
}); });
} }
@@ -933,7 +933,7 @@ $(function ($) {
} }
reorderDefender(result.order); reorderDefender(result.order);
}, function (result) { }, function () {
alert('재정렬 실패!'); alert('재정렬 실패!');
}); });
} }
@@ -968,7 +968,7 @@ $(function ($) {
}); });
$('#importModal').on('show.bs.modal', function (e) { $('#importModal').on('show.bs.modal', function () {
if (!initGeneralList) { if (!initGeneralList) {
const $list = $('#modalSelector'); const $list = $('#modalSelector');
-1
View File
@@ -19,7 +19,6 @@
"currentCity": "currentCity.ts", "currentCity": "currentCity.ts",
"hallOfFame": "hallOfFame.ts", "hallOfFame": "hallOfFame.ts",
"history": "history.ts", "history": "history.ts",
"join": "legacy/join.ts",
"select_general_from_pool": "select_general_from_pool.ts", "select_general_from_pool": "select_general_from_pool.ts",
"extKingdoms": "extKingdoms.ts", "extKingdoms": "extKingdoms.ts",
"common": "common_deprecated.ts" "common": "common_deprecated.ts"
+127 -10
View File
@@ -1,7 +1,7 @@
import $ from 'jquery'; import $ from 'jquery';
import 'popper.js'; import 'popper.js';
import Popper from 'popper.js'; import Popper from 'popper.js';
(window as unknown as {Popper:unknown}).Popper = Popper; (window as unknown as { Popper: unknown }).Popper = Popper;
import 'bootstrap'; import 'bootstrap';
import { JQValidateForm, NamedRules } from '../util/jqValidateForm'; import { JQValidateForm, NamedRules } from '../util/jqValidateForm';
import axios from 'axios'; import axios from 'axios';
@@ -11,9 +11,12 @@ import { unwrap_any } from '../util/unwrap_any';
import { sha512 } from 'js-sha512'; import { sha512 } from 'js-sha512';
import { unwrap } from '../util/unwrap'; import { unwrap } from '../util/unwrap';
import { InvalidResponse } from '../defs'; import { InvalidResponse } from '../defs';
import internal from 'stream';
import { delay } from '../util/delay';
type LoginResponse = { type LoginResponse = {
result: true, result: true,
nextToken: [number, string] | undefined,
} | { } | {
result: false, result: false,
reqOTP: boolean, reqOTP: boolean,
@@ -29,6 +32,19 @@ type OTPResponse = {
reason: string, reason: string,
} }
type AutoLoginNonceResponse = {
result: true,
loginNonce: string,
} | InvalidResponse;
type AutoLoginResponse = {
result: true,
nextToken: [number, string] | undefined,
} | {
result: false,
silent: boolean,
reason: string,
}
declare global { declare global {
interface Window { interface Window {
getOAuthToken: (mode: string, scope_list: string[]) => void; getOAuthToken: (mode: string, scope_list: string[]) => void;
@@ -41,6 +57,92 @@ declare const kakao_oauth_redirect_uri: string;
let oauthMode: string | null = null; let oauthMode: string | null = null;
const TOKEN_VERSION = 1;
const LOGIN_TOKEN_KEY = 'sammo_login_token';
function regNextToken(tokenInfo: [number, string]) {
localStorage.setItem(LOGIN_TOKEN_KEY, JSON.stringify([TOKEN_VERSION, tokenInfo, Date.now()]));
}
function getToken(): [number, string] | undefined {
const trialToken = localStorage.getItem(LOGIN_TOKEN_KEY);
if (!trialToken) {
return;
}
const tokenItems = JSON.parse(trialToken);
if (tokenItems[0] != TOKEN_VERSION) {
console.log(tokenItems);
resetToken();
return;
}
const [, token,] = tokenItems;
return token;
}
function resetToken(){
localStorage.removeItem(LOGIN_TOKEN_KEY);
}
async function tryAutoLogin() {
try {
const tokenInfo = getToken();
if (!tokenInfo) {
return;
}
const [tokenID, token] = tokenInfo;
const result = await axios.post<AutoLoginNonceResponse>('api.php', {
path: ["Login", "ReqNonce"]
});
if(!result){
//api 에러.
return;
}
if(!result.data.result){
resetToken();
return;
}
const nonce = result.data.loginNonce;
const hashedToken = sha512(token + nonce);
const _loginResult = await axios.post<AutoLoginResponse>('api.php', {
path: ["Login", "LoginByToken"],
args: {
'hashedToken':hashedToken,
'token_id':tokenID,
}
});
if(!_loginResult){
return;
}
const loginResult = _loginResult.data;
if(!loginResult.result){
if(!loginResult.silent){
alert(loginResult.reason);
}
console.error(loginResult.reason);
return;
}
if(loginResult.nextToken){
regNextToken(loginResult.nextToken);
}
window.location.href = "./";
}
catch(e){
console.error(e);
return;
}
}
function getOAuthToken(mode: string, scope_list?: string[] | string) { function getOAuthToken(mode: string, scope_list?: string[] | string) {
if (mode === undefined) { if (mode === undefined) {
mode = 'login'; mode = 'login';
@@ -115,6 +217,9 @@ async function doLoginUsingOAuth() {
} }
if (result.result) { if (result.result) {
if (result.nextToken) {
regNextToken(result.nextToken);
}
window.location.href = "./"; window.location.href = "./";
return; return;
} }
@@ -156,9 +261,16 @@ function postOAuthResult(mode: string) {
window.postOAuthResult = postOAuthResult; window.postOAuthResult = postOAuthResult;
$(function ($) { $(async function ($) {
setAxiosXMLHttpRequest(); setAxiosXMLHttpRequest();
//로그인 먼저 해볼 것
if(getToken()){
void tryAutoLogin();
await delay(100);
}
type LoginFormType = { type LoginFormType = {
username: string, username: string,
password: string, password: string,
@@ -194,13 +306,16 @@ $(function ($) {
try { try {
const response = await axios({ const response = await axios({
url: 'j_login.php', url: 'api.php',
responseType: 'json', responseType: 'json',
method: 'post', method: 'post',
data: convertFormData({ data: {
username: values.username, path: ["Login", "LoginByID"],
password: hash_pw, args: {
}) username: values.username,
password: hash_pw,
}
}
}); });
result = response.data; result = response.data;
} }
@@ -212,6 +327,9 @@ $(function ($) {
if (result.result) { if (result.result) {
if (result.nextToken) {
regNextToken(result.nextToken);
}
window.location.href = "./"; window.location.href = "./";
return; return;
} }
@@ -268,12 +386,11 @@ $(function ($) {
getOAuthToken('change_pw', 'talk_message'); getOAuthToken('change_pw', 'talk_message');
}); });
$('#btn_kakao_login').on('click', function(e){ $('#btn_kakao_login').on('click', function (e) {
e.preventDefault(); e.preventDefault();
getOAuthToken('login', ['account_email','talk_message']); getOAuthToken('login', ['account_email', 'talk_message']);
}) })
//TODO: 모바일에서 크기 비례 지도 다시 띄우기? //TODO: 모바일에서 크기 비례 지도 다시 띄우기?
/* /*
if (document.body.clientWidth < 700) { if (document.body.clientWidth < 700) {
+2 -3
View File
@@ -1,5 +1,4 @@
import { template } from "lodash"; import { NPCChiefActions, NPCGeneralActions } from "./defs";
import { NationPolicy, NPCChiefActions, NPCGeneralActions } from "./defs";
export const NPCPriorityBtnHelpMessage: { export const NPCPriorityBtnHelpMessage: {
[v in NPCChiefActions | NPCGeneralActions]: string; [v in NPCChiefActions | NPCGeneralActions]: string;
@@ -34,7 +33,7 @@ export const NPCPriorityBtnHelpMessage: {
NPC후방발령: NPC후방발령:
"NPC전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.", "NPC전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.",
NPC포상: NPC포상:
"금/쌀이 부족한 유저장에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.", "금/쌀이 부족한 NPC에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.",
NPC전방발령: NPC전방발령:
"후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.", "후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.",
: :
+30 -6
View File
@@ -3,7 +3,12 @@
<div <div
id="container" id="container"
class="bg0 px-2" class="bg0 px-2"
style="max-width: 1000px; margin: auto; border: solid 1px #888888; overflow:hidden;" style="
max-width: 1000px;
margin: auto;
border: solid 1px #888888;
overflow: hidden;
"
> >
<div id="inheritance_list" class="row"> <div id="inheritance_list" class="row">
<template v-for="(text, key) in inheritanceViewText" :key="key"> <template v-for="(text, key) in inheritanceViewText" :key="key">
@@ -235,6 +240,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col">
<div class="bg1 a-center">유산 포인트 변경 내역(최근 30)</div>
</div>
</div>
<div class="row" v-for="(log, idx) in lastInheritPointLogs" :key="idx">
<div class="col a-right" style="max-width:20ch">
<small class="text-muted">[{{log.date}}]</small>
</div>
<div class="col a-left">
{{log.text}}
</div>
</div>
</div> </div>
</template> </template>
@@ -263,6 +282,14 @@ type InheritanceType =
type InheritanceViewType = InheritanceType | "sum" | "new"; type InheritanceViewType = InheritanceType | "sum" | "new";
declare const lastInheritPointLogs: {
server_id: string,
year: number,
month: number,
date: string,
text: string,
}[];
declare const items: Record<InheritanceType, number>; declare const items: Record<InheritanceType, number>;
const inheritanceViewText: Record< const inheritanceViewText: Record<
@@ -442,6 +469,7 @@ export default defineComponent({
availableSpecialWar, availableSpecialWar,
availableUnique, availableUnique,
specificUniqueAmount: inheritActionCost.minSpecificUnique, specificUniqueAmount: inheritActionCost.minSpecificUnique,
lastInheritPointLogs,
}; };
}, },
methods: { methods: {
@@ -617,11 +645,7 @@ export default defineComponent({
return; return;
} }
//TODO: JosaUtil //TODO: JosaUtil
if ( if (!confirm(`${amount} 포인트로 ${uniqueName}(을)를 입찰하겠습니까?`)) {
!confirm(
`${amount} 포인트로 ${uniqueName}(을)를 입찰하겠습니까?`
)
) {
return; return;
} }
-213
View File
@@ -1,213 +0,0 @@
import $ from 'jquery';
import { exportWindow } from '../util/exportWindow';
import { mb_strwidth } from '../util/mb_strwidth';
import { unwrap_any } from '../util/unwrap_any';
declare const defaultStatTotal: number;
declare const defaultStatMax: number;
declare const defaultStatMin: number;
declare const charInfoText: Record<string, string>;
$(function ($) {
const $leadership = $('#leadership');
const $strength = $('#strength');
const $intel = $('#intel');
function abilityRand(): void {
let leadership = Math.random() * 65 + 10;
let strength = Math.random() * 65 + 10;
let intel = Math.random() * 65 + 10;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
leadership += 1;
}
if (leadership > defaultStatMax || strength > defaultStatMax || intel > defaultStatMax || leadership < defaultStatMin || strength < defaultStatMin || intel < defaultStatMin) {
return abilityRand();
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityLeadpow() {
let leadership = Math.random() * 6;
let strength = Math.random() * 6;
let intel = Math.random() * 1;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
strength += 1;
}
if (intel < defaultStatMin) {
leadership -= defaultStatMin - intel;
intel = defaultStatMin;
}
if (leadership > defaultStatMax) {
strength += leadership - defaultStatMax;
leadership = defaultStatMax;
}
if (strength > defaultStatMax) {
leadership += strength - defaultStatMax;
strength = defaultStatMax;
}
if (leadership > defaultStatMax) {
intel += leadership - defaultStatMax;
leadership = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityLeadint() {
let leadership = Math.random() * 6;
let strength = Math.random() * 1;
let intel = Math.random() * 6;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
intel += 1;
}
if (strength < defaultStatMin) {
leadership -= defaultStatMin - strength;
strength = defaultStatMin;
}
if (leadership > defaultStatMax) {
intel += leadership - defaultStatMax;
leadership = defaultStatMax;
}
if (intel > defaultStatMax) {
leadership += intel - defaultStatMax;
intel = defaultStatMax;
}
if (leadership > defaultStatMax) {
strength += leadership - defaultStatMax;
leadership = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
function abilityPowint() {
let leadership = Math.random() * 1;
let strength = Math.random() * 6;
let intel = Math.random() * 6;
const rate = leadership + strength + intel;
leadership = Math.floor(leadership / rate * defaultStatTotal);
strength = Math.floor(strength / rate * defaultStatTotal);
intel = Math.floor(intel / rate * defaultStatTotal);
while (leadership + strength + intel < defaultStatTotal) {
intel += 1;
}
if (leadership < defaultStatMin) {
strength -= defaultStatMin - leadership;
leadership = defaultStatMin;
}
if (strength > defaultStatMax) {
intel += strength - defaultStatMax;
strength = defaultStatMax;
}
if (intel > defaultStatMax) {
strength += intel - defaultStatMax;
intel = defaultStatMax;
}
if (strength > defaultStatMax) {
leadership += strength - defaultStatMax;
strength = defaultStatMax;
}
$leadership.val(leadership);
$strength.val(strength);
$intel.val(intel);
}
exportWindow(abilityRand, 'abilityRand');
exportWindow(abilityLeadpow, 'abilityLeadpow');
exportWindow(abilityLeadint, 'abilityLeadint');
exportWindow(abilityPowint, 'abilityPowint');
const $charInfoText = $('#charInfoText');
const $selChar = $('#selChar');
$selChar.change(function () {
const $this = $(this);
const char = unwrap_any<string>($this.val());
if (char in charInfoText) {
$charInfoText.html(charInfoText[char]);
}
else {
$charInfoText.html('');
}
});
const $generalName = $('#generalName');
$generalName.on('change keyup paste', function () {
const generalName = unwrap_any<string>($generalName.val());
const len = mb_strwidth(generalName);
if (len == 0 || len > 18) {
$generalName.css('color', 'red');
}
else {
$generalName.css('color', 'white');
}
});
$('#join_form').submit(function () {
const generalName = unwrap_any<string>($generalName.val());
if (mb_strwidth(generalName) > 18) {
alert('장수 이름이 너무 깁니다!');
return false;
}
const currentStatTotal = parseInt(unwrap_any<string>($leadership.val())) + parseInt(unwrap_any<string>($strength.val())) + parseInt(unwrap_any<string>($intel.val()));
if (currentStatTotal < defaultStatTotal) {
if (!confirm(`현재 능력치 총합은 ${currentStatTotal}으로, ${defaultStatTotal}보다 낮습니다. 그래도 생성할까요?`)) {
return false;
}
}
return true;
});
const randomGenType = Math.floor(Math.random() * 7);
if (randomGenType < 3) {
abilityLeadpow();
}
else if (randomGenType < 6) {
abilityLeadint();
}
else {
abilityPowint();
}
});
+13
View File
@@ -192,6 +192,19 @@ $(function ($) {
return false; return false;
}) })
$('.open-window').on('click', function(e){
e.preventDefault();
let target = $(e.target as HTMLAnchorElement);
while(target.attr('href') === undefined){
target = target.parent('a');
if(target.length == 0){
return;
}
}
const href = target.attr('href');
window.open(href);
});
setInterval(myclock, 500); setInterval(myclock, 500);
reloadCommandList(); reloadCommandList();
activateFlip(); activateFlip();
+1 -1
View File
@@ -516,7 +516,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
//터치스크린 탭 //터치스크린 탭
if (!option.neutralView && is_touch_device()) { if (!option.neutralView && is_touch_device()) {
$objs.on('touchstart', function (e) { $objs.on('touchstart', function () {
if (window.sam_toggleSingleTap) { if (window.sam_toggleSingleTap) {
return true; return true;
} }
+4
View File
@@ -171,6 +171,7 @@ $(function ($) {
}); });
$('#set_my_setting').on('click', async function (e) { $('#set_my_setting').on('click', async function (e) {
e.preventDefault();
let result: InvalidResponse; let result: InvalidResponse;
try { try {
@@ -186,6 +187,9 @@ $(function ($) {
}) })
}); });
result = response.data; result = response.data;
if(!result.result){
throw result.reason;
}
} }
catch (e) { catch (e) {
console.log(e); console.log(e);
+1 -1
View File
@@ -203,7 +203,7 @@ function printGenerals(value: NPCToken) {
const time = Date.now() + value.pickMoreSeconds * 1000; const time = Date.now() + value.pickMoreSeconds * 1000;
$('#btn_pick_more').data('available', time).prop('disabled', true); $('#btn_pick_more').data('available', time).prop('disabled', true);
const pick = $.map(value.pick, function (value, key) { const pick = $.map(value.pick, function (value) {
return value; return value;
}); });
+11 -8
View File
@@ -17,7 +17,7 @@ $me = General::createGeneralObjFromDB($generalID);
$currentInheritBuff = []; $currentInheritBuff = [];
foreach ($me->getAuxVar('inheritBuff')??[] as $buff => $buffLevel) { foreach ($me->getAuxVar('inheritBuff') ?? [] as $buff => $buffLevel) {
if (!key_exists($buff, TriggerInheritBuff::BUFF_KEY_TEXT)) { if (!key_exists($buff, TriggerInheritBuff::BUFF_KEY_TEXT)) {
continue; continue;
} }
@@ -43,15 +43,15 @@ foreach (GameConst::$availableSpecialWar as $specialWarKey) {
} }
$availableUnique = []; $availableUnique = [];
foreach (GameConst::$allItems as $subItems){ foreach (GameConst::$allItems as $subItems) {
foreach($subItems as $itemKey=>$amount){ foreach ($subItems as $itemKey => $amount) {
if($amount == 0){ if ($amount == 0) {
continue; continue;
} }
$itemObj = buildItemClass($itemKey); $itemObj = buildItemClass($itemKey);
$availableUnique[$itemKey] = [ $availableUnique[$itemKey] = [
'title' => $itemObj->getName(), 'title' => $itemObj->getName(),
'info'=>$itemObj->getInfo(), 'info' => $itemObj->getInfo(),
]; ];
} }
} }
@@ -62,8 +62,10 @@ foreach (array_keys(General::INHERITANCE_KEY) as $key) {
$items[$key] = $me->getInheritancePoint($key) ?? 0; $items[$key] = $me->getInheritancePoint($key) ?? 0;
} }
$resetTurnTimeLevel = $me->getAuxVar('inheritResetTurnTime') ?? 0; $resetTurnTimeLevel = ($me->getAuxVar('inheritResetTurnTime') ?? -1) + 1;
$resetSpecialWarLevel = $me->getAuxVar('inheritResetSpecialWar') ?? 0; $resetSpecialWarLevel = ($me->getAuxVar('inheritResetSpecialWar') ?? -1) + 1;
$lastInheritPointLogs = $db->query('SELECT server_id, year, month, date, text FROM user_record WHERE log_type = %s AND user_id = %i ORDER BY id desc LIMIT 30', "inheritPoint", $userID);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -91,10 +93,11 @@ $resetSpecialWarLevel = $me->getAuxVar('inheritResetSpecialWar') ?? 0;
'resetSpecialWar' => calcResetAttrPoint($resetSpecialWarLevel), 'resetSpecialWar' => calcResetAttrPoint($resetSpecialWarLevel),
'randomUnique' => GameConst::$inheritItemRandomPoint, 'randomUnique' => GameConst::$inheritItemRandomPoint,
'nextSpecial' => GameConst::$inheritSpecificSpecialPoint, 'nextSpecial' => GameConst::$inheritSpecificSpecialPoint,
'minSpecificUnique'=>GameConst::$inheritItemUniqueMinPoint, 'minSpecificUnique' => GameConst::$inheritItemUniqueMinPoint,
], ],
'availableSpecialWar' => $avilableSpecialWar, 'availableSpecialWar' => $avilableSpecialWar,
'availableUnique' => $availableUnique, 'availableUnique' => $availableUnique,
'lastInheritPointLogs' => $lastInheritPointLogs,
]) ?> ]) ?>
</head> </head>
-181
View File
@@ -1,181 +0,0 @@
<?php
namespace sammo;
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/oauth_kakao/lib.join.php');
WebUtil::requireAJAX();
use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper;
$RootDB = RootDB::db();
$session = Session::getInstance();
if ($session->isLoggedIn()) {
$session->logout();
}
$username = mb_strtolower(Util::getPost('username'), 'utf-8');
$password = Util::getPost('password');
if (!$username || !$password) {
Json::die([
'result' => false,
'reqOTP' => false,
'reason' => '올바르지 않은 입력입니다.'
]);
}
function kakaoOAuthCheck(array $userInfo): ?array
{
if (!\kakao\KakaoKey::REST_KEY) {
return [false, '카카오 API 앱이 등록되지 않았습니다. 관리자에게 문의해 주세요.'];
}
$oauthID = $userInfo['oauth_id'];
$oauthInfo = Json::decode($userInfo['oauth_info']) ?? [];
if (!$oauthInfo) {
return [false, 'OAuth 정보가 보관되어 있지 않습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessToken = $oauthInfo['accessToken'] ?? null;
$refreshToken = $oauthInfo['refreshToken'] ?? null;
$accessTokenValidUntil = $oauthInfo['accessTokenValidUntil'] ?? null;
$refreshTokenValidUntil = $oauthInfo['refreshTokenValidUntil'] ?? null;
$OTPValue = $oauthInfo['OTPValue'] ?? null;
$OTPTrialUntil = $oauthInfo['OTPTrialUntil'] ?? null;
$tokenValidUntil = $userInfo['token_valid_until'];
if (!$accessToken || !$refreshToken || !$accessTokenValidUntil || !$refreshTokenValidUntil) {
return [false, 'OAuth 정보가 보관되어 있지 않습니다. 카카오 로그인을 수행해 주세요.'];
}
$now = TimeUtil::now();
if ($now > $refreshTokenValidUntil) {
return [false, '로그인 토큰이 만료되었습니다. 카카오 로그인을 수행해 주세요.'];
}
if ($now > $accessTokenValidUntil) {
$apiHelper = new Kakao_REST_API_Helper($accessToken);
$refreshResult = $apiHelper->refresh_access_token($refreshToken);
if (!$refreshResult) {
return [false, '로그인 토큰 자동 갱신을 실패했습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessToken = $refreshResult['access_token'] ?? null;
if (!$accessToken) {
trigger_error("refreshToken 에러 " . Json::encode($refreshResult) . "," . $refreshToken . "," . substr(\kakao\KakaoKey::REST_KEY, 0, 6), E_USER_NOTICE);
return [false, '로그인 토큰 자동 갱신을 실패했습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['expires_in']);
$oauthInfo['accessToken'] = $accessToken;
$oauthInfo['accessTokenValidUntil'] = $accessTokenValidUntil;
$refreshToken = $refreshResult['refresh_token'] ?? null;
if ($refreshToken) {
$refreshTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['refresh_token_expires_in']);
$oauthInfo['refreshToken'] = $refreshToken;
$oauthInfo['refresh_token_expires_in'] = $refreshTokenValidUntil;
}
RootDB::db()->update('member', [
'oauth_info' => Json::encode($oauthInfo)
], 'no=%i', $userInfo['no']);
}
if ($tokenValidUntil && $now <= $tokenValidUntil) {
return null;
}
//인증 시스템 가동
$session = Session::getInstance();
$session->access_token = $accessToken;
$session->expires = $accessTokenValidUntil;
$session->refresh_token = $refreshToken;
$session->refresh_token_expires = $refreshTokenValidUntil;
if (!createOTPbyUserNO($userInfo['no'])) {
return [false, '인증 코드를 보내는데 실패했습니다.'];
}
return [true, '인증 코드를 입력해주세요'];
}
$userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_id, oauth_type, oauth_info, token_valid_until ' .
'from member where id=%s_username AND ' .
'pw=sha2(concat(salt, %s_password, salt), 512)',
[
'username' => $username,
'password' => $password
]
);
if (!$userInfo) {
Json::die([
'result' => false,
'reqOTP' => false,
'reason' => '아이디나 비밀번호가 올바르지 않습니다.'
]);
}
$canLogin = $RootDB->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
if ($canLogin != 'Y' && $userInfo['grade'] < 5) {
Json::die([
'result' => false,
'reason' => '현재는 로그인이 금지되어있습니다!'
]);
}
$nowDate = TimeUtil::now();
if ($userInfo['delete_after']) {
if ($userInfo['delete_after'] < $nowDate) {
$RootDB->delete('member', 'no=%i', $userInfo['no']);
Json::die([
'result' => false,
'reqOTP' => false,
'reason' => "기간 만기로 삭제되었습니다. 재 가입을 시도해주세요."
]);
} else {
Json::die([
'result' => false,
'reqOTP' => false,
'reason' => "삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
]);
}
}
$RootDB->insert('member_log', [
'member_no' => $userInfo['no'],
'action_type' => 'login',
'action' => Json::encode([
'ip' => Util::get_client_ip(true),
'type' => 'plain'
])
]);
if ($userInfo['oauth_type'] == 'KAKAO') {
$oauthFailResult = kakaoOAuthCheck($userInfo);
if ($oauthFailResult !== null) {
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, $userInfo['token_valid_until'], Json::decode($userInfo['acl'] ?? '{}'));
[$oauthReqOTP, $oauthFailReason] = $oauthFailResult;
Json::die([
'result' => false,
'reqOTP' => $oauthReqOTP,
'reason' => $oauthFailReason
]);
}
}
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, $userInfo['token_valid_until'], Json::decode($userInfo['acl'] ?? '{}'));
Json::die([
'result' => true,
'reqOTP' => false,
'reason' => '로그인 되었습니다.'
]);
+1 -1
View File
@@ -230,7 +230,7 @@ if ($server == $baseServerName) {
__DIR__ . '/' . $server . '/d_setting/VersionGit.php', __DIR__ . '/' . $server . '/d_setting/VersionGit.php',
[ [
'verionGit' => $version, 'verionGit' => $version,
'hash' => $hash 'hash' => $gitHash
], ],
true true
); );
+120 -79
View File
@@ -1,25 +1,30 @@
<?php <?php
namespace sammo; namespace sammo;
require(__DIR__.'/../vendor/autoload.php'); require(__DIR__ . '/../vendor/autoload.php');
require('lib.join.php'); require('lib.join.php');
//TODO: KakaoOauth를 API로 정식으로 이동
WebUtil::requireAJAX(); WebUtil::requireAJAX();
use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper; use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper;
$RootDB = RootDB::db(); $RootDB = RootDB::db();
$session = Session::getInstance(); $session = Session::getInstance();
if($session->isLoggedIn()){ if ($session->isLoggedIn()) {
$session->logout(); $session->logout();
} }
$canLogin = RootDB::db()->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1'); $canLogin = RootDB::db()->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
if($canLogin != 'Y'){ if ($canLogin != 'Y') {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'현재는 로그인이 금지되어있습니다!', 'reason' => '현재는 로그인이 금지되어있습니다!',
'noRetry'=>true 'noRetry' => true
]); ]);
} }
@@ -32,84 +37,84 @@ $refresh_token_expires = $session->refresh_token_expires;
$email = $session->kaccount_email; $email = $session->kaccount_email;
if(!$access_token || !$expires){ if (!$access_token || !$expires) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오로그인이 이루어지지 않았습니다.' 'reason' => '카카오로그인이 이루어지지 않았습니다.'
]); ]);
} }
//TODO: join과 login의 동작이 비슷하다. helper class로 묶자. //TODO: join과 login의 동작이 비슷하다. helper class로 묶자.
$restAPI = new Kakao_REST_API_Helper($access_token); $restAPI = new Kakao_REST_API_Helper($access_token);
if($expires < $now && (!$refresh_token || ($refresh_token_expires < $now))){ if ($expires < $now && (!$refresh_token || ($refresh_token_expires < $now))) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'로그인 토큰 만료.'.$refresh_token_expires.' 다시 카카오로그인을 수행해주세요.' 'reason' => '로그인 토큰 만료.' . $refresh_token_expires . ' 다시 카카오로그인을 수행해주세요.'
]); ]);
} }
if($expires < $now){ if ($expires < $now) {
$session->kaccount_email = null; $session->kaccount_email = null;
$email = null; $email = null;
$result = $restAPI->refresh_access_token($refresh_token); $result = $restAPI->refresh_access_token($refresh_token);
if(!isset($refresh_token)){ if (!isset($refresh_token)) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다' 'reason' => '카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다'
]); ]);
} }
$access_token = $result['access_token']; $access_token = $result['access_token'];
$expires = TimeUtil::nowAddSeconds($result['expires_in']); $expires = TimeUtil::nowAddSeconds($result['expires_in']);
if(isset($result['refresh_token'])){ if (isset($result['refresh_token'])) {
$refresh_token = Util::array_get($result['refresh_token']); $refresh_token = Util::array_get($result['refresh_token']);
$refresh_token_expires = TimeUtil::nowAddSeconds($result['refresh_token_expires_in']); $refresh_token_expires = TimeUtil::nowAddSeconds($result['refresh_token_expires_in']);
} }
} }
if(!$email){ if (!$email) {
$me = $restAPI->meWithEmail(); $me = $restAPI->meWithEmail();
$me['code'] = Util::array_get($me['code'], 0); $me['code'] = Util::array_get($me['code'], 0);
if ($me['code']< 0) { if ($me['code'] < 0) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오로그인이 정상적으로 수행되지 않았습니다.' 'reason' => '카카오로그인이 정상적으로 수행되지 않았습니다.'
]); ]);
} }
$kakao_account = $me['kakao_account']??null; $kakao_account = $me['kakao_account'] ?? null;
if (!$kakao_account) { if (!$kakao_account) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오 로그인 정보를 제대로 받아오지 못했습니다.' 'reason' => '카카오 로그인 정보를 제대로 받아오지 못했습니다.'
]); ]);
} }
if(!($kakao_account['has_email']??false)){ if (!($kakao_account['has_email'] ?? false)) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'이메일 정보 공유를 허가해 주셔야 합니다.', 'reason' => '이메일 정보 공유를 허가해 주셔야 합니다.',
]); ]);
} }
$validEmail = $kakao_account['is_email_valid']??false; $validEmail = $kakao_account['is_email_valid'] ?? false;
$verifiedEmail = $kakao_account['is_email_verified']??false; $verifiedEmail = $kakao_account['is_email_verified'] ?? false;
if(!$validEmail || !$verifiedEmail){ if (!$validEmail || !$verifiedEmail) {
$restAPI->unlink(); $restAPI->unlink();
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다', 'reason' => '카카오 계정 이메일이 아직 인증되지 않았습니다',
]); ]);
} }
@@ -119,86 +124,122 @@ if(!$email){
$userInfo = $RootDB->queryFirstRow( $userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_info, token_valid_until from member where email=%s',$email); 'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_info, token_valid_until from member where email=%s',
$email
);
if(!$userInfo){ if (!$userInfo) {
$restAPI->unlink(); $restAPI->unlink();
$session->access_token = null; $session->access_token = null;
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.', 'reason' => '카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.',
'aux'=>$session->tmpx, 'aux' => $session->tmpx,
]); ]);
} }
if($userInfo['delete_after']){ if ($userInfo['delete_after']) {
if($userInfo['delete_after'] < $now){ if ($userInfo['delete_after'] < $now) {
$restAPI->unlink(); $restAPI->unlink();
$session->access_token = null; $session->access_token = null;
$RootDB->delete('member', 'no=%i', $userInfo['no']); $RootDB->delete('member', 'no=%i', $userInfo['no']);
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>"기간 만기로 삭제되었습니다. 재 가입을 시도해주세요.", 'reason' => "기간 만기로 삭제되었습니다. 재 가입을 시도해주세요.",
]); ]);
} } else {
else{
$restAPI->unlink(); $restAPI->unlink();
$session->access_token = null; $session->access_token = null;
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>"삭제 요청된 계정입니다.[{$userInfo['delete_after']}]" 'reason' => "삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
]); ]);
} }
} }
$oauthInfo = Json::decode($userInfo['oauth_info'])??[]; $oauthInfo = Json::decode($userInfo['oauth_info']) ?? [];
$oauthInfo['accessToken'] = $access_token; $oauthInfo['accessToken'] = $access_token;
$oauthInfo['accessTokenValidUntil'] = $expires; $oauthInfo['accessTokenValidUntil'] = $expires;
if($refresh_token){ if ($refresh_token) {
$oauthInfo['refreshToken'] = $refresh_token; $oauthInfo['refreshToken'] = $refresh_token;
$oauthInfo['refreshTokenValidUntil'] = $refresh_token_expires; $oauthInfo['refreshTokenValidUntil'] = $refresh_token_expires;
} }
RootDB::db()->update('member', [ RootDB::db()->update('member', [
'oauth_info'=>Json::encode($oauthInfo) 'oauth_info' => Json::encode($oauthInfo)
], 'no=%i', $userInfo['no']); ], 'no=%i', $userInfo['no']);
$tokenValidUntil = $userInfo['token_valid_until']; $tokenValidUntil = $userInfo['token_valid_until'];
if(!$tokenValidUntil || $tokenValidUntil < $now){ if (!$tokenValidUntil || $tokenValidUntil < $now) {
if(!createOTPbyUserNO($userInfo['no'])){ if (!createOTPbyUserNO($userInfo['no'])) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'인증 코드를 보내는데 실패했습니다.' 'reason' => '인증 코드를 보내는데 실패했습니다.'
]); ]);
} }
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, $userInfo['token_valid_until'], Json::decode($userInfo['acl']??'{}')); $session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, $userInfo['token_valid_until'], null, Json::decode($userInfo['acl'] ?? '{}'));
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reqOTP'=>true, 'reqOTP' => true,
'reason'=>'인증 코드를 입력해주세요.' 'reason' => '인증 코드를 입력해주세요.'
]); ]);
} }
$RootDB->insert('member_log',[ $RootDB->insert('member_log', [
'member_no'=>$userInfo['no'], 'member_no' => $userInfo['no'],
'action_type'=>'login', 'action_type' => 'login',
'action'=>Json::encode([ 'action' => Json::encode([
'ip'=>Util::get_client_ip(true), 'ip' => Util::get_client_ip(true),
'type'=>'kakao' 'type' => 'kakao'
]) ])
]); ]);
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, $userInfo['token_valid_until'], Json::decode($userInfo['acl']??'{}'));
//TODO: 이동하면서 이부분 정리
$nowDate = TimeUtil::now();
$RootDB->delete(
'login_token',
'user_id = %i AND expire_date < %s',
$userID,
$nowDate
);
$RootDB->query(
'DELETE invalid FROM login_token AS invalid
JOIN
( SELECT id
FROM login_token
WHERE user_id = %i
ORDER BY id DESC
LIMIT 8,1
) AS valid
ON invalid.id < valid.id WHERE user_id = %i',
$userID,
$userID
);
$token = Util::randomStr(20);
$RootDB->insert('login_token', [
'user_id' => $userInfo['no'],
'base_token' => $token,
'reg_ip' => Util::get_client_ip(true),
'reg_date' => $nowDate,
'expire_date' => TimeUtil::nowAddDays(7)
]);
$tokenID = $RootDB->insertId();
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, $userInfo['token_valid_until'], $tokenID, Json::decode($userInfo['acl'] ?? '{}'));
Json::die([ Json::die([
'result'=>true, 'result' => true,
'reqOTP'=>false, 'reqOTP' => false,
'reason'=>'로그인 되었습니다.' 'nextToken' => [$tokenID, $token],
'reason' => '로그인 되었습니다.'
]); ]);
+13 -15
View File
@@ -27,8 +27,8 @@
"axios": "^0.21.4", "axios": "^0.21.4",
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"bootstrap5": "npm:bootstrap@^5.1.1", "bootstrap5": "npm:bootstrap@^5.1.1",
"core-js": "^3.17.2", "core-js": "^3.17.3",
"date-fns": "^2.23.0", "date-fns": "^2.24.0",
"downloadjs": "^1.4.7", "downloadjs": "^1.4.7",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"js-sha512": "^0.8.0", "js-sha512": "^0.8.0",
@@ -45,39 +45,37 @@
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.15.4", "@babel/cli": "^7.15.4",
"@babel/core": "^7.15.5", "@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.4", "@babel/preset-env": "^7.15.6",
"@babel/preset-typescript": "^7.15.0", "@babel/preset-typescript": "^7.15.0",
"@coreui/vue": "^4.0.0-beta.2", "@coreui/vue": "^4.0.0-beta.2",
"@types/bootstrap": "^5.1.4", "@types/bootstrap": "^5.1.4",
"@types/jquery": "^3.5.6", "@types/jquery": "^3.5.6",
"@types/lodash": "^4.14.172", "@types/lodash": "^4.14.173",
"@types/node": "^16.7.13", "@types/node": "^16.9.2",
"@typescript-eslint/eslint-plugin": "^4.31.0", "@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.0", "@typescript-eslint/parser": "^4.31.1",
"@vue/compiler-sfc": "^3.2.10", "@vue/compiler-sfc": "^3.2.12",
"@vue/eslint-config-typescript": "^7.0.0", "@vue/eslint-config-typescript": "^7.0.0",
"babel-loader": "^8.2.2",
"babel-plugin-lodash": "^3.3.4", "babel-plugin-lodash": "^3.3.4",
"babel-preset-modern-browsers": "^15.0.2", "babel-preset-modern-browsers": "^15.0.2",
"bootstrap-vue-3": "^0.0.3", "bootstrap-vue-3": "^0.0.3",
"bootswatch": "^5.1.1", "bootswatch": "^5.1.1",
"clean-terminal-webpack-plugin": "^3.0.0", "clean-terminal-webpack-plugin": "^3.0.0",
"css-loader": "^6.2.0", "css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^3.0.2", "esbuild-loader": "^2.15.1",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"mini-css-extract-plugin": "^2.2.2", "mini-css-extract-plugin": "^2.3.0",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"sass": "^1.39.0", "sass": "^1.41.1",
"sass-loader": "^12.1.0", "sass-loader": "^12.1.0",
"style-loader": "^3.2.1", "style-loader": "^3.2.1",
"ts-loader": "^9.2.5", "typescript": "^4.4.3",
"typescript": "^4.4.2",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"vue-eslint-parser": "^7.11.0", "vue-eslint-parser": "^7.11.0",
"vue-loader": "^16.5.0", "vue-loader": "^16.5.0",
"vue-style-loader": "^4.1.3", "vue-style-loader": "^4.1.3",
"webpack": "^5.52.0", "webpack": "^5.53.0",
"webpack-bundle-analyzer": "^4.4.2", "webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.8.0" "webpack-cli": "^4.8.0"
}, },
+162
View File
@@ -0,0 +1,162 @@
<?php
namespace sammo\API\Login;
use DateTime;
use sammo\Session;
use DateTimeInterface;
use sammo\BaseAPI;
use sammo\Json;
use sammo\KakaoUtil;
use sammo\RootDB;
use sammo\TimeUtil;
use sammo\Util;
use sammo\Validator;
class LoginByID extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'username',
'password'
]);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return BaseAPI::NO_SESSION;
}
public function scrubToken(int $userID)
{
$RootDB = RootDB::db();
$nowDate = TimeUtil::now();
$RootDB->delete(
'login_token',
'user_id = %i AND expire_date < %s',
$userID,
$nowDate
);
$RootDB->query(
'DELETE invalid FROM login_token AS invalid
JOIN
( SELECT id
FROM login_token
WHERE user_id = %i
ORDER BY id DESC
LIMIT 8,1
) AS valid
ON invalid.id < valid.id WHERE user_id = %i',
$userID,
$userID
);
}
public function addToken(int $userID)
{
$RootDB = RootDB::db();
$nowDate = TimeUtil::now();
$token = Util::randomStr(20);
$RootDB->insert('login_token', [
'user_id' => $userID,
'base_token' => $token,
'reg_ip' => Util::get_client_ip(true),
'reg_date' => $nowDate,
'expire_date' => TimeUtil::nowAddDays(7)
]);
$tokenID = $RootDB->insertId();
return [$tokenID, $token];
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$RootDB = RootDB::db();
if ($session->isLoggedIn()) {
$session->logout();
}
$username = $this->args['username'];
$password = $this->args['password'];
$userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_id, oauth_type, oauth_info, token_valid_until ' .
'from member where id=%s_username AND ' .
'pw=sha2(concat(salt, %s_password, salt), 512)',
[
'username' => $username,
'password' => $password
]
);
if (!$userInfo) {
return '아이디나 비밀번호가 올바르지 않습니다.';
}
$canLogin = $RootDB->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
if ($canLogin != 'Y' && $userInfo['grade'] < 5) {
return '현재는 로그인이 금지되어있습니다!';
}
$nowDate = TimeUtil::now();
if ($userInfo['delete_after']) {
if ($userInfo['delete_after'] < $nowDate) {
$RootDB->delete('member', 'no=%i', $userInfo['no']);
return [
'result' => false,
'reqOTP' => false,
'reason' => "기간 만기로 삭제되었습니다. 재 가입을 시도해주세요."
];
} else {
return [
'result' => false,
'reqOTP' => false,
'reason' => "삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
];
}
}
$RootDB->insert('member_log', [
'member_no' => $userInfo['no'],
'action_type' => 'login',
'action' => Json::encode([
'ip' => Util::get_client_ip(true),
'type' => 'plain'
])
]);
if ($userInfo['oauth_type'] == 'KAKAO') {
$oauthFailResult = KakaoUtil::kakaoOAuthCheck($userInfo);
if ($oauthFailResult !== null) {
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, $userInfo['token_valid_until'], null, Json::decode($userInfo['acl'] ?? '{}'));
[$oauthReqOTP, $oauthFailReason] = $oauthFailResult;
return [
'result' => false,
'reqOTP' => $oauthReqOTP,
'reason' => $oauthFailReason
];
}
}
$this->scrubToken($userInfo['no']);
$nextToken = $this->addToken($userInfo['no']);
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, $userInfo['token_valid_until'], $nextToken[0], Json::decode($userInfo['acl'] ?? '{}'));
return [
'result' => true,
'reqOTP' => false,
'nextToken' => $nextToken,
'reason' => '로그인 되었습니다.'
];
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
namespace sammo\API\Login;
use sammo\Session;
use DateTimeInterface;
use sammo\BaseAPI;
use sammo\Json;
use sammo\KakaoUtil;
use sammo\RootDB;
use sammo\TimeUtil;
use sammo\Util;
use sammo\Validator;
class LoginByToken extends LoginByID
{
public function getRequiredSessionMode(): int
{
return \sammo\BaseAPI::NO_SESSION; //XXX: Token 때문에 엄밀히는 NO_SESSION이 아님
}
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'token_id',
'hashedToken'
]);
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
{
$loginNonce = $session->loginNonce ?? null;
$loginNonceExpired = $session->loginNonceExpired ?? null;
if (!is_string($loginNonce) || !is_string($loginNonceExpired)) {
return '자동 로그인: 절차 오류';
}
$RootDB = RootDB::db();
if ($session->isLoggedIn()) {
$session->logout();
}
$token_id = $this->args['token_id'];
$token_info = $RootDB->queryFirstRow('SELECT * FROM login_token WHERE id = %i', $token_id);
if (!$token_info) {
return [
'result' => false,
'silent' => true,
'reason' => 'failed'
];
}
$hashedToken = $this->args['hashedToken'];
$tokenAnswer = hash('sha512', "{$token_info['base_token']}{$loginNonce}");
if (strtolower($hashedToken) != strtolower($tokenAnswer)) {
return [
'result' => false,
'silent' => true,
'reason' => 'failed'
];
}
$userInfo = $RootDB->queryFirstRow(
'SELECT `no`, `id`, `name`, `grade`, `delete_after`, `acl`, oauth_id, oauth_type, oauth_info, token_valid_until ' .
'from member where NO = %i',
$token_info['user_id']
);
if(!$userInfo){
return '자동 로그인: 올바른 계정이 아닙니다.';
}
$canLogin = $RootDB->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
if ($canLogin != 'Y' && $userInfo['grade'] < 5) {
return '자동 로그인: 현재는 로그인이 금지되어있습니다!';
}
$nowDate = TimeUtil::now();
if ($userInfo['delete_after']) {
if ($userInfo['delete_after'] < $nowDate) {
$RootDB->delete('member', 'no=%i', $userInfo['no']);
return [
'result' => false,
'silent' => true,
'reason' => "기간 만기"
];
} else {
return [
'result' => false,
'silent' => true,
'reason' => "삭제 요청된 계정[{$userInfo['delete_after']}]"
];
}
}
$RootDB->insert('member_log', [
'member_no' => $userInfo['no'],
'action_type' => 'login',
'action' => Json::encode([
'ip' => Util::get_client_ip(true),
'type' => 'auto'
])
]);
if ($userInfo['oauth_type'] == 'KAKAO') {
$oauthFailResult = KakaoUtil::kakaoOAuthCheck($userInfo);
if ($oauthFailResult !== null) {
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], true, $userInfo['token_valid_until'], null, Json::decode($userInfo['acl'] ?? '{}'));
[$oauthReqOTP, $oauthFailReason] = $oauthFailResult;
$RootDB->delete(
'login_token',
'id = %i', $token_id
);
return $oauthFailReason;
}
}
$session->login($userInfo['no'], $userInfo['id'], $userInfo['grade'], false, $userInfo['token_valid_until'], $token_id, Json::decode($userInfo['acl'] ?? '{}'));
$this->scrubToken($userInfo['no']);
$nextDate = TimeUtil::nowAddDays(2);
if($nextDate < $token_info['expire_date']){
return [
'result' => true,
'silent' => true,
'reason' => 'success'
];
}
$RootDB->delete(
'login_token',
'id = %i', $token_id
);
$nextToken = $this->addToken($token_id);
return [
'result' => true,
'silent' => true,
'nextToken' => $nextToken,
'reason' => 'success'
];
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace sammo\API\Login;
use sammo\Session;
use DateTimeInterface;
use sammo\BaseAPI;
use sammo\Json;
use sammo\KakaoUtil;
use sammo\RootDB;
use sammo\TimeUtil;
use sammo\Util;
use sammo\Validator;
class ReqNonce extends BaseAPI{
public function getRequiredSessionMode(): int {
return \sammo\BaseAPI::NO_SESSION;
}
public function validateArgs(): ?string
{
return null;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag) {
$loginNonce = Util::randomStr(16);
$loginNonceExpired = TimeUtil::nowAddSeconds(2);
$session->loginNonce = $loginNonce;
$session->loginNonceExpired = $loginNonceExpired;
return [
'result'=>true,
'loginNonce'=>$loginNonce,
];
}
}
+4 -4
View File
@@ -40,7 +40,7 @@ class APIHelper
$sessionMode = $obj->getRequiredSessionMode(); $sessionMode = $obj->getRequiredSessionMode();
if ($sessionMode === BaseAPI::NO_SESSION) { if ($sessionMode === BaseAPI::NO_SESSION) {
$session = null; $session = Session::getInstance();//XXX: NoSession이면 진짜 NoSession이어야..?
} else { } else {
if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) { if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) {
$session = Session::requireGameLogin(); $session = Session::requireGameLogin();
@@ -71,7 +71,7 @@ class APIHelper
[$lastModified, $etag] = $cacheResult; [$lastModified, $etag] = $cacheResult;
if ($lastModified !== null) { if ($lastModified !== null) {
header("Last-Modified: " . gmdate("D, d M Y H:i:s", TimeUtil::DateTimeToSeconds($lastModified, true)) . " GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s", Util::toInt(TimeUtil::DateTimeToSeconds($lastModified, true))) . " GMT");
} }
if ($etag !== null) { if ($etag !== null) {
header("Etag: $etag"); header("Etag: $etag");
@@ -94,10 +94,10 @@ class APIHelper
], $cacheResult === null ? Json::NO_CACHE : 0); ], $cacheResult === null ? Json::NO_CACHE : 0);
} }
Json::die($result, $cacheResult === null ? Json::NO_CACHE : 0); Json::die($result, $cacheResult === null ? Json::NO_CACHE : 0);
} catch (\Exception $e) { } catch (\Throwable $e) {
Json::dieWithReason($e->getMessage()); Json::dieWithReason($e->getMessage());
} catch (mixed $e) { } catch (mixed $e) {
Json::dieWithReason($e); Json::dieWithReason(strval($e));
} }
} }
} }
+1
View File
@@ -39,6 +39,7 @@ class Json
return json_decode($value); return json_decode($value);
} }
/** @return never */
public static function die($value, $flag = self::NO_CACHE) public static function die($value, $flag = self::NO_CACHE)
{ {
//NOTE: REST 형식에 맞게, ok(), fail()로 쪼개는게 낫지 않을까 생각해봄. //NOTE: REST 형식에 맞게, ok(), fail()로 쪼개는게 낫지 않을까 생각해봄.
+221
View File
@@ -0,0 +1,221 @@
<?php
namespace sammo;
use kakao\Kakao_REST_API_Helper;
class KakaoUtil
{
private function __construct()
{
}
static function checkUsernameDup($username)
{
if (!$username) {
return '계정명을 입력해주세요';
}
$username = mb_strtolower($username, 'utf-8');
$length = strlen($username);
if ($length < 4 || $length > 64) {
return '적절하지 않은 길이입니다.';
}
$cnt = RootDB::db()->queryFirstField('SELECT count(no) FROM member WHERE `id` = %s LIMIT 1', $username);
if ($cnt != 0) {
return '이미 사용중인 계정명입니다';
}
return true;
}
static function checkNicknameDup($nickname)
{
if (!$nickname) {
return '닉네임을 입력해주세요';
}
$length = mb_strwidth($nickname, 'utf-8');
if ($length < 1 || $length > 18) {
return '적절하지 않은 길이입니다.';
}
$cnt = RootDB::db()->queryFirstField('SELECT count(no) FROM member WHERE `name` = %s LIMIT 1', $nickname);
if ($cnt != 0) {
return '이미 사용중인 닉네임입니다';
}
return true;
}
static function checkEmailDup($email)
{
if (!$email) {
return '이메일을 입력해주세요';
}
$length = strlen($email);
if ($length < 1 || $length > 64) {
return '적절하지 않은 길이입니다.';
}
$userInfo = RootDB::db()->queryFirstField('SELECT `no`, `delete_after` FROM member WHERE `email` = %s LIMIT 1', $email);
if ($userInfo) {
if (!$userInfo['delete_after']) {
return '이미 사용중인 이메일입니다. 관리자에게 문의해주세요.';
}
if ($userInfo['delete_after'] >= $userInfo) {
return "삭제 요청된 계정입니다.[{$userInfo['delete_after']}]";
}
//$userInfo['delete_after'] < $userInfo
RootDB::db()->delete('member', 'no=%i', $userInfo['no']);
}
return true;
}
static function createOTPbyUserNO(int $userNo): bool
{
$userInfo = RootDB::db()->queryFirstRow('SELECT oauth_info FROM member WHERE no=%i', $userNo);
if (!$userInfo) {
return false;
}
$oauthInfo = Json::decode($userInfo['oauth_info']);
if (!$oauthInfo) {
return false;
}
$accessToken = $oauthInfo['accessToken'];
$OTPValue = $oauthInfo['OTPValue'] ?? null;
$OTPTrialUntil = $oauthInfo['OTPTrialUntil'] ?? null;
$now = TimeUtil::now();
if ($OTPTrialUntil && $OTPValue && $OTPTrialUntil > $now) {
return true;
}
[$OTPValue, $OTPTrialUntil] = static::createOTP($accessToken);
if (!$OTPValue) {
return false;
}
$oauthInfo['OTPValue'] = $OTPValue;
$oauthInfo['OTPTrialUntil'] = $OTPTrialUntil;
$oauthInfo['OTPTrialCount'] = 3;
RootDB::db()->update('member', [
'oauth_info' => Json::encode($oauthInfo)
], 'no=%i', $userNo);
return true;
}
static function createOTP(string $accessToken): ?array
{
$restAPI = new Kakao_REST_API_Helper($accessToken);
$OTPValue = Util::randRangeInt(1000, 9999);
$OTPTrialUntil = TimeUtil::nowAddSeconds(180);
$sendResult = $restAPI->talk_to_me_default([
"object_type" => "text",
"text" => "인증 코드는 $OTPValue 입니다. $OTPTrialUntil 이내에 입력해주세요.",
"link" => [
"web_url" => ServConfig::getServerBasepath(),
"mobile_web_url" => ServConfig::getServerBasepath()
],
"button_title" => "로그인 페이지 열기"
]);
$sendResult['code'] = Util::array_get($sendResult['code'], 0);
if ($sendResult['code'] < 0) {
return null;
}
return [$OTPValue, $OTPTrialUntil];
}
static function kakaoOAuthCheck(array $userInfo): ?array
{
if (!\kakao\KakaoKey::REST_KEY) {
return [false, '카카오 API 앱이 등록되지 않았습니다. 관리자에게 문의해 주세요.'];
}
$oauthID = $userInfo['oauth_id'];
$oauthInfo = Json::decode($userInfo['oauth_info']) ?? [];
if (!$oauthInfo) {
return [false, 'OAuth 정보가 보관되어 있지 않습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessToken = $oauthInfo['accessToken'] ?? null;
$refreshToken = $oauthInfo['refreshToken'] ?? null;
$accessTokenValidUntil = $oauthInfo['accessTokenValidUntil'] ?? null;
$refreshTokenValidUntil = $oauthInfo['refreshTokenValidUntil'] ?? null;
$OTPValue = $oauthInfo['OTPValue'] ?? null;
$OTPTrialUntil = $oauthInfo['OTPTrialUntil'] ?? null;
$tokenValidUntil = $userInfo['token_valid_until'];
if (!$accessToken || !$refreshToken || !$accessTokenValidUntil || !$refreshTokenValidUntil) {
return [false, 'OAuth 정보가 보관되어 있지 않습니다. 카카오 로그인을 수행해 주세요.'];
}
$now = TimeUtil::now();
if ($now > $refreshTokenValidUntil) {
return [false, '로그인 토큰이 만료되었습니다. 카카오 로그인을 수행해 주세요.'];
}
if ($now > $accessTokenValidUntil) {
$apiHelper = new Kakao_REST_API_Helper($accessToken);
$refreshResult = $apiHelper->refresh_access_token($refreshToken);
if (!$refreshResult) {
return [false, '로그인 토큰 자동 갱신을 실패했습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessToken = $refreshResult['access_token'] ?? null;
if (!$accessToken) {
trigger_error("refreshToken 에러 " . Json::encode($refreshResult) . "," . $refreshToken . "," . substr(\kakao\KakaoKey::REST_KEY, 0, 6), E_USER_NOTICE);
return [false, '로그인 토큰 자동 갱신을 실패했습니다. 카카오 로그인을 수행해 주세요.'];
}
$accessTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['expires_in']);
$oauthInfo['accessToken'] = $accessToken;
$oauthInfo['accessTokenValidUntil'] = $accessTokenValidUntil;
$refreshToken = $refreshResult['refresh_token'] ?? null;
if ($refreshToken) {
$refreshTokenValidUntil = TimeUtil::nowAddSeconds($refreshResult['refresh_token_expires_in']);
$oauthInfo['refreshToken'] = $refreshToken;
$oauthInfo['refresh_token_expires_in'] = $refreshTokenValidUntil;
}
RootDB::db()->update('member', [
'oauth_info' => Json::encode($oauthInfo)
], 'no=%i', $userInfo['no']);
}
if ($tokenValidUntil && $now <= $tokenValidUntil) {
return null;
}
//인증 시스템 가동
$session = Session::getInstance();
$session->access_token = $accessToken;
$session->expires = $accessTokenValidUntil;
$session->refresh_token = $refreshToken;
$session->refresh_token_expires = $refreshTokenValidUntil;
if (!createOTPbyUserNO($userInfo['no'])) {
return [false, '인증 코드를 보내는데 실패했습니다.'];
}
return [true, '인증 코드를 입력해주세요'];
}
}
+7 -1
View File
@@ -10,6 +10,7 @@ namespace sammo;
* @property string $ip IP * @property string $ip IP
* @property bool $reqOTP 인증 코드 필요 * @property bool $reqOTP 인증 코드 필요
* @property array $acl 권한 * @property array $acl 권한
* @property int|null $tokenID 토큰ID
* @property string $tokenValidUntil 로그인 토큰 길이 * @property string $tokenValidUntil 로그인 토큰 길이
* *
* @property int $generalID 장수 번호 (게임 로그인 필요) * @property int $generalID 장수 번호 (게임 로그인 필요)
@@ -170,7 +171,7 @@ class Session
return Util::array_get($_SESSION[$name]); return Util::array_get($_SESSION[$name]);
} }
public function login(int $userID, string $userName, int $grade, bool $reqOTP, ?string $tokenValidUntil, array $acl): Session public function login(int $userID, string $userName, int $grade, bool $reqOTP, ?string $tokenValidUntil, ?int $tokenID, array $acl): Session
{ {
$this->set('userID', $userID); $this->set('userID', $userID);
$this->set('userName', $userName); $this->set('userName', $userName);
@@ -180,6 +181,7 @@ class Session
$this->set('acl', $acl); $this->set('acl', $acl);
$this->set('reqOTP', $reqOTP); $this->set('reqOTP', $reqOTP);
$this->set('tokenValidUntil', $tokenValidUntil); $this->set('tokenValidUntil', $tokenValidUntil);
$this->set('tokenID', $tokenID);
return $this; return $this;
} }
@@ -198,6 +200,10 @@ class Session
$this->logoutGame(); $this->logoutGame();
} }
if($this->tokenID??null){
RootDB::db()->delete('login_token', 'id = %i', $this->tokenID);
}
$this->set('userID', null); $this->set('userID', null);
$this->set('userName', null); $this->set('userName', null);
$this->set('userGrade', null); $this->set('userGrade', null);
+1 -1
View File
@@ -618,7 +618,7 @@ class Util extends \utilphp\util
* *
* @param array $items 선택하고자 하는 배열 * @param array $items 선택하고자 하는 배열
* *
* @return int|float|string|object 선택된 value값. * @return int|float|string|array|object 선택된 value값.
*/ */
public static function choiceRandom(array $items) public static function choiceRandom(array $items)
{ {
Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../nesbot/carbon/bin/carbon
+154 -5
View File
@@ -29,7 +29,7 @@ private static $installed = array (
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf', 'reference' => 'cf3f40b5787b2a1aed9255775143108ef5b1f278',
'name' => 'sammo-hid/sammo', 'name' => 'sammo-hid/sammo',
), ),
'versions' => 'versions' =>
@@ -70,6 +70,15 @@ private static $installed = array (
), ),
'reference' => '84674dd3a7575ba617f5a76d7e9e29a7d3891339', 'reference' => '84674dd3a7575ba617f5a76d7e9e29a7d3891339',
), ),
'doctrine/inflector' =>
array (
'pretty_version' => '2.0.3',
'version' => '2.0.3.0',
'aliases' =>
array (
),
'reference' => '9cf661f4eb38f7c881cac67c75ea9b00bf97b210',
),
'erusev/parsedown' => 'erusev/parsedown' =>
array ( array (
'pretty_version' => '1.7.4', 'pretty_version' => '1.7.4',
@@ -142,6 +151,87 @@ private static $installed = array (
), ),
'reference' => 'dc960a912984efb74d0a90222870c72c87f10c91', 'reference' => 'dc960a912984efb74d0a90222870c72c87f10c91',
), ),
'illuminate/bus' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '808097c0dfd893309bd77b00139586c516b965c9',
),
'illuminate/collections' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '18fa841df912ec56849351dd6ca8928e8a98b69d',
),
'illuminate/container' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '862b64ea4ab56e307a1676104a1b93295d347ad0',
),
'illuminate/contracts' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => 'ab4bb4ec3b36905ccf972c84f9aaa2bdd1153913',
),
'illuminate/database' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => 'acc11d6839ddb3b694bc6585177fa5141b70c693',
),
'illuminate/events' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '7def78033f29cd0c0383513b27c291d233a7f90e',
),
'illuminate/macroable' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '300aa13c086f25116b5f3cde3ca54ff5c822fb05',
),
'illuminate/pipeline' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => '23aeff5b26ae4aee3f370835c76bd0f4e93f71d2',
),
'illuminate/support' =>
array (
'pretty_version' => 'v8.61.0',
'version' => '8.61.0.0',
'aliases' =>
array (
),
'reference' => 'b0a21c41163381dd9a5abbd68fe85ed7b4247d30',
),
'league/plates' => 'league/plates' =>
array ( array (
'pretty_version' => 'v3.4.0', 'pretty_version' => 'v3.4.0',
@@ -169,6 +259,15 @@ private static $installed = array (
), ),
'reference' => 'c6b00f05152ae2c9b04a448f99c7590beb6042f5', 'reference' => 'c6b00f05152ae2c9b04a448f99c7590beb6042f5',
), ),
'nesbot/carbon' =>
array (
'pretty_version' => '2.53.1',
'version' => '2.53.1.0',
'aliases' =>
array (
),
'reference' => 'f4655858a784988f880c1b8c7feabbf02dfdf045',
),
'netresearch/jsonmapper' => 'netresearch/jsonmapper' =>
array ( array (
'pretty_version' => 'v4.0.0', 'pretty_version' => 'v4.0.0',
@@ -216,12 +315,12 @@ private static $installed = array (
), ),
'phan/phan' => 'phan/phan' =>
array ( array (
'pretty_version' => '5.0.0', 'pretty_version' => '5.2.1',
'version' => '5.0.0.0', 'version' => '5.2.1.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => 'f36b6b9a2f4143a25f35ce94d712ceb0527e9d90', 'reference' => 'd724bbb8fc3ba89179868bb5220ecdf6a9c1636b',
), ),
'php-extended/php-system' => 'php-extended/php-system' =>
array ( array (
@@ -277,6 +376,13 @@ private static $installed = array (
), ),
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf', 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
), ),
'psr/container-implementation' =>
array (
'provided' =>
array (
0 => '1.0',
),
),
'psr/http-message' => 'psr/http-message' =>
array ( array (
'pretty_version' => '1.0.1', 'pretty_version' => '1.0.1',
@@ -310,6 +416,15 @@ private static $installed = array (
1 => '1.0|2.0', 1 => '1.0|2.0',
), ),
), ),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'ralouphie/getallheaders' => 'ralouphie/getallheaders' =>
array ( array (
'pretty_version' => '3.0.3', 'pretty_version' => '3.0.3',
@@ -335,7 +450,7 @@ private static $installed = array (
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf', 'reference' => 'cf3f40b5787b2a1aed9255775143108ef5b1f278',
), ),
'scssphp/scssphp' => 'scssphp/scssphp' =>
array ( array (
@@ -472,6 +587,31 @@ private static $installed = array (
), ),
'reference' => 'bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1', 'reference' => 'bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1',
), ),
'symfony/translation' =>
array (
'pretty_version' => 'v5.3.7',
'version' => '5.3.7.0',
'aliases' =>
array (
),
'reference' => '4d595a6d15fd3a2c67f6f31d14d15d3b7356d7a6',
),
'symfony/translation-contracts' =>
array (
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
),
'symfony/translation-implementation' =>
array (
'provided' =>
array (
0 => '2.3',
),
),
'tysonandre/var_representation_polyfill' => 'tysonandre/var_representation_polyfill' =>
array ( array (
'pretty_version' => '0.0.2', 'pretty_version' => '0.0.2',
@@ -490,6 +630,15 @@ private static $installed = array (
), ),
'reference' => '5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb', 'reference' => '5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb',
), ),
'voku/portable-ascii' =>
array (
'pretty_version' => '1.5.6',
'version' => '1.5.6.0',
'aliases' =>
array (
),
'reference' => '80953678b19901e5165c56752d087fc11526017c',
),
'webmozart/assert' => 'webmozart/assert' =>
array ( array (
'pretty_version' => '1.10.0', 'pretty_version' => '1.10.0',
+5 -1
View File
@@ -8,12 +8,15 @@ $baseDir = dirname($vendorDir);
return array( return array(
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php', '2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php', 'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php', 'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
@@ -25,6 +28,7 @@ return array(
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'6714be961f4a45ae8b9a99d5d55c5d07' => $vendorDir . '/tysonandre/var_representation_polyfill/src/var_representation.php', '6714be961f4a45ae8b9a99d5d55c5d07' => $vendorDir . '/tysonandre/var_representation_polyfill/src/var_representation.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'ef65a1626449d89d0811cf9befce46f0' => $vendorDir . '/illuminate/events/functions.php',
'5b154887902198b16314243c6e0e3e19' => $vendorDir . '/pguardiario/phpuri/phpuri.php', '5b154887902198b16314243c6e0e3e19' => $vendorDir . '/pguardiario/phpuri/phpuri.php',
'870dc64919afa8b0f700701bb2c6a783' => $baseDir . '/f_config/config.php', '870dc64919afa8b0f700701bb2c6a783' => $baseDir . '/f_config/config.php',
); );
+13
View File
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
'sammo\\' => array($baseDir . '/src/sammo'), 'sammo\\' => array($baseDir . '/src/sammo'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
'kakao\\' => array($baseDir . '/src/kakao'), 'kakao\\' => array($baseDir . '/src/kakao'),
@@ -20,12 +21,15 @@ return array(
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'), 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
'Symfony\\Component\\Lock\\' => array($vendorDir . '/symfony/lock'), 'Symfony\\Component\\Lock\\' => array($vendorDir . '/symfony/lock'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'), 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'),
'Sabre\\Event\\' => array($vendorDir . '/sabre/event/lib'), 'Sabre\\Event\\' => array($vendorDir . '/sabre/event/lib'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
@@ -36,10 +40,19 @@ return array(
'Microsoft\\PhpParser\\' => array($vendorDir . '/microsoft/tolerant-php-parser/src'), 'Microsoft\\PhpParser\\' => array($vendorDir . '/microsoft/tolerant-php-parser/src'),
'Medoo\\' => array($vendorDir . '/catfan/medoo/src'), 'Medoo\\' => array($vendorDir . '/catfan/medoo/src'),
'League\\Plates\\' => array($vendorDir . '/league/plates/src'), 'League\\Plates\\' => array($vendorDir . '/league/plates/src'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/support'),
'Illuminate\\Pipeline\\' => array($vendorDir . '/illuminate/pipeline'),
'Illuminate\\Events\\' => array($vendorDir . '/illuminate/events'),
'Illuminate\\Database\\' => array($vendorDir . '/illuminate/database'),
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'Illuminate\\Container\\' => array($vendorDir . '/illuminate/container'),
'Illuminate\\Bus\\' => array($vendorDir . '/illuminate/bus'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'), 'Composer\\XdebugHandler\\' => array($vendorDir . '/composer/xdebug-handler/src'),
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'AdvancedJsonRpc\\' => array($vendorDir . '/felixfbecker/advanced-json-rpc/lib'), 'AdvancedJsonRpc\\' => array($vendorDir . '/felixfbecker/advanced-json-rpc/lib'),
); );
+81 -1
View File
@@ -9,12 +9,15 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
public static $files = array ( public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php', '2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php', 'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php',
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php', 'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
@@ -26,11 +29,16 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'6714be961f4a45ae8b9a99d5d55c5d07' => __DIR__ . '/..' . '/tysonandre/var_representation_polyfill/src/var_representation.php', '6714be961f4a45ae8b9a99d5d55c5d07' => __DIR__ . '/..' . '/tysonandre/var_representation_polyfill/src/var_representation.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'ef65a1626449d89d0811cf9befce46f0' => __DIR__ . '/..' . '/illuminate/events/functions.php',
'5b154887902198b16314243c6e0e3e19' => __DIR__ . '/..' . '/pguardiario/phpuri/phpuri.php', '5b154887902198b16314243c6e0e3e19' => __DIR__ . '/..' . '/pguardiario/phpuri/phpuri.php',
'870dc64919afa8b0f700701bb2c6a783' => __DIR__ . '/../..' . '/f_config/config.php', '870dc64919afa8b0f700701bb2c6a783' => __DIR__ . '/../..' . '/f_config/config.php',
); );
public static $prefixLengthsPsr4 = array ( public static $prefixLengthsPsr4 = array (
'v' =>
array (
'voku\\' => 5,
),
's' => 's' =>
array ( array (
'sammo\\' => 6, 'sammo\\' => 6,
@@ -62,7 +70,9 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
'Symfony\\Polyfill\\Intl\\Idn\\' => 26, 'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31, 'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
'Symfony\\Polyfill\\Ctype\\' => 23, 'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\Translation\\' => 30,
'Symfony\\Contracts\\Service\\' => 26, 'Symfony\\Contracts\\Service\\' => 26,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\String\\' => 25, 'Symfony\\Component\\String\\' => 25,
'Symfony\\Component\\Lock\\' => 23, 'Symfony\\Component\\Lock\\' => 23,
'Symfony\\Component\\Console\\' => 26, 'Symfony\\Component\\Console\\' => 26,
@@ -71,6 +81,7 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
), ),
'P' => 'P' =>
array ( array (
'Psr\\SimpleCache\\' => 16,
'Psr\\Log\\' => 8, 'Psr\\Log\\' => 8,
'Psr\\Http\\Message\\' => 17, 'Psr\\Http\\Message\\' => 17,
'Psr\\Container\\' => 14, 'Psr\\Container\\' => 14,
@@ -88,16 +99,31 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
'League\\Plates\\' => 14, 'League\\Plates\\' => 14,
), ),
'I' =>
array (
'Illuminate\\Support\\' => 19,
'Illuminate\\Pipeline\\' => 20,
'Illuminate\\Events\\' => 18,
'Illuminate\\Database\\' => 20,
'Illuminate\\Contracts\\' => 21,
'Illuminate\\Container\\' => 21,
'Illuminate\\Bus\\' => 15,
),
'G' => 'G' =>
array ( array (
'GuzzleHttp\\Psr7\\' => 16, 'GuzzleHttp\\Psr7\\' => 16,
'GuzzleHttp\\Promise\\' => 19, 'GuzzleHttp\\Promise\\' => 19,
'GuzzleHttp\\' => 11, 'GuzzleHttp\\' => 11,
), ),
'D' =>
array (
'Doctrine\\Inflector\\' => 19,
),
'C' => 'C' =>
array ( array (
'Composer\\XdebugHandler\\' => 23, 'Composer\\XdebugHandler\\' => 23,
'Composer\\Semver\\' => 16, 'Composer\\Semver\\' => 16,
'Carbon\\' => 7,
), ),
'A' => 'A' =>
array ( array (
@@ -106,6 +132,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
); );
public static $prefixDirsPsr4 = array ( public static $prefixDirsPsr4 = array (
'voku\\' =>
array (
0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
),
'sammo\\' => 'sammo\\' =>
array ( array (
0 => __DIR__ . '/../..' . '/src/sammo', 0 => __DIR__ . '/../..' . '/src/sammo',
@@ -164,10 +194,18 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
), ),
'Symfony\\Contracts\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
),
'Symfony\\Contracts\\Service\\' => 'Symfony\\Contracts\\Service\\' =>
array ( array (
0 => __DIR__ . '/..' . '/symfony/service-contracts', 0 => __DIR__ . '/..' . '/symfony/service-contracts',
), ),
'Symfony\\Component\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation',
),
'Symfony\\Component\\String\\' => 'Symfony\\Component\\String\\' =>
array ( array (
0 => __DIR__ . '/..' . '/symfony/string', 0 => __DIR__ . '/..' . '/symfony/string',
@@ -188,6 +226,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
0 => __DIR__ . '/..' . '/sabre/event/lib', 0 => __DIR__ . '/..' . '/sabre/event/lib',
), ),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
),
'Psr\\Log\\' => 'Psr\\Log\\' =>
array ( array (
0 => __DIR__ . '/..' . '/psr/log/Psr/Log', 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
@@ -228,6 +270,36 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
0 => __DIR__ . '/..' . '/league/plates/src', 0 => __DIR__ . '/..' . '/league/plates/src',
), ),
'Illuminate\\Support\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/collections',
1 => __DIR__ . '/..' . '/illuminate/macroable',
2 => __DIR__ . '/..' . '/illuminate/support',
),
'Illuminate\\Pipeline\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/pipeline',
),
'Illuminate\\Events\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/events',
),
'Illuminate\\Database\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/database',
),
'Illuminate\\Contracts\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/contracts',
),
'Illuminate\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/container',
),
'Illuminate\\Bus\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/bus',
),
'GuzzleHttp\\Psr7\\' => 'GuzzleHttp\\Psr7\\' =>
array ( array (
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
@@ -240,6 +312,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
), ),
'Doctrine\\Inflector\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector',
),
'Composer\\XdebugHandler\\' => 'Composer\\XdebugHandler\\' =>
array ( array (
0 => __DIR__ . '/..' . '/composer/xdebug-handler/src', 0 => __DIR__ . '/..' . '/composer/xdebug-handler/src',
@@ -248,6 +324,10 @@ class ComposerStaticInit67b09c83b85c3bc0027caefe5bba171a
array ( array (
0 => __DIR__ . '/..' . '/composer/semver/src', 0 => __DIR__ . '/..' . '/composer/semver/src',
), ),
'Carbon\\' =>
array (
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
),
'AdvancedJsonRpc\\' => 'AdvancedJsonRpc\\' =>
array ( array (
0 => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib', 0 => __DIR__ . '/..' . '/felixfbecker/advanced-json-rpc/lib',

Some files were not shown because too many files have changed in this diff Show More