forked from devsam/core
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
673b7054aa | ||
|
|
1472cbf257 | ||
|
|
d806935c58 | ||
|
|
6b56eb79e1 | ||
|
|
d2aea16744 | ||
|
|
bb800f032e | ||
|
|
64b9f9443e | ||
|
|
fd2d3a0e06 | ||
|
|
08d678bdb8 | ||
|
|
418007e572 | ||
|
|
4a1bccdf75 | ||
|
|
00c0b59e9d | ||
|
|
ac82c8ff0b | ||
|
|
f4bef8a090 | ||
|
|
d8a1055bff | ||
|
|
d672ce4d80 | ||
|
|
43ec361d03 | ||
|
|
c3c99c5f76 | ||
|
|
eb1e1421ab | ||
|
|
e8a1d87919 | ||
|
|
921ba6811d | ||
|
|
906dd241b4 | ||
|
|
3f0cd2ad64 | ||
|
|
41420d1954 | ||
|
|
6e5a72b170 | ||
|
|
4b19e6aec8 | ||
|
|
58572cbc36 | ||
|
|
096d5766bf | ||
|
|
f5c5b56492 | ||
|
|
69c69d63e6 | ||
|
|
3fd8b21867 | ||
|
|
8660e8cd85 | ||
|
|
8458f725f2 | ||
|
|
366678c965 | ||
|
|
336b5668db | ||
|
|
55886269ea | ||
|
|
0b3698595b | ||
|
|
05e43a39db | ||
|
|
5737ad3db2 | ||
|
|
4ac174eb9a | ||
|
|
895eec10b4 | ||
|
|
e0d891e89a | ||
|
|
adf7734b85 | ||
|
|
5362be9c21 | ||
|
|
847ece52f2 | ||
|
|
851c59d22c | ||
|
|
0669534bba | ||
|
|
05db47e62a | ||
|
|
4a0e608d1c | ||
|
|
45fe73af86 | ||
|
|
4d9fcd657f | ||
|
|
a057deb0fe | ||
|
|
4766210a7d |
+36
-30
@@ -15,20 +15,34 @@ return [
|
||||
// Note that the **only** effect of choosing `'5.6'` is to infer
|
||||
// that functions removed in php 7.0 exist.
|
||||
// (See `backward_compatibility_checks` for additional options)
|
||||
"target_php_version" => '7.4',
|
||||
"target_php_version" => '8.0',
|
||||
'backward_compatibility_checks ' => true,
|
||||
'minimum_severity'=>\Phan\Issue::SEVERITY_CRITICAL,
|
||||
'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
|
||||
|
||||
'file_list' => [
|
||||
'f_config/config.php',
|
||||
'hwe/_119_b.php',
|
||||
'hwe/_119.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.php',
|
||||
'hwe/a_genList.php',
|
||||
'hwe/a_hallOfFame.php',
|
||||
'hwe/a_history.php',
|
||||
'hwe/a_kingdomList.php',
|
||||
'hwe/a_npcList.php',
|
||||
'hwe/api.php',
|
||||
'hwe/a_status.php',
|
||||
'hwe/a_traffic.php',
|
||||
'hwe/a_vote.php',
|
||||
@@ -41,13 +55,11 @@ return [
|
||||
'hwe/b_dipcenter.php',
|
||||
'hwe/b_diplomacy.php',
|
||||
'hwe/b_genList.php',
|
||||
'hwe/v_inheritPoint.php',
|
||||
'hwe/b_myBossInfo.php',
|
||||
'hwe/b_myCityInfo.php',
|
||||
'hwe/b_myGenInfo.php',
|
||||
'hwe/b_myKingdomInfo.php',
|
||||
'hwe/b_myPage.php',
|
||||
'hwe/b_npc_control.php',
|
||||
'hwe/b_processing.php',
|
||||
'hwe/b_tournament.php',
|
||||
'hwe/b_troop.php',
|
||||
@@ -55,7 +67,6 @@ return [
|
||||
'hwe/c_dipcenter.php',
|
||||
'hwe/c_tournament.php',
|
||||
'hwe/c_vote.php',
|
||||
'hwe/func.php',
|
||||
'hwe/func_auction.php',
|
||||
'hwe/func_command.php',
|
||||
'hwe/func_converter.php',
|
||||
@@ -64,16 +75,15 @@ return [
|
||||
'hwe/func_legacy.php',
|
||||
'hwe/func_map.php',
|
||||
'hwe/func_message.php',
|
||||
'hwe/func.php',
|
||||
'hwe/func_process.php',
|
||||
'hwe/func_string.php',
|
||||
'hwe/func_template.php',
|
||||
'hwe/func_time_event.php',
|
||||
'hwe/func_tournament.php',
|
||||
'hwe/index.php',
|
||||
'hwe/install.php',
|
||||
'hwe/install_db.php',
|
||||
'hwe/join.php',
|
||||
'hwe/join_post.php',
|
||||
'hwe/install.php',
|
||||
'hwe/j_adjust_icon.php',
|
||||
'hwe/j_autoreset.php',
|
||||
'hwe/j_basic_info.php',
|
||||
@@ -92,8 +102,8 @@ return [
|
||||
'hwe/j_general_log_old.php',
|
||||
'hwe/j_general_set_permission.php',
|
||||
'hwe/j_general_turn.php',
|
||||
'hwe/j_getChiefTurn.php',
|
||||
'hwe/j_get_basic_general_list.php',
|
||||
'hwe/j_getChiefTurn.php',
|
||||
'hwe/j_get_city_list.php',
|
||||
'hwe/j_get_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_pool.php',
|
||||
'hwe/j_image_upload.php',
|
||||
'hwe/j_install.php',
|
||||
'hwe/j_install_db.php',
|
||||
'hwe/j_install.php',
|
||||
'hwe/j_load_scenarios.php',
|
||||
'hwe/j_map.php',
|
||||
'hwe/j_map_history.php',
|
||||
'hwe/j_map.php',
|
||||
'hwe/j_map_recent.php',
|
||||
'hwe/j_msg_contact_list.php',
|
||||
'hwe/j_msg_decide_opt.php',
|
||||
'hwe/j_msg_delete.php',
|
||||
@@ -123,26 +134,20 @@ return [
|
||||
'hwe/j_set_npc_control.php',
|
||||
'hwe/j_simulate_battle.php',
|
||||
'hwe/j_troop.php',
|
||||
'hwe/j_update_picked_general.php',
|
||||
'hwe/j_vacation.php',
|
||||
'hwe/lib.php',
|
||||
'hwe/process_war.php',
|
||||
'hwe/proc.php',
|
||||
'hwe/readme.php',
|
||||
'hwe/recent_map.php',
|
||||
'hwe/select_general_from_pool.php',
|
||||
'hwe/select_npc.php',
|
||||
'hwe/t_board.php',
|
||||
'hwe/t_diplomacy.php',
|
||||
'hwe/_119.php',
|
||||
'hwe/_119_b.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/v_board.php',
|
||||
'hwe/v_inheritPoint.php',
|
||||
'hwe/v_join.php',
|
||||
'hwe/v_NPCControl.php',
|
||||
],
|
||||
|
||||
// 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
|
||||
// your application should be included in this list.
|
||||
'directory_list' => [
|
||||
'hwe/d_setting',
|
||||
'hwe/sammo',
|
||||
'd_setting',
|
||||
'hwe/d_setting',
|
||||
'hwe/sammo',
|
||||
'd_setting',
|
||||
'src/sammo',
|
||||
'src/kakao',
|
||||
'vendor'
|
||||
@@ -179,6 +184,7 @@ return [
|
||||
|
||||
'suppress_issue_types' => [
|
||||
'PhanUnreferencedUseNormal',
|
||||
'PhanTypeArraySuspiciousNullable',
|
||||
],
|
||||
|
||||
// A list of plugin files to execute.
|
||||
@@ -195,4 +201,4 @@ return [
|
||||
'PregRegexCheckerPlugin',
|
||||
'PrintfCheckerPlugin',
|
||||
],
|
||||
];
|
||||
];
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<title>닫혀 있습니다.</title>
|
||||
<script>
|
||||
setTimeout(function(){
|
||||
window.location = window.location+'/../';
|
||||
window.location.href = '../';
|
||||
}, 5000);
|
||||
</script>
|
||||
<style>
|
||||
@@ -13,7 +13,7 @@
|
||||
background-color:black;
|
||||
color:yellow;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
|
||||
|
||||
if (!class_exists('\\sammo\\RootDB')) {
|
||||
Json::dieWithReason('No DB');
|
||||
}
|
||||
|
||||
APIHelper::launch(dirname(__FILE__));
|
||||
+3
-1
@@ -28,7 +28,9 @@
|
||||
"catfan/medoo": "^1.5",
|
||||
"phan/phan": "*",
|
||||
"erusev/parsedown-extra": "^0.8.1",
|
||||
"nette/caching": "^3.0"
|
||||
"nette/caching": "^3.0",
|
||||
"illuminate/database": "^8.61",
|
||||
"illuminate/events": "^8.61"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+987
-9
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2aeb036fc53a6fdc343bd2707d4697ee",
|
||||
"content-hash": "317938cff7b30806f4e385a70f4943fc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brandonwamboldt/utilphp",
|
||||
@@ -265,6 +265,101 @@
|
||||
],
|
||||
"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",
|
||||
"version": "1.7.4",
|
||||
@@ -707,6 +802,497 @@
|
||||
},
|
||||
"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",
|
||||
"version": "v3.4.0",
|
||||
@@ -902,6 +1488,100 @@
|
||||
],
|
||||
"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",
|
||||
"version": "v4.0.0",
|
||||
@@ -1206,16 +1886,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phan/phan",
|
||||
"version": "5.0.0",
|
||||
"version": "5.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phan/phan.git",
|
||||
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90"
|
||||
"reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phan/phan/zipball/f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
|
||||
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
|
||||
"url": "https://api.github.com/repos/phan/phan/zipball/d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
|
||||
"reference": "d724bbb8fc3ba89179868bb5220ecdf6a9c1636b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1232,7 +1912,7 @@
|
||||
"symfony/console": "^3.2|^4.0|^5.0",
|
||||
"symfony/polyfill-mbstring": "^1.11.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": {
|
||||
"phpunit/phpunit": "^8.5.0"
|
||||
@@ -1279,9 +1959,9 @@
|
||||
],
|
||||
"support": {
|
||||
"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",
|
||||
@@ -1684,6 +2364,57 @@
|
||||
},
|
||||
"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",
|
||||
"version": "3.0.3",
|
||||
@@ -2970,6 +3701,179 @@
|
||||
],
|
||||
"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",
|
||||
"version": "0.0.2",
|
||||
@@ -3080,6 +3984,80 @@
|
||||
],
|
||||
"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",
|
||||
"version": "1.10.0",
|
||||
@@ -3203,7 +4181,7 @@
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.3"
|
||||
"php": "7.4"
|
||||
},
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
|
||||
+41
-16
@@ -15,35 +15,35 @@ ini_set("session.gc_maxlifetime", '604800'); // seconds
|
||||
function getFriendlyErrorType($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case E_ERROR: // 1 //
|
||||
case E_ERROR: // 1 //
|
||||
return 'E_ERROR';
|
||||
case E_WARNING: // 2 //
|
||||
case E_WARNING: // 2 //
|
||||
return 'E_WARNING';
|
||||
case E_PARSE: // 4 //
|
||||
case E_PARSE: // 4 //
|
||||
return 'E_PARSE';
|
||||
case E_NOTICE: // 8 //
|
||||
case E_NOTICE: // 8 //
|
||||
return 'E_NOTICE';
|
||||
case E_CORE_ERROR: // 16 //
|
||||
case E_CORE_ERROR: // 16 //
|
||||
return 'E_CORE_ERROR';
|
||||
case E_CORE_WARNING: // 32 //
|
||||
case E_CORE_WARNING: // 32 //
|
||||
return 'E_CORE_WARNING';
|
||||
case E_COMPILE_ERROR: // 64 //
|
||||
case E_COMPILE_ERROR: // 64 //
|
||||
return 'E_COMPILE_ERROR';
|
||||
case E_COMPILE_WARNING: // 128 //
|
||||
case E_COMPILE_WARNING: // 128 //
|
||||
return 'E_COMPILE_WARNING';
|
||||
case E_USER_ERROR: // 256 //
|
||||
case E_USER_ERROR: // 256 //
|
||||
return 'E_USER_ERROR';
|
||||
case E_USER_WARNING: // 512 //
|
||||
case E_USER_WARNING: // 512 //
|
||||
return 'E_USER_WARNING';
|
||||
case E_USER_NOTICE: // 1024 //
|
||||
case E_USER_NOTICE: // 1024 //
|
||||
return 'E_USER_NOTICE';
|
||||
case E_STRICT: // 2048 //
|
||||
case E_STRICT: // 2048 //
|
||||
return 'E_STRICT';
|
||||
case E_RECOVERABLE_ERROR: // 4096 //
|
||||
case E_RECOVERABLE_ERROR: // 4096 //
|
||||
return 'E_RECOVERABLE_ERROR';
|
||||
case E_DEPRECATED: // 8192 //
|
||||
case E_DEPRECATED: // 8192 //
|
||||
return 'E_DEPRECATED';
|
||||
case E_USER_DEPRECATED: // 16384 //
|
||||
case E_USER_DEPRECATED: // 16384 //
|
||||
return 'E_USER_DEPRECATED';
|
||||
}
|
||||
return "{$type}";
|
||||
@@ -134,7 +134,7 @@ function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, in
|
||||
getExceptionTraceAsString($e)
|
||||
);
|
||||
}
|
||||
set_error_handler("\sammo\logErrorByCustomHandler");
|
||||
set_error_handler("\\sammo\\logErrorByCustomHandler");
|
||||
|
||||
|
||||
function logExceptionByCustomHandler(\Throwable $e)
|
||||
@@ -151,3 +151,28 @@ function logExceptionByCustomHandler(\Throwable $e)
|
||||
throw $e;
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -58,7 +58,7 @@ CREATE TABLE `member_log` (
|
||||
INDEX `action` (`member_no`, `action_type`, `date`),
|
||||
INDEX `member` (`member_no`, `date`)
|
||||
)
|
||||
ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
ENGINE=Aria DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
###################
|
||||
# KV storage
|
||||
@@ -72,4 +72,19 @@ CREATE TABLE if not exists `storage` (
|
||||
UNIQUE INDEX `key` (`namespace`, `key`)
|
||||
)
|
||||
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
|
||||
;
|
||||
@@ -2,9 +2,15 @@
|
||||
|
||||
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
|
||||
{
|
||||
private static $uDB = null;
|
||||
private static ?Capsule $uIlluminate = null;
|
||||
|
||||
private static $host = '_tK_host_';
|
||||
private static $user = '_tK_user_';
|
||||
@@ -12,6 +18,8 @@ class RootDB
|
||||
private static $dbName = '_tK_dbName_';
|
||||
private static $port = _tK_port_;
|
||||
private static $encoding = 'utf8mb4';
|
||||
private static $collation = 'utf8mb4_general_ci';
|
||||
|
||||
|
||||
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 객체 생성
|
||||
*
|
||||
|
||||
@@ -342,6 +342,7 @@ switch ($btn) {
|
||||
}
|
||||
break;
|
||||
case "랜덤턴":
|
||||
$turnterm = $gameStor->turnterm;
|
||||
foreach ($genlist as $generalID) {
|
||||
$turntime = getRandTurn($turnterm);
|
||||
$db->update('general', [
|
||||
|
||||
@@ -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'];
|
||||
$searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ var storedData = <?=Json::encode([
|
||||
<?=WebUtil::printJS('dist_js/vendors.js')?>
|
||||
<?=WebUtil::printJS('dist_js/dipcenter.js')?>
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../e_lib/summernote/summernote-bs4.css')?>
|
||||
<?=WebUtil::printCSS('dist_css/vendors.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ $admin = $gameStor->getValues(['develcost', 'cost', 'vote_title', 'vote', 'votec
|
||||
|
||||
$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) {
|
||||
$develcost = $admin['develcost'] * 5;
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<?php
|
||||
|
||||
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 ?Capsule $uIlluminate = null;
|
||||
|
||||
private static $host = '_tK_host_';
|
||||
private static $user = '_tK_user_';
|
||||
@@ -10,11 +18,36 @@ class DB{
|
||||
private static $dbName = '_tK_dbName_';
|
||||
private static $port = _tK_port_;
|
||||
private static $encoding = 'utf8mb4';
|
||||
private static $collation = 'utf8mb4_general_ci';
|
||||
|
||||
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
|
||||
* @suppress PhanTypeMismatchProperty
|
||||
*/
|
||||
public static function db(){
|
||||
if(self::$uDB === null){
|
||||
self::$uDB = new \MeekroDB(self::$host,self::$user,self::$password,self::$dbName,self::$port,self::$encoding);
|
||||
public static function db()
|
||||
{
|
||||
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->error_handler= function(){};
|
||||
self::$uDB->error_handler = function () {
|
||||
};
|
||||
self::$uDB->throw_exception_on_error = true;
|
||||
self::$uDB->throw_exception_on_nonsql_error = true;
|
||||
}
|
||||
@@ -39,4 +74,4 @@ class DB{
|
||||
{
|
||||
return self::$prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<div class="buttonPlate bg1">
|
||||
<div>
|
||||
<a href="a_status.php" target="_blank"><button class="toolbarButton">세력도</button></a>
|
||||
<a href="a_kingdomList.php" target="_blank"><button class="toolbarButton">세력일람</button></a>
|
||||
<a href="a_genList.php" target="_blank"><button class="toolbarButton">장수일람</button></a>
|
||||
<a href="a_bestGeneral.php" target="_blank"><button class="toolbarButton">명장일람</button></a>
|
||||
<a href="a_history.php" target="_blank"><button class="toolbarButton">연감</button></a>
|
||||
<a href="a_hallOfFame.php" target="_blank"><button class="toolbarButton">명예의전당</button></a>
|
||||
<a href="a_emperior.php" target="_blank"><button class="toolbarButton">왕조일람</button></a>
|
||||
<a href="a_traffic.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" class="open-window"><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" class="open-window"><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" class="open-window"><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" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/bbs/board" target="_blank"><button class="toolbarButton2">삼모게시판</button></a>
|
||||
<a href="/bbs/tip" target="_blank"><button class="toolbarButton">팁/강좌</button></a>
|
||||
<a href="/bbs/news" target="_blank"><button class="toolbarButton">삼국 일보</button></a>
|
||||
<a href="/bbs/history2" target="_blank"><button class="toolbarButton">개인 열전</button></a>
|
||||
<a href="/bbs/history3" target="_blank"><button class="toolbarButton">국가 열전</button></a>
|
||||
<a href="/bbs/patch" target="_blank"><button class="toolbarButton">패치 내역</button></a>
|
||||
<a href="../i_other/help.php" target="_blank"><button class="toolbarButton">튜토리얼</button></a>
|
||||
<a href="<?=$site?>" target="_blank"><button class="toolbarButton"><?=$call?></button></a>
|
||||
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
|
||||
<a href="/bbs/tip" target="_blank"><button type="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 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="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
|
||||
<a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+44
-13
@@ -1256,9 +1256,12 @@ function addAge()
|
||||
//나이와 호봉 증가
|
||||
$db->update('general', [
|
||||
'age' => $db->sqleval('age+1'),
|
||||
'belong' => $db->sqleval('belong+1')
|
||||
], true);
|
||||
|
||||
$db->update('general', [
|
||||
'belong' => $db->sqleval('belong+1')
|
||||
], 'nation != 0');
|
||||
|
||||
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
|
||||
|
||||
if ($year >= $startYear + 3) {
|
||||
@@ -1286,12 +1289,11 @@ function addAge()
|
||||
$generalAux = Json::decode($general['aux']);
|
||||
|
||||
$updateVars = [];
|
||||
if(key_exists('inheritSpecificSpecialWar', $generalAux)){
|
||||
if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
|
||||
$special2 = $generalAux['inheritSpecificSpecialWar'];
|
||||
unset($generalAux['inheritSpecificSpecialWar']);
|
||||
$updateVars['aux'] = Json::encode($generalAux);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$special2 = SpecialityHelper::pickSpecialWar(
|
||||
$general,
|
||||
($generalAux['prev_types_special2']) ?? []
|
||||
@@ -1592,9 +1594,19 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ($general->getAuxVar('inheritRandomUnique')) {
|
||||
$general->setAuxVar('inheritRandomUnique', null);
|
||||
}
|
||||
|
||||
[$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique);
|
||||
|
||||
$nationName = $general->getStaticNation()['name'];
|
||||
@@ -1628,22 +1640,29 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
|
||||
$itemTrials = $general->getAuxVar('inheritUniqueTrial');
|
||||
LogText("선택유니크 롤백:{$ownerID}", [$itemKey, $itemTrials]);
|
||||
unset($itemTrials[$itemKey]);
|
||||
if(count($itemTrials) == 0){
|
||||
$itemTrials = null;
|
||||
}
|
||||
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
|
||||
|
||||
|
||||
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
|
||||
$ownTrial = $trialStor->getValue("u{$ownerID}");
|
||||
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$itemName = $itemObj->getName();
|
||||
|
||||
if ($ownTrial) {
|
||||
//두 값이 general, KVStorage 둘다 있고, 이중에선 KVStorage 값을 기준으로 하자 따르자
|
||||
[,, $amount] = $ownTrial;
|
||||
$trialStor->deleteValue("u{$ownerID}");
|
||||
$general->increaseInheritancePoint('previous', $amount);
|
||||
LogText("선택유니크 롤백포인트:{$ownerID}", $amount);
|
||||
|
||||
$userLogger = new UserLogger($ownerID);
|
||||
$userLogger->push("{$itemName} 입찰에 사용한 {$amount} 포인트 반환", "inheritPoint");
|
||||
}
|
||||
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$itemName = $itemObj->getName();
|
||||
//메시지
|
||||
|
||||
$staticNation = $general->getStaticNation();
|
||||
@@ -1662,11 +1681,16 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
|
||||
[]
|
||||
);
|
||||
|
||||
$msg->send(true);
|
||||
$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');
|
||||
if (!$ownerID) {
|
||||
@@ -1769,6 +1793,9 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
|
||||
if ($ownTarget === null) {
|
||||
return false;
|
||||
}
|
||||
if ($justRollback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogText("선택유니크획득{$ownerID}", $ownTarget);
|
||||
|
||||
@@ -1814,7 +1841,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
|
||||
}
|
||||
|
||||
$inheritUnique = $general->getAuxVar('inheritUniqueTrial');
|
||||
if ($inheritUnique && count($inheritUnique)) {
|
||||
if ($acquireType != '설문조사' && $inheritUnique && count($inheritUnique)) {
|
||||
LogText("유니크 준비?? {$general->getID()}", $inheritUnique);
|
||||
$trialResult = tryInheritUniqueItem($general, $acquireType);
|
||||
if ($trialResult) {
|
||||
@@ -1833,6 +1860,12 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
|
||||
|
||||
if ($trialCnt <= 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1859,13 +1892,11 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
|
||||
$result = false;
|
||||
|
||||
$prob /= sqrt(2);
|
||||
$moreProb = pow(2, 1/4);
|
||||
$moreProb = pow(2, 1 / 4);
|
||||
|
||||
if($general->getAuxVar('inheritRandomUnique')){
|
||||
if ($general->getAuxVar('inheritRandomUnique')) {
|
||||
//포인트로 랜덤 유니크 획득
|
||||
$prob = 1;
|
||||
LogText("{$general->getName()}, {$general->getID()} 유산 포인트 유니크", $prob);
|
||||
$general->setAuxVar('inheritRandomUnique', null);
|
||||
}
|
||||
|
||||
foreach (Util::range($trialCnt) as $_idx) {
|
||||
|
||||
@@ -357,31 +357,6 @@ function buildNationCommandClass(?string $type, General $generalObj, array $env,
|
||||
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){
|
||||
static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\';
|
||||
$classPath = ($basePath.$type);
|
||||
|
||||
+15
-3
@@ -624,12 +624,12 @@ function updateNationState()
|
||||
$targetKillTurn
|
||||
);
|
||||
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
|
||||
$chiefObj = null;
|
||||
$chiefID = null;
|
||||
|
||||
$uniqueLotteryWeightList = [];
|
||||
foreach ($nationGenList as $nationGen) {
|
||||
if ($nationGen->getVar('officer_level') == 12) {
|
||||
$chiefObj = $nationGen;
|
||||
$chiefID = $nationGen->getID();
|
||||
}
|
||||
$trialCnt = count(GameConst::$allItems);
|
||||
|
||||
@@ -670,8 +670,10 @@ function updateNationState()
|
||||
$winnerObj->applyDB($db);
|
||||
}
|
||||
|
||||
if($chiefObj){
|
||||
if($chiefID){
|
||||
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
|
||||
$chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
|
||||
$chiefObj->applyDB($db);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1166,13 +1168,23 @@ function resetInheritanceUser(int $userID, bool $isRebirth=false):float{
|
||||
//이미 리셋되었으므로 리셋 안함
|
||||
return $allPoints['previous'][0];
|
||||
}
|
||||
|
||||
$userLogger = new UserLogger($userID);
|
||||
|
||||
$previousPoint = ($allPoints['previous']??[0,0])[0];
|
||||
|
||||
foreach($allPoints as $key=>[$value,]){
|
||||
if($isRebirth && key_exists($key, $rebirthDegraded)){
|
||||
$value *= $rebirthDegraded[$key];
|
||||
}
|
||||
$keyText = General::INHERITANCE_KEY[$key][2];
|
||||
$userLogger->push("{$keyText} 포인트 {$value} 증가", "inheritPoint");
|
||||
$totalPoint += $value;
|
||||
}
|
||||
$totalPoint = Util::toInt($totalPoint);
|
||||
$userLogger->push("포인트 {$previousPoint} => {$totalPoint}", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$inheritStor->resetValues();
|
||||
$inheritStor->setValue('previous', [$totalPoint, null]);
|
||||
return $totalPoint;
|
||||
|
||||
@@ -1132,7 +1132,7 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type) {
|
||||
$gen1resKey = 'd';
|
||||
$gen2resKey = 'd';
|
||||
break;
|
||||
default: new MustNotBeReachedException();
|
||||
default: throw new MustNotBeReachedException();
|
||||
}
|
||||
|
||||
$db->update('rank_data', [
|
||||
|
||||
@@ -47,7 +47,7 @@ else{
|
||||
'name', 'leadership', 'strength', 'intel', 'gold','rice',
|
||||
'troop','officer_level','npc','picture','imgsvr',
|
||||
'permission','penalty','belong', 'crewtype',
|
||||
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
|
||||
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'aux',
|
||||
], 1);
|
||||
|
||||
if($general instanceof DummyGeneral){
|
||||
@@ -104,7 +104,7 @@ function do수뇌임명(General $general, int $targetOfficerLevel):?string{
|
||||
if($general->getVar('strength') < GameConst::$chiefStatMin){
|
||||
return '무력이 부족합니다.';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
if($general->getVar('intel') < GameConst::$chiefStatMin){
|
||||
@@ -175,7 +175,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
|
||||
$generalName = $general->getVar('name');
|
||||
$nationID = $general->getNationID();
|
||||
|
||||
|
||||
|
||||
|
||||
//추방할사람이 외교권자이면 불가
|
||||
$permission = checkSecretPermission($general->getRaw());
|
||||
@@ -252,7 +252,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
|
||||
]);
|
||||
|
||||
$src = new MessageTarget(
|
||||
$generalID,
|
||||
$generalID,
|
||||
$generalName,
|
||||
$nationID,
|
||||
$nation['name'],
|
||||
@@ -260,7 +260,7 @@ function do추방(General $general, int $myOfficerLevel):?string{
|
||||
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
|
||||
);
|
||||
$msg = new Message(
|
||||
Message::MSGTYPE_PUBLIC,
|
||||
Message::MSGTYPE_PUBLIC,
|
||||
$src,
|
||||
$src,
|
||||
$str,
|
||||
|
||||
@@ -39,7 +39,7 @@ $db = DB::db();
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
if($defence_train != $me->getVar('defence_train')){
|
||||
if($defence_train !== $me->getVar('defence_train')){
|
||||
if($defence_train == 999){
|
||||
$me->increaseVar('myset', -1);
|
||||
$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));
|
||||
|
||||
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
|
||||
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
||||
}
|
||||
|
||||
if($me->getVar('tnmt') != $tnmt){
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
}
|
||||
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
|
||||
$me->setVar('tnmt', $tnmt);
|
||||
|
||||
if($me->getNPCType() == 1 && $detachNPC){
|
||||
$turnterm = $gameStor->turnterm;
|
||||
|
||||
+69
-57
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
@@ -21,18 +22,18 @@ $availableTypes = [
|
||||
'nationPolicy',
|
||||
];
|
||||
|
||||
if(!in_array($type, $availableTypes)){
|
||||
if (!in_array($type, $availableTypes)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 타입이 아닙니다.',
|
||||
'result' => false,
|
||||
'reason' => '올바른 타입이 아닙니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
$data = Json::decode($data);
|
||||
if(!$data || !is_array($data)){
|
||||
if (!$data || !is_array($data)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바른 입력이 아닙니다.',
|
||||
'result' => false,
|
||||
'reason' => '올바른 입력이 아닙니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -44,94 +45,95 @@ $me = $db->queryFirstRow('SELECT no, name, npc, nation, city, officer_level, con
|
||||
$nationID = $me['nation'];
|
||||
if (!$nationID) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'국가에 소속되어있지 않습니다.',
|
||||
'result' => false,
|
||||
'reason' => '국가에 소속되어있지 않습니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
$permission = checkSecretPermission($me);
|
||||
if ($permission < 3) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.'
|
||||
'result' => false,
|
||||
'reason' => '권한이 부족합니다. 군주, 외교권자, 조언자가 아닙니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
function applyNationPolicy($policy, $nationID, $generalName):?string{
|
||||
function applyNationPolicy($policy, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
|
||||
$defaultPolicy = AutorunNationPolicy::$defaultPolicy;
|
||||
$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';
|
||||
}
|
||||
$cityList = CityConst::all();
|
||||
$nationPolicyRoot = $nationStor->npc_nation_policy;
|
||||
$nationPolicy = $nationPolicyRoot['values']??[];
|
||||
foreach($policy as $key=>$val){
|
||||
$nationPolicy = $nationPolicyRoot['values'] ?? [];
|
||||
foreach ($policy as $key => $val) {
|
||||
|
||||
if($key === 'CombatForce'){
|
||||
if(!is_array($val)){
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
if ($key === 'CombatForce') {
|
||||
if (!is_array($val)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
foreach($val as $troopID=>$troopTarget){
|
||||
if(!key_exists($troopID, $troopCache)){
|
||||
foreach ($val as $troopID => $troopTarget) {
|
||||
if (!key_exists($troopID, $troopCache)) {
|
||||
return "{$troopID}는 국가의 부대가 아닙니다.";
|
||||
}
|
||||
if($troopCache[$troopID] != 'Neutral'){
|
||||
if ($troopCache[$troopID] != 'Neutral') {
|
||||
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
|
||||
}
|
||||
if(!is_array($troopTarget) || count($troopTarget)!=2){
|
||||
if (!is_array($troopTarget) || count($troopTarget) != 2) {
|
||||
return "{$troopID}의 입력양식이 올바르지 않습니다.";
|
||||
}
|
||||
[$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}가 올바른 도시 번호가 아닙니다.";
|
||||
}
|
||||
$troopCache[$troopID]=$key;
|
||||
$troopCache[$troopID] = $key;
|
||||
}
|
||||
$nationPolicy[$key]=$val;
|
||||
$nationPolicy[$key] = $val;
|
||||
continue;
|
||||
}
|
||||
if(in_array($key, ['SupportForce', 'DevelopForce'])){
|
||||
if(!is_array($val)){
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
if (in_array($key, ['SupportForce', 'DevelopForce'])) {
|
||||
if (!is_array($val)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
foreach($val as $troopID){
|
||||
if(!key_exists($troopID, $troopCache)){
|
||||
foreach ($val as $troopID) {
|
||||
if (!key_exists($troopID, $troopCache)) {
|
||||
return "{$troopID}는 국가의 부대가 아닙니다.";
|
||||
}
|
||||
if($troopCache[$troopID] != 'Neutral'){
|
||||
if ($troopCache[$troopID] != 'Neutral') {
|
||||
return "부대({$troopID}는 하나의 역할만 지정할 수 있습니다.";
|
||||
}
|
||||
$troopCache[$troopID]=$key;
|
||||
$troopCache[$troopID] = $key;
|
||||
}
|
||||
|
||||
$nationPolicy[$key]=array_values($val);
|
||||
$nationPolicy[$key] = array_values($val);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if(!key_exists($key, $defaultPolicy)){
|
||||
if (!key_exists($key, $defaultPolicy)) {
|
||||
return "{$key}는 올바른 정책값이 아닙니다.";
|
||||
}
|
||||
$defaultValue = $defaultPolicy[$key];
|
||||
if(is_numeric($defaultValue) != is_numeric($val)){
|
||||
if (is_numeric($defaultValue) != is_numeric($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_integer($defaultValue) != is_integer($val)){
|
||||
if (is_integer($defaultValue) != is_integer($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_array($defaultValue) != is_array($val)){
|
||||
if (is_array($defaultValue) != is_array($val)) {
|
||||
return "{$key}는 올바른 값이 아닙니다.";
|
||||
}
|
||||
if(is_integer($val) && $val < 0){
|
||||
if (is_integer($val) && $val < 0) {
|
||||
$val = 0;
|
||||
}
|
||||
$nationPolicy[$key] = $val;
|
||||
}
|
||||
|
||||
|
||||
$nationPolicyRoot['values'] = $nationPolicy;
|
||||
$nationPolicyRoot['valueSetter'] = $generalName;
|
||||
$nationPolicyRoot['valueSetTime'] = TimeUtil::now();
|
||||
@@ -139,14 +141,15 @@ function applyNationPolicy($policy, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyNationPriority($priority, $nationID, $generalName):?string{
|
||||
function applyNationPriority($priority, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$nationPolicyRoot = $nationStor->npc_nation_policy;
|
||||
|
||||
$defaultPriority = AutorunNationPolicy::$defaultPriority;
|
||||
foreach($priority as $item){
|
||||
if(!in_array($item, $defaultPriority)){
|
||||
foreach ($priority as $item) {
|
||||
if (!in_array($item, $defaultPriority)) {
|
||||
return "{$item}은 올바른 명령이 아닙니다.";
|
||||
}
|
||||
}
|
||||
@@ -157,17 +160,29 @@ function applyNationPriority($priority, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyGeneralPriority($priority, $nationID, $generalName):?string{
|
||||
function applyGeneralPriority($priority, $nationID, $generalName): ?string
|
||||
{
|
||||
$db = DB::db();
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$generalPolicyRoot = $nationStor->npc_general_policy;
|
||||
|
||||
$defaultPriority = AutorunGeneralPolicy::$default_priority;
|
||||
foreach($priority as $item){
|
||||
if(!in_array($item, $defaultPriority)){
|
||||
$mustHaveActions = ['출병' => 1];
|
||||
foreach ($priority as $item) {
|
||||
if (key_exists($item, $mustHaveActions)) {
|
||||
$mustHaveActions[$item] = 0;
|
||||
}
|
||||
if (!in_array($item, $defaultPriority)) {
|
||||
return "{$item}은 올바른 명령이 아닙니다.";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($mustHaveActions as $actionKey => $unset) {
|
||||
if ($unset) {
|
||||
return "{$actionKey}은 항상 사용해야 합니다.";
|
||||
}
|
||||
}
|
||||
|
||||
$generalPolicyRoot['priority'] = $priority;
|
||||
$generalPolicyRoot['prioritySetter'] = $generalName;
|
||||
$generalPolicyRoot['prioritySetTime'] = TimeUtil::now();
|
||||
@@ -175,26 +190,23 @@ function applyGeneralPriority($priority, $nationID, $generalName):?string{
|
||||
return null;
|
||||
}
|
||||
|
||||
if($type == 'nationPolicy'){
|
||||
if ($type == 'nationPolicy') {
|
||||
$result = applyNationPolicy($data, $nationID, $me['name']);
|
||||
}
|
||||
else if($type == 'generalPriority'){
|
||||
} else if ($type == 'generalPriority') {
|
||||
$result = applyGeneralPriority($data, $nationID, $me['name']);
|
||||
}
|
||||
else if($type == 'nationPriority'){
|
||||
} else if ($type == 'nationPriority') {
|
||||
$result = applyNationPriority($data, $nationID, $me['name']);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
throw new MustNotBeReachedException();
|
||||
}
|
||||
|
||||
if($result!==null){
|
||||
if ($result !== null) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$result,
|
||||
'result' => false,
|
||||
'reason' => $result,
|
||||
]);
|
||||
}
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
]);
|
||||
'result' => true,
|
||||
'reason' => 'success',
|
||||
]);
|
||||
|
||||
@@ -16,6 +16,7 @@ use sammo\Session;
|
||||
use sammo\SpecialityHelper;
|
||||
use sammo\StringUtil;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Util;
|
||||
use sammo\Validator;
|
||||
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);
|
||||
$inheritRequiredPoint = 0;
|
||||
|
||||
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
|
||||
|
||||
if ($inheritCity !== null) {
|
||||
$inheritRequiredPoint += GameConst::$inheritBornCityPoint;
|
||||
}
|
||||
@@ -183,6 +186,8 @@ class Join extends \sammo\BaseAPI
|
||||
}
|
||||
|
||||
if ($inheritSpecial) {
|
||||
$speicalText = getGeneralSpecialWarName($inheritSpecial);
|
||||
$userLogger->push("{$speicalText} 전투 특기를 가진 천재 생성", "inheritPoint");
|
||||
$genius = true;
|
||||
} else {
|
||||
// 현재 1%
|
||||
@@ -196,6 +201,8 @@ class Join extends \sammo\BaseAPI
|
||||
}
|
||||
|
||||
if ($inheritCity !== null) {
|
||||
$cityname = CityConst::byID($inheritCity)->name;
|
||||
$userLogger->push("{$cityname}에 장수 생성", "inheritPoint");
|
||||
$city = $inheritCity;
|
||||
} else {
|
||||
// 공백지에서만 태어나게
|
||||
@@ -207,6 +214,7 @@ class Join extends \sammo\BaseAPI
|
||||
|
||||
if ($inheritBonusStat) {
|
||||
[$pleadership, $pstrength, $pintel] = $inheritBonusStat;
|
||||
$userLogger->push("{$pleadership}, {$pstrength}, {$pintel} 보너스 능력치로 생성", "inheritPoint");
|
||||
} else {
|
||||
$pleadership = 0;
|
||||
$pstrength = 0;
|
||||
@@ -276,8 +284,10 @@ class Join extends \sammo\BaseAPI
|
||||
}
|
||||
|
||||
if ($inheritTurntime !== null) {
|
||||
//FIXME: 오동작함
|
||||
$inheritTurntime = $inheritTurntime % ($admin['turnterm'] * 60);
|
||||
|
||||
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime%60), "inheritPoint");
|
||||
|
||||
$inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
|
||||
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm']));
|
||||
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
|
||||
@@ -372,9 +382,12 @@ class Join extends \sammo\BaseAPI
|
||||
]);
|
||||
$cityname = CityConst::byID($city)->name;
|
||||
|
||||
|
||||
if ($inheritRequiredPoint > 0) {
|
||||
$userLogger->push("장수 생성으로 포인트 {$inheritRequiredPoint} 소모", "inheritPoint");
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
|
||||
$inheritStor->setValue('previous', [$inheritTotalPoint - $inheritRequiredPoint, null]);
|
||||
$userLogger->flush();
|
||||
}
|
||||
|
||||
$me = [
|
||||
|
||||
@@ -10,6 +10,7 @@ use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\TriggerInheritBuff;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Validator;
|
||||
|
||||
class BuyHiddenBuff extends \sammo\BaseAPI
|
||||
@@ -50,6 +51,7 @@ class BuyHiddenBuff extends \sammo\BaseAPI
|
||||
if ($userID != $general->getVar('owner')) {
|
||||
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
|
||||
}
|
||||
$userLogger = new UserLogger($userID);
|
||||
|
||||
$inheritBuffList = $general->getAuxVar('inheritBuff') ?? [];
|
||||
$prevLevel = $inheritBuffList[$type] ?? 0;
|
||||
@@ -70,6 +72,11 @@ class BuyHiddenBuff extends \sammo\BaseAPI
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$buffTypeText = TriggerInheritBuff::BUFF_KEY_TEXT[$type];
|
||||
$moreText = $prevLevel > 0 ? "추가":"";
|
||||
$userLogger->push("{$reqAmount} 포인트로 {$buffTypeText} {$level} 단계 {$moreText}구입", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$inheritBuffList[$type] = $level;
|
||||
$general->setAuxVar('inheritBuff', $inheritBuffList);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
|
||||
|
||||
@@ -9,6 +9,7 @@ use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\UserLogger;
|
||||
|
||||
class BuyRandomUnique extends \sammo\BaseAPI
|
||||
{
|
||||
@@ -40,12 +41,17 @@ class BuyRandomUnique extends \sammo\BaseAPI
|
||||
$db = DB::db();
|
||||
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
|
||||
$previousPoint = ($inheritStor->getValue('previous')??[0, 0])[0];
|
||||
if($previousPoint < GameConst::$inheritItemRandomPoint){
|
||||
$reqAmount = GameConst::$inheritItemRandomPoint;
|
||||
if($previousPoint < $reqAmount){
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$userLogger = new UserLogger($userID);
|
||||
$userLogger->push("{$reqAmount} 포인트로 랜덤 유니크 구입", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$general->setAuxVar('inheritRandomUnique', TimeUtil::now());
|
||||
$inheritStor->setValue('previous', [$previousPoint - GameConst::$inheritItemRandomPoint, null]);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
|
||||
$general->applyDB($db);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,12 +8,16 @@ use sammo\DB;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Validator;
|
||||
|
||||
use function sammo\buildItemClass;
|
||||
|
||||
class BuySpecificUnique extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$availableItems = [];
|
||||
foreach (GameConst::$allItems as $items) {
|
||||
foreach ($items as $itemKey => $amount) {
|
||||
if ($amount == 0) {
|
||||
@@ -70,6 +74,11 @@ class BuySpecificUnique extends \sammo\BaseAPI
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$userLogger = new UserLogger($userID);
|
||||
$userLogger->push("{$amount} 포인트로 유니크 {$itemObj->getName()} 구입 시도", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$itemTrials[$itemKey] = $amount;
|
||||
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $amount, null]);
|
||||
|
||||
@@ -8,6 +8,7 @@ use sammo\DB;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Validator;
|
||||
|
||||
class ResetSpecialWar extends \sammo\BaseAPI
|
||||
@@ -55,6 +56,10 @@ class ResetSpecialWar extends \sammo\BaseAPI
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$userLogger = new UserLogger($userID);
|
||||
$userLogger->push("{$reqPoint} 포인트로 전투 특기 초기화", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$oldTypeKey = 'prev_types_special2';
|
||||
$oldSpecialList = $general->getAuxVar($oldTypeKey) ?? [];
|
||||
$oldSpecialList[] = $currentSpecialWar;
|
||||
|
||||
@@ -10,6 +10,7 @@ use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Util;
|
||||
|
||||
class ResetTurnTime extends \sammo\BaseAPI
|
||||
@@ -59,6 +60,15 @@ class ResetTurnTime extends \sammo\BaseAPI
|
||||
|
||||
$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));
|
||||
if ($turnTime <= $serverTurnTimeObj && $serverTurnTimeObj <= $currTurnTime) {
|
||||
$turnTime = $turnTime->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
|
||||
|
||||
@@ -8,8 +8,11 @@ use sammo\DB;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Validator;
|
||||
|
||||
use function sammo\buildGeneralSpecialWarClass;
|
||||
|
||||
class SetNextSpecialWar extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
@@ -67,6 +70,11 @@ class SetNextSpecialWar extends \sammo\BaseAPI
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$userLogger = new UserLogger($userID);
|
||||
$specialWarObj = buildGeneralSpecialWarClass($type);
|
||||
$userLogger->push("{$reqAmount} 포인트로 다음 전투 특기로 {$specialWarObj->getName()} 지정", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$general->setAuxVar('inheritSpecificSpecialWar', $type);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
|
||||
$general->applyDB($db);
|
||||
|
||||
@@ -19,7 +19,7 @@ class che_무기_09_동호비궁 extends \sammo\BaseStatItem{
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class che_무기_13_양유기궁 extends \sammo\BaseStatItem{
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,25 +11,29 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
|
||||
protected $id = 61;
|
||||
protected $rawName = '비급';
|
||||
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 $buyable = true;
|
||||
protected $consumable = false;
|
||||
protected $reqSecu = 3000;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 0.95;
|
||||
$generalWarSpecial = $unit->getGeneral()->getSpecialWar();
|
||||
if($generalWarSpecial !== null && $generalWarSpecial->getName() == '무쌍'){
|
||||
return [1, 1];
|
||||
}
|
||||
$attackMultiplier = 1.05;
|
||||
$defenceMultiplier = 0.98;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
|
||||
$attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
|
||||
$defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class event_전투특기_반계 extends \sammo\BaseItem{
|
||||
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
return new WarUnitTriggerCaller(
|
||||
new che_반계시도($unit),
|
||||
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
|
||||
new che_반계발동($unit)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 61;
|
||||
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 $selectWeight = 1;
|
||||
@@ -19,18 +19,22 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
|
||||
];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 1;
|
||||
$generalWarSpecial = $unit->getGeneral()->getSpecialWar();
|
||||
if($generalWarSpecial !== null && $generalWarSpecial->getName() == '무쌍'){
|
||||
return [1, 1];
|
||||
}
|
||||
$attackMultiplier = 1.05;
|
||||
$defenceMultiplier = 0.98;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
|
||||
$attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
|
||||
$defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class che_무쌍 extends \sammo\BaseSpecial{
|
||||
|
||||
protected $id = 61;
|
||||
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 $selectWeight = 1;
|
||||
@@ -19,18 +19,18 @@ class che_무쌍 extends \sammo\BaseSpecial{
|
||||
];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
$attackMultiplier = 1.1;
|
||||
$defenceMultiplier = 0.95;
|
||||
$attackMultiplier = 1.05;
|
||||
$defenceMultiplier = 0.98;
|
||||
$killnum = $unit->getGeneral()->getRankVar('killnum');
|
||||
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
|
||||
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
|
||||
$attackMultiplier += log(max(1, $killnum / 5), 2) / 20;
|
||||
$defenceMultiplier -= log(max(1, $killnum / 5), 2) / 50;
|
||||
return [$attackMultiplier, $defenceMultiplier];
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@ namespace sammo;
|
||||
|
||||
class CityHelper{
|
||||
//Just Helper
|
||||
private static $list = null;
|
||||
private static $listInv = null;
|
||||
private static $listByNation = null;
|
||||
private static ?array $list = null;
|
||||
private static ?array $listInv = null;
|
||||
private static ?array $listByNation = null;
|
||||
|
||||
private function __construct(){
|
||||
|
||||
@@ -25,7 +25,7 @@ class CityHelper{
|
||||
'@phan-var array<int,mixed>|null $list';
|
||||
'@phan-var array<string,mixed>|null $listInv';
|
||||
'@phan-var array<int,mixed>|null $listByNation';
|
||||
|
||||
|
||||
foreach (DB::db()->query('SELECT `city` as `id`, `name`, `level`, `nation` from city') as $city) {
|
||||
$id = $city['id'];
|
||||
$name = $city['name'];
|
||||
@@ -83,5 +83,5 @@ class CityHelper{
|
||||
return $city;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace sammo\Command\General;
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
CityConst,
|
||||
CityConst,
|
||||
ActionLogger,
|
||||
LastTurn,
|
||||
Command
|
||||
@@ -13,6 +13,7 @@ use \sammo\{
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_NPC능동 extends Command\GeneralCommand{
|
||||
static protected $actionName = 'NPC능동';
|
||||
@@ -46,7 +47,7 @@ class che_NPC능동 extends Command\GeneralCommand{
|
||||
|
||||
$general = $this->generalObj;
|
||||
$this->setNation();
|
||||
|
||||
|
||||
|
||||
$this->permissionConstraints=[
|
||||
ConstraintHelper::MustBeNPC()
|
||||
@@ -65,7 +66,7 @@ class che_NPC능동 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -97,11 +98,11 @@ class che_NPC능동 extends Command\GeneralCommand{
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
}
|
||||
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class che_랜덤임관 extends Command\GeneralCommand
|
||||
/*if($this->arg === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
$destNationIDList = $this->arg['destNationIDList']??null;
|
||||
//null은 에러, []는 정상
|
||||
|
||||
@@ -56,8 +56,8 @@ class che_랜덤임관 extends Command\GeneralCommand
|
||||
}
|
||||
$this->arg = [
|
||||
'destNationIDList' => $destNationIDList
|
||||
];
|
||||
|
||||
];
|
||||
|
||||
return true;*/
|
||||
}
|
||||
|
||||
@@ -182,13 +182,13 @@ class che_랜덤임관 extends Command\GeneralCommand
|
||||
$generalsCnt = [];
|
||||
if ($notIn) {
|
||||
$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,
|
||||
$notIn
|
||||
);
|
||||
} else {
|
||||
$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
|
||||
);
|
||||
}
|
||||
@@ -234,7 +234,7 @@ class che_랜덤임관 extends Command\GeneralCommand
|
||||
if (!$destNation) {
|
||||
//임관 가능한 국가가 없다!
|
||||
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
|
||||
$this->alternative = new che_요양($general, $this->env, null);
|
||||
$this->alternative = new che_인재탐색($general, $this->env, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ use \sammo\{
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_모반시도 extends Command\GeneralCommand{
|
||||
static protected $actionName = '모반시도';
|
||||
|
||||
@@ -29,7 +31,7 @@ class che_모반시도 extends Command\GeneralCommand{
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::BeChief(),
|
||||
@@ -43,7 +45,7 @@ class che_모반시도 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -72,7 +74,7 @@ class che_모반시도 extends Command\GeneralCommand{
|
||||
$lordName = $lordGeneral->getName();
|
||||
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
|
||||
$logger = $general->getLogger();
|
||||
$lordLogger = $lordGeneral->getLogger();
|
||||
|
||||
@@ -82,7 +84,7 @@ class che_모반시도 extends Command\GeneralCommand{
|
||||
$lordGeneral->setVar('officer_city', 0);
|
||||
$lordGeneral->multiplyVar('experience', 0.7);
|
||||
|
||||
|
||||
|
||||
$josaYi = JosaUtil::pick($generalName, '이');
|
||||
$logger->pushGlobalHistoryLog("<Y><b>【모반】</b></><Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>의 군주 자리를 찬탈했습니다.");
|
||||
$logger->pushNationalHistoryLog("<Y>{$generalName}</>{$josaYi} <Y>{$lordName}</>에게서 군주자리를 찬탈");
|
||||
@@ -95,11 +97,12 @@ class che_모반시도 extends Command\GeneralCommand{
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
$lordGeneral->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
@@ -15,7 +15,7 @@ use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\CityConst;
|
||||
use function sammo\DeleteConflict;
|
||||
use function sammo\refreshNationStaticInfo;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_방랑 extends Command\GeneralCommand{
|
||||
static protected $actionName = '방랑';
|
||||
@@ -34,7 +34,7 @@ class che_방랑 extends Command\GeneralCommand{
|
||||
$this->setNation();
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::BeLord(),
|
||||
ConstraintHelper::NotWanderingNation(),
|
||||
@@ -48,7 +48,7 @@ class che_방랑 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class che_방랑 extends Command\GeneralCommand{
|
||||
$logger->pushGlobalHistoryLog("<R><b>【방랑】</b></><D><b>{$generalName}</b></>{$josaUn} <R>방랑</>의 길을 떠납니다.");
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$nationName}</b></>{$josaUl} 버리고 방랑");
|
||||
|
||||
|
||||
|
||||
//분쟁기록 모두 지움
|
||||
DeleteConflict($nationID);
|
||||
// 국명, 색깔 바꿈 국가 레벨 0, 성향리셋, 기술0
|
||||
@@ -123,6 +123,7 @@ class che_방랑 extends Command\GeneralCommand{
|
||||
refreshNationStaticInfo();
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -20,6 +20,7 @@ use function\sammo\tryUniqueItemLottery;
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_선양 extends Command\GeneralCommand
|
||||
{
|
||||
@@ -136,6 +137,7 @@ class che_선양 extends Command\GeneralCommand
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
$destGeneral->applyDB($db);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
@@ -13,6 +13,8 @@ use \sammo\{
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_소집해제 extends Command\GeneralCommand{
|
||||
static protected $actionName = '소집해제';
|
||||
|
||||
@@ -27,7 +29,7 @@ class che_소집해제 extends Command\GeneralCommand{
|
||||
|
||||
$this->setCity();
|
||||
$this->setNation();
|
||||
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::ReqGeneralCrew(),
|
||||
];
|
||||
@@ -43,7 +45,7 @@ class che_소집해제 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -70,7 +72,7 @@ class che_소집해제 extends Command\GeneralCommand{
|
||||
|
||||
$exp = 70;
|
||||
$ded = 100;
|
||||
|
||||
|
||||
$db->update('city', [
|
||||
'pop'=>$db->sqleval('pop + %i', $crew)
|
||||
], 'city=%i', $general->getCityID());
|
||||
@@ -80,10 +82,11 @@ class che_소집해제 extends Command\GeneralCommand{
|
||||
$general->addDedication($ded);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
@@ -13,7 +13,7 @@ use \sammo\{
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_요양 extends Command\GeneralCommand{
|
||||
static protected $actionName = '요양';
|
||||
@@ -28,7 +28,7 @@ class che_요양 extends Command\GeneralCommand{
|
||||
$general = $this->generalObj;
|
||||
|
||||
$this->setNation();
|
||||
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
];
|
||||
|
||||
@@ -37,7 +37,7 @@ class che_요양 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class che_요양 extends Command\GeneralCommand{
|
||||
$general = $this->generalObj;
|
||||
$date = $general->getTurnTime($general::TURNTIME_HM);
|
||||
|
||||
|
||||
|
||||
$crew = $general->getVar('crew');
|
||||
|
||||
$logger = $general->getLogger();
|
||||
@@ -71,10 +71,11 @@ class che_요양 extends Command\GeneralCommand{
|
||||
$general->addDedication($ded);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class che_장비매매 extends Command\GeneralCommand{
|
||||
else if($itemCode == $general->getVar($itemType)){
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 가지고 있습니다.');
|
||||
}
|
||||
else if($itemType != 'item' && !buildItemClass($general->getVar($itemType))->isBuyable()){
|
||||
else if(!buildItemClass($general->getVar($itemType))->isBuyable()){
|
||||
$this->fullConditionConstraints[] = ConstraintHelper::AlwaysFail('이미 진귀한 것을 가지고 있습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use \sammo\Json;
|
||||
|
||||
use function \sammo\searchDistance;
|
||||
use function \sammo\printCitiesBasedOnDistance;
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
@@ -217,6 +218,7 @@ class che_첩보 extends Command\GeneralCommand
|
||||
$general->increaseVar('leadership_exp', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
Command
|
||||
@@ -31,18 +31,20 @@ class che_탈취 extends che_화계{
|
||||
$commandName = $this->getName();
|
||||
$db = DB::db();
|
||||
|
||||
// 탈취 최대 800 * 8 * sqrt(1 + (year - startyear) / 5) / 2
|
||||
$yearCoef = sqrt(1 + ($this->env['year'] - $this->env['startyear']) / 5) / 2;
|
||||
$gold = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef;
|
||||
$rice = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef;
|
||||
// 탈취 최대 800 * 8 * sqrt(1 + (year - startyear) / 4) / 2
|
||||
$yearCoef = sqrt(1 + ($this->env['year'] - $this->env['startyear']) / 4) / 2;
|
||||
$commRatio = $destCity['comm'] / $destCity['comm_max'];
|
||||
$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']){
|
||||
[$destNationGold, $destNationRice] = $db->queryFirstList('SELECT gold,rice FROM nation WHERE nation=%i', $destNationID);
|
||||
|
||||
|
||||
$destNationGold -= $gold;
|
||||
$destNationRice -= $rice;
|
||||
|
||||
if($destNationGold < GameConst::$minNationalGold) {
|
||||
|
||||
if($destNationGold < GameConst::$minNationalGold) {
|
||||
$gold += $destNationGold - GameConst::$minNationalGold;
|
||||
$destNationGold = GameConst::$minNationalGold;
|
||||
}
|
||||
@@ -50,7 +52,7 @@ class che_탈취 extends che_화계{
|
||||
$rice += $destNationRice - GameConst::$minNationalRice;
|
||||
$destNationRice = GameConst::$minNationalRice;
|
||||
}
|
||||
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$destNationGold,
|
||||
'rice'=>$destNationRice
|
||||
@@ -96,5 +98,5 @@ class che_탈취 extends che_화계{
|
||||
|
||||
$logger->pushGeneralActionLog("금<C>{$goldText}</> 쌀<C>{$riceText}</>을 획득했습니다.", ActionLogger::PLAIN);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
@@ -14,7 +14,7 @@ use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\CityConst;
|
||||
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_하야 extends Command\GeneralCommand{
|
||||
static protected $actionName = '하야';
|
||||
@@ -32,7 +32,7 @@ class che_하야 extends Command\GeneralCommand{
|
||||
$this->setNation();
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
ConstraintHelper::NotBeNeutral(),
|
||||
ConstraintHelper::NotOpeningPart($relYear),
|
||||
@@ -43,7 +43,7 @@ class che_하야 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class che_하야 extends Command\GeneralCommand{
|
||||
|
||||
$nationID = $this->nation['nation'];
|
||||
$nationName = $this->nation['name'];
|
||||
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 하야했습니다. <1>$date</>");
|
||||
@@ -101,13 +101,14 @@ class che_하야 extends Command\GeneralCommand{
|
||||
$general->setVar('officer_city', 0);
|
||||
$general->setVar('belong', 0);
|
||||
$general->setVar('makelimit', 12);
|
||||
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil,
|
||||
General,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
@@ -16,13 +16,12 @@ use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\CityConst;
|
||||
use function sammo\refreshNationStaticInfo;
|
||||
use function sammo\deleteNation;
|
||||
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class che_해산 extends Command\GeneralCommand{
|
||||
static protected $actionName = '해산';
|
||||
|
||||
protected function argTest():bool{
|
||||
protected function argTest():bool{
|
||||
$this->arg = [];
|
||||
|
||||
return true;
|
||||
@@ -45,7 +44,7 @@ class che_해산 extends Command\GeneralCommand{
|
||||
public function getCost():array{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
return 0;
|
||||
}
|
||||
@@ -96,11 +95,11 @@ class che_해산 extends Command\GeneralCommand{
|
||||
$oldGeneral->setVar('makelimit', 12);
|
||||
$oldGeneral->applyDB($db);
|
||||
}
|
||||
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@ use \sammo\Command;
|
||||
|
||||
use function \sammo\searchDistance;
|
||||
use function \sammo\printCitiesBasedOnDistance;
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
@@ -294,6 +295,7 @@ class che_화계 extends Command\GeneralCommand
|
||||
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
return false;
|
||||
}
|
||||
@@ -327,6 +329,7 @@ class che_화계 extends Command\GeneralCommand
|
||||
$general->increaseRankVar('firenum', 1);
|
||||
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
|
||||
$general->checkStatChange();
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB($db);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -7,9 +7,11 @@ use \sammo\JosaUtil;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\DB;
|
||||
|
||||
use function sammo\tryRollbackInheritUniqueItem;
|
||||
|
||||
class 휴식 extends Command\GeneralCommand{
|
||||
static protected $actionName = '휴식';
|
||||
|
||||
|
||||
protected function argTest():bool{
|
||||
return true;
|
||||
}
|
||||
@@ -39,7 +41,7 @@ class 휴식 extends Command\GeneralCommand{
|
||||
$logger->pushGeneralActionLog("아무것도 실행하지 않았습니다. <1>$date</>");
|
||||
|
||||
$this->setResultTurn(new LastTurn());
|
||||
|
||||
tryRollbackInheritUniqueItem($general);
|
||||
$general->applyDB(DB::db());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ class che_물자원조 extends Command\NationCommand{
|
||||
}
|
||||
|
||||
$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}</>을 지원 받음");
|
||||
|
||||
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
|
||||
|
||||
@@ -33,6 +33,9 @@ class che_피장파장 extends Command\NationCommand{
|
||||
if(!key_exists('destNationID', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
if(!key_exists('commandType', $this->arg)){
|
||||
return false;
|
||||
}
|
||||
$destNationID = $this->arg['destNationID'];
|
||||
$commandType = $this->arg['commandType'];
|
||||
|
||||
|
||||
@@ -42,6 +42,22 @@ class DummyGeneral extends General{
|
||||
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{
|
||||
if($this->logger){
|
||||
$this->initLogger(1, 1);
|
||||
|
||||
@@ -9,9 +9,11 @@ use function sammo\pickGeneralFromPool;
|
||||
//기존 event_3.php
|
||||
class CreateManyNPC extends \sammo\Event\Action{
|
||||
protected $npcCount;
|
||||
protected $fillCnt;
|
||||
protected $avgGen;
|
||||
public function __construct($npcCount = 10){
|
||||
public function __construct($npcCount = 10, $fillCnt = 0){
|
||||
$this->npcCount = $npcCount;
|
||||
$this->fillCnt = $fillCnt;
|
||||
}
|
||||
|
||||
protected function generateNPC($env, int $cnt){
|
||||
@@ -41,13 +43,23 @@ class CreateManyNPC extends \sammo\Event\Action{
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function run(array $env){
|
||||
if($this->npcCount <= 0){
|
||||
return [__CLASS__, []];
|
||||
if($this->npcCount <= 0 && $this->fillCnt <= 0){
|
||||
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']);
|
||||
$genCnt = count($result);
|
||||
@@ -62,6 +74,6 @@ class CreateManyNPC extends \sammo\Event\Action{
|
||||
$logger->pushGlobalHistoryLog("장수 <C>{$genCnt}</>명이 <S>등장</>했습니다.", \sammo\ActionLogger::NOTICE_YEAR_MONTH);
|
||||
$logger->flush();
|
||||
|
||||
return [__CLASS__, $result];
|
||||
return [__CLASS__, $result];
|
||||
}
|
||||
}
|
||||
+452
-344
@@ -5,7 +5,8 @@ namespace sammo;
|
||||
use sammo\Command\GeneralCommand;
|
||||
use sammo\WarUnitTrigger as WarUnitTrigger;
|
||||
|
||||
class General implements iAction{
|
||||
class General implements iAction
|
||||
{
|
||||
use LazyVarUpdater;
|
||||
|
||||
protected $raw = [];
|
||||
@@ -42,28 +43,28 @@ class General implements iAction{
|
||||
protected $resultTurn = null;
|
||||
|
||||
const RANK_COLUMN = [
|
||||
'firenum'=>1, 'warnum'=>1, 'killnum'=>1, 'deathnum'=>1, 'killcrew'=>1, 'deathcrew'=>1,
|
||||
'ttw'=>1, 'ttd'=>1, 'ttl'=>1, 'ttg'=>1, 'ttp'=>1,
|
||||
'tlw'=>1, 'tld'=>1, 'tll'=>1, 'tlg'=>1, 'tlp'=>1,
|
||||
'tsw'=>1, 'tsd'=>1, 'tsl'=>1, 'tsg'=>1, 'tsp'=>1,
|
||||
'tiw'=>1, 'tid'=>1, 'til'=>1, 'tig'=>1, 'tip'=>1,
|
||||
'betwin'=>1, 'betgold'=>1, 'betwingold'=>1,
|
||||
'killcrew_person'=>1, 'deathcrew_person'=>1,
|
||||
'occupied'=>1,
|
||||
'firenum' => 1, 'warnum' => 1, 'killnum' => 1, 'deathnum' => 1, 'killcrew' => 1, 'deathcrew' => 1,
|
||||
'ttw' => 1, 'ttd' => 1, 'ttl' => 1, 'ttg' => 1, 'ttp' => 1,
|
||||
'tlw' => 1, 'tld' => 1, 'tll' => 1, 'tlg' => 1, 'tlp' => 1,
|
||||
'tsw' => 1, 'tsd' => 1, 'tsl' => 1, 'tsg' => 1, 'tsp' => 1,
|
||||
'tiw' => 1, 'tid' => 1, 'til' => 1, 'tig' => 1, 'tip' => 1,
|
||||
'betwin' => 1, 'betgold' => 1, 'betwingold' => 1,
|
||||
'killcrew_person' => 1, 'deathcrew_person' => 1,
|
||||
'occupied' => 1,
|
||||
];
|
||||
|
||||
const INHERITANCE_KEY = [
|
||||
'previous'=>[true, 1, '기존 포인트'],
|
||||
'lived_month'=>[true, 1, '생존'],
|
||||
'max_belong'=>[false, 10, '최대 임관년 수'],
|
||||
'max_domestic_critical'=>[true, 1, '최대 연속 내정 성공'],
|
||||
'snipe_combat'=>[true, 10, '병종 상성 우위 횟수'],
|
||||
'combat'=>[['rank', 'warnum'], 5, '전투 횟수'],
|
||||
'sabotage'=>[['rank', 'firenum'], 20, '계략 성공 횟수'],
|
||||
'unifier'=>[true, 1, '천통 기여'],
|
||||
'dex'=>[false, 0.001, '숙련도'],
|
||||
'tournament'=>[true, 1, '토너먼트'],
|
||||
'betting'=>[false, 10, '베팅 당첨'],
|
||||
'previous' => [true, 1, '기존 포인트'],
|
||||
'lived_month' => [true, 1, '생존'],
|
||||
'max_belong' => [false, 10, '최대 임관년 수'],
|
||||
'max_domestic_critical' => [true, 1, '최대 연속 내정 성공'],
|
||||
'snipe_combat' => [true, 10, '병종 상성 우위 횟수'],
|
||||
'combat' => [['rank', 'warnum'], 5, '전투 횟수'],
|
||||
'sabotage' => [['rank', 'firenum'], 20, '계략 성공 횟수'],
|
||||
'unifier' => [true, 1, '천통 기여'],
|
||||
'dex' => [false, 0.001, '숙련도'],
|
||||
'tournament' => [true, 1, '토너먼트'],
|
||||
'betting' => [false, 10, '베팅 당첨'],
|
||||
];
|
||||
|
||||
const TURNTIME_FULL_MS = -1;
|
||||
@@ -75,19 +76,19 @@ class General implements iAction{
|
||||
|
||||
protected static $prohibitedDirectUpdateVars = [
|
||||
//Reason: iAction
|
||||
'leadership'=>1,
|
||||
'power'=>1,
|
||||
'intel'=>1,
|
||||
'nation'=>2,
|
||||
'officer_level'=>1,
|
||||
'leadership' => 1,
|
||||
'power' => 1,
|
||||
'intel' => 1,
|
||||
'nation' => 2,
|
||||
'officer_level' => 1,
|
||||
//NOTE: officerLevelObj로 인해 국가의 '레벨'이 바뀌는 것도 조심해야 하나, 국가 레벨의 변경은 월 초/말에만 일어남.
|
||||
'special'=>1,
|
||||
'special2'=>1,
|
||||
'personal'=>1,
|
||||
'horse'=>1,
|
||||
'weapon'=>1,
|
||||
'book'=>1,
|
||||
'item'=>1
|
||||
'special' => 1,
|
||||
'special2' => 1,
|
||||
'personal' => 1,
|
||||
'horse' => 1,
|
||||
'weapon' => 1,
|
||||
'book' => 1,
|
||||
'item' => 1
|
||||
];
|
||||
|
||||
|
||||
@@ -98,10 +99,11 @@ class General implements iAction{
|
||||
* @param int|null $month 게임 월
|
||||
* @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 값을 직접 구해야함.
|
||||
|
||||
if($nation === null){
|
||||
if ($nation === null) {
|
||||
$nation = getNationStaticInfo($raw['nation']);
|
||||
}
|
||||
|
||||
@@ -109,20 +111,20 @@ class General implements iAction{
|
||||
$this->rawCity = $city;
|
||||
|
||||
$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->resultTurn = $this->lastTurn->duplicate();
|
||||
}
|
||||
|
||||
if($year !== null && $month !== null){
|
||||
if ($year !== null && $month !== null) {
|
||||
$this->initLogger($year, $month);
|
||||
}
|
||||
|
||||
if($rawRank){
|
||||
if ($rawRank) {
|
||||
$this->rankVarRead = $rawRank;
|
||||
}
|
||||
|
||||
if(!$fullConstruct){
|
||||
if (!$fullConstruct) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -139,15 +141,16 @@ class General implements iAction{
|
||||
$this->itemObjs['book'] = buildItemClass($raw['book']);
|
||||
$this->itemObjs['item'] = buildItemClass($raw['item']);
|
||||
|
||||
if(key_exists('aux', $this->raw)){
|
||||
if (key_exists('aux', $this->raw)) {
|
||||
$rawInheritBuff = $this->getAuxVar('inheritBuff');
|
||||
if($rawInheritBuff !== null){
|
||||
if ($rawInheritBuff !== null) {
|
||||
$this->inheritBuffObj = new TriggerInheritBuff($rawInheritBuff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initLogger(int $year, int $month){
|
||||
function initLogger(int $year, int $month)
|
||||
{
|
||||
$this->logger = new ActionLogger(
|
||||
$this->getVar('no'),
|
||||
$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 [
|
||||
self::TURNTIME_FULL_MS=>function($turntime){return $turntime;},
|
||||
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);},
|
||||
self::TURNTIME_FULL_MS => function ($turntime) {
|
||||
return $turntime;
|
||||
},
|
||||
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'));
|
||||
}
|
||||
|
||||
function setItem(string $itemKey='item', ?string $itemCode){
|
||||
if($itemCode === null){
|
||||
function setItem(string $itemKey = 'item', ?string $itemCode)
|
||||
{
|
||||
if ($itemCode === null) {
|
||||
$this->deleteItem($itemKey);
|
||||
}
|
||||
|
||||
@@ -175,50 +188,61 @@ class General implements iAction{
|
||||
$this->itemObjs[$itemKey] = buildItemClass($itemCode);
|
||||
}
|
||||
|
||||
function deleteItem(string $itemKey='item'){
|
||||
function deleteItem(string $itemKey = 'item')
|
||||
{
|
||||
$this->setVar($itemKey, 'None');
|
||||
$this->itemObjs[$itemKey] = new ActionItem\None();
|
||||
}
|
||||
|
||||
function getItem(string $itemKey='item'):BaseItem{
|
||||
function getItem(string $itemKey = 'item'): BaseItem
|
||||
{
|
||||
return $this->itemObjs[$itemKey];
|
||||
}
|
||||
|
||||
function getNPCType():int{
|
||||
function getNPCType(): int
|
||||
{
|
||||
return $this->raw['npc'];
|
||||
}
|
||||
|
||||
/** @return BaseItem[] */
|
||||
function getItems():array{
|
||||
function getItems(): array
|
||||
{
|
||||
return $this->itemObjs;
|
||||
}
|
||||
|
||||
function getPersonality():iAction{
|
||||
function getPersonality(): iAction
|
||||
{
|
||||
return $this->personalityObj;
|
||||
}
|
||||
|
||||
function getSpecialDomestic():iAction{
|
||||
function getSpecialDomestic(): iAction
|
||||
{
|
||||
return $this->specialDomesticObj;
|
||||
}
|
||||
|
||||
function getSpecialWar():iAction{
|
||||
function getSpecialWar(): iAction
|
||||
{
|
||||
return $this->specialWarObj;
|
||||
}
|
||||
|
||||
function getLastTurn():LastTurn{
|
||||
function getLastTurn(): LastTurn
|
||||
{
|
||||
return $this->lastTurn;
|
||||
}
|
||||
|
||||
function _setResultTurn(LastTurn $resultTurn){
|
||||
function _setResultTurn(LastTurn $resultTurn)
|
||||
{
|
||||
$this->resultTurn = $resultTurn;
|
||||
}
|
||||
|
||||
function getResultTurn():LastTurn{
|
||||
function getResultTurn(): LastTurn
|
||||
{
|
||||
return $this->resultTurn;
|
||||
}
|
||||
|
||||
function clearActivatedSkill(){
|
||||
foreach ($this->activatedSkill as $skillName=>$state) {
|
||||
function clearActivatedSkill()
|
||||
{
|
||||
foreach ($this->activatedSkill as $skillName => $state) {
|
||||
if (!$state) {
|
||||
continue;
|
||||
}
|
||||
@@ -232,86 +256,103 @@ class General implements iAction{
|
||||
$this->activatedSkill = [];
|
||||
}
|
||||
|
||||
function getActivatedSkillLog():array{
|
||||
function getActivatedSkillLog(): array
|
||||
{
|
||||
return $this->logActivatedSkill;
|
||||
}
|
||||
|
||||
function hasActivatedSkill(string $skillName):bool{
|
||||
function hasActivatedSkill(string $skillName): bool
|
||||
{
|
||||
return $this->activatedSkill[$skillName] ?? false;
|
||||
}
|
||||
|
||||
function activateSkill(... $skillNames){
|
||||
foreach($skillNames as $skillName){
|
||||
function activateSkill(...$skillNames)
|
||||
{
|
||||
foreach ($skillNames as $skillName) {
|
||||
$this->activatedSkill[$skillName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function deactivateSkill(... $skillNames){
|
||||
foreach($skillNames as $skillName){
|
||||
function deactivateSkill(...$skillNames)
|
||||
{
|
||||
foreach ($skillNames as $skillName) {
|
||||
$this->activatedSkill[$skillName] = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getName():string{
|
||||
function getName(): string
|
||||
{
|
||||
return $this->raw['name'];
|
||||
}
|
||||
|
||||
function getInfo():string{
|
||||
function getInfo(): string
|
||||
{
|
||||
//iAction용 info로는 적절하지 않음
|
||||
return '';
|
||||
}
|
||||
|
||||
function getID():int{
|
||||
function getID(): int
|
||||
{
|
||||
return $this->raw['no'];
|
||||
}
|
||||
|
||||
function getRawCity():?array{
|
||||
function getRawCity(): ?array
|
||||
{
|
||||
return $this->rawCity;
|
||||
}
|
||||
|
||||
function setRawCity(?array $city){
|
||||
function setRawCity(?array $city)
|
||||
{
|
||||
$this->rawCity = $city;
|
||||
}
|
||||
|
||||
function getCityID():int{
|
||||
function getCityID(): int
|
||||
{
|
||||
return $this->raw['city'];
|
||||
}
|
||||
|
||||
function getNationID():int{
|
||||
function getNationID(): int
|
||||
{
|
||||
return $this->raw['nation'];
|
||||
}
|
||||
|
||||
function getStaticNation():array{
|
||||
function getStaticNation(): array
|
||||
{
|
||||
return getNationStaticInfo($this->raw['nation']);
|
||||
}
|
||||
|
||||
function getLogger():?ActionLogger{
|
||||
function getLogger(): ?ActionLogger
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
public function getNationTypeObj():iAction{
|
||||
public function getNationTypeObj(): iAction
|
||||
{
|
||||
return $this->nationType;
|
||||
}
|
||||
|
||||
public function getOfficerLevelObj():iAction{
|
||||
public function getOfficerLevelObj(): iAction
|
||||
{
|
||||
return $this->officerLevelObj;
|
||||
}
|
||||
|
||||
function getCrewTypeObj():GameUnitDetail{
|
||||
function getCrewTypeObj(): GameUnitDetail
|
||||
{
|
||||
$crewType = GameUnitConst::byID($this->getVar('crewtype'));
|
||||
if($crewType === null){
|
||||
throw new \InvalidArgumentException('Invalid CrewType:'.$this->getVar('crewtype'));
|
||||
if ($crewType === null) {
|
||||
throw new \InvalidArgumentException('Invalid CrewType:' . $this->getVar('crewtype'));
|
||||
}
|
||||
return $crewType;
|
||||
}
|
||||
|
||||
function calcRecentWarTurn(int $turnTerm):int{
|
||||
function calcRecentWarTurn(int $turnTerm): int
|
||||
{
|
||||
$cacheKey = "recent_war_turn_{$turnTerm}";
|
||||
if(key_exists($cacheKey, $this->calcCache)){
|
||||
if (key_exists($cacheKey, $this->calcCache)) {
|
||||
return $this->calcCache[$cacheKey];
|
||||
}
|
||||
if(!$this->getVar('recent_war')){
|
||||
$result = 12*1000;
|
||||
if (!$this->getVar('recent_war')) {
|
||||
$result = 12 * 1000;
|
||||
$this->calcCache[$cacheKey] = $result;
|
||||
return $result;
|
||||
}
|
||||
@@ -319,7 +360,7 @@ class General implements iAction{
|
||||
$turnNow = new \DateTimeImmutable($this->getVar('turntime'));
|
||||
$secDiff = TimeUtil::DateIntervalToSeconds($recwar->diff($turnNow));
|
||||
|
||||
if($secDiff <= 0){
|
||||
if ($secDiff <= 0) {
|
||||
$this->calcCache[$cacheKey] = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -329,13 +370,14 @@ class General implements iAction{
|
||||
return $result;
|
||||
}
|
||||
|
||||
function getReservedTurn(int $turnIdx, array $env):GeneralCommand{
|
||||
function getReservedTurn(int $turnIdx, array $env): GeneralCommand
|
||||
{
|
||||
$db = DB::db();
|
||||
$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($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
|
||||
* @return GeneralCommand[]
|
||||
*/
|
||||
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env){
|
||||
if($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn){
|
||||
throw new \OutOfRangeException('$turnIdxFrom 범위 초과'.$turnIdxFrom);
|
||||
public function getReservedTurnList(int $turnIdxFrom, int $turnIdxTo, array $env)
|
||||
{
|
||||
if ($turnIdxFrom < 0 || $turnIdxFrom >= GameConst::$maxTurn) {
|
||||
throw new \OutOfRangeException('$turnIdxFrom 범위 초과' . $turnIdxFrom);
|
||||
}
|
||||
|
||||
if($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo){
|
||||
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
|
||||
if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
|
||||
throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
if(!$rawCmds){
|
||||
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
|
||||
if (!$rawCmds) {
|
||||
foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
|
||||
$result[$turnIdx] = buildGeneralCommandClass(null, $this, $env);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
foreach($rawCmds as $turnIdx=>$rawCmd){
|
||||
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg']??null));
|
||||
foreach ($rawCmds as $turnIdx => $rawCmd) {
|
||||
$result[$turnIdx] = buildGeneralCommandClass($rawCmd['action'], $this, $env, Json::decode($rawCmd['arg'] ?? null));
|
||||
}
|
||||
|
||||
return $result;
|
||||
@@ -388,11 +431,12 @@ class General implements iAction{
|
||||
* @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}";
|
||||
if(key_exists($cKey, $this->calcCache)){
|
||||
if (key_exists($cKey, $this->calcCache)) {
|
||||
$statValue = $this->calcCache[$cKey];
|
||||
if($useFloor){
|
||||
if ($useFloor) {
|
||||
return Util::toInt($statValue);
|
||||
}
|
||||
return $statValue;
|
||||
@@ -400,35 +444,34 @@ class General implements iAction{
|
||||
|
||||
$statValue = $this->getVar($statName);
|
||||
|
||||
if($withInjury){
|
||||
if ($withInjury) {
|
||||
$statValue *= (100 - $this->getVar('injury')) / 100;
|
||||
}
|
||||
|
||||
if($withStatAdjust){
|
||||
if($statName === 'strength'){
|
||||
if ($withStatAdjust) {
|
||||
if ($statName === 'strength') {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
if($withIActionObj){
|
||||
foreach([
|
||||
if ($withIActionObj) {
|
||||
foreach ([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
$this->specialWarObj,
|
||||
$this->personalityObj,
|
||||
$this->inheritBuffObj,
|
||||
] as $actionObj){
|
||||
if($actionObj !== null){
|
||||
] as $actionObj) {
|
||||
if ($actionObj !== null) {
|
||||
$statValue = $actionObj->onCalcStat($this, $statName, $statValue);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->itemObjs as $actionObj){
|
||||
if($actionObj !== null){
|
||||
foreach ($this->itemObjs as $actionObj) {
|
||||
if ($actionObj !== null) {
|
||||
$statValue = $actionObj->onCalcStat($this, $statName, $statValue);
|
||||
}
|
||||
}
|
||||
@@ -436,54 +479,58 @@ class General implements iAction{
|
||||
|
||||
$this->calcCache[$cKey] = $statValue;
|
||||
|
||||
if($useFloor){
|
||||
if ($useFloor) {
|
||||
return Util::toInt($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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function getDex(GameUnitDetail $crewType){
|
||||
function getDex(GameUnitDetail $crewType)
|
||||
{
|
||||
$armType = $crewType->armType;
|
||||
|
||||
if($armType == GameUnitConst::T_CASTLE){
|
||||
if ($armType == GameUnitConst::T_CASTLE) {
|
||||
$armType = GameUnitConst::T_SIEGE;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if($armType == GameUnitConst::T_CASTLE){
|
||||
if ($armType == GameUnitConst::T_CASTLE) {
|
||||
$armType = GameUnitConst::T_SIEGE;
|
||||
}
|
||||
|
||||
if($armType < 0){
|
||||
if ($armType < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($armType == GameUnitConst::T_WIZARD) {
|
||||
if ($armType == GameUnitConst::T_WIZARD) {
|
||||
$exp *= 0.9;
|
||||
}
|
||||
else if($armType == GameUnitConst::T_SIEGE) {
|
||||
} else if ($armType == GameUnitConst::T_SIEGE) {
|
||||
$exp *= 0.9;
|
||||
}
|
||||
|
||||
if($affectTrainAtmos){
|
||||
if ($affectTrainAtmos) {
|
||||
$exp *= ($this->getVar('train') + $this->getVar('atmos')) / 200;
|
||||
}
|
||||
|
||||
@@ -492,39 +539,39 @@ class General implements iAction{
|
||||
$this->increaseVar($dexType, $exp);
|
||||
}
|
||||
|
||||
function addExperience(float $experience, bool $affectTrigger=true){
|
||||
if($affectTrigger){
|
||||
function addExperience(float $experience, bool $affectTrigger = true)
|
||||
{
|
||||
if ($affectTrigger) {
|
||||
$experience = $this->onCalcStat($this, 'experience', $experience);
|
||||
}
|
||||
|
||||
$this->increaseVar('experience', $experience);
|
||||
$nextExpLevel = getExpLevel($this->getVar('experience'));
|
||||
$comp = $nextExpLevel <=> $this->getVar('explevel');
|
||||
if($comp === 0){
|
||||
if ($comp === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateVar('explevel', $nextExpLevel);
|
||||
|
||||
$josaRo = JosaUtil::pick($nextExpLevel, '로');
|
||||
if($comp > 0){
|
||||
if ($comp > 0) {
|
||||
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <C>레벨업</>!", ActionLogger::PLAIN);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$this->getLogger()->pushGeneralActionLog("<C>Lv {$nextExpLevel}</>{$josaRo} <R>레벨다운</>!", ActionLogger::PLAIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function addDedication(float $dedication, bool $affectTrigger=true){
|
||||
if($affectTrigger){
|
||||
function addDedication(float $dedication, bool $affectTrigger = true)
|
||||
{
|
||||
if ($affectTrigger) {
|
||||
$dedication = $this->onCalcStat($this, 'dedication', $dedication);
|
||||
}
|
||||
|
||||
$this->increaseVar('dedication', $dedication);
|
||||
$nextDedLevel = getDedLevel($this->getVar('dedication'));
|
||||
$comp = $nextDedLevel <=> $this->getVar('dedlevel');
|
||||
if($comp === 0){
|
||||
if ($comp === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -534,20 +581,19 @@ class General implements iAction{
|
||||
$billText = number_format(getBillByLevel($nextDedLevel));
|
||||
$josaRoDed = JosaUtil::pick($dedLevelText, '로');
|
||||
$josaRoBill = JosaUtil::pick($billText, '로');
|
||||
if($comp > 0){
|
||||
if ($comp > 0) {
|
||||
$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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateVar(string $key, $value){
|
||||
if(($this->raw[$key]??null) === $value){
|
||||
function updateVar(string $key, $value)
|
||||
{
|
||||
if (($this->raw[$key] ?? null) === $value) {
|
||||
return;
|
||||
}
|
||||
if(!key_exists($key, $this->updatedVar)){
|
||||
if (!key_exists($key, $this->updatedVar)) {
|
||||
$this->updatedVar[$key] = true;
|
||||
}
|
||||
$this->raw[$key] = $value;
|
||||
@@ -557,39 +603,81 @@ class General implements iAction{
|
||||
/**
|
||||
* @param \MeekroDB $db
|
||||
*/
|
||||
function kill($db, bool $sendDyingMessage=true, ?string $dyingMessage=null){
|
||||
function kill($db, bool $sendDyingMessage = true, ?string $dyingMessage = null)
|
||||
{
|
||||
$generalID = $this->getID();
|
||||
$logger = $this->getLogger();
|
||||
|
||||
$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');
|
||||
if($officerLevel == 12) {
|
||||
if ($officerLevel == 12) {
|
||||
nextRuler($this);
|
||||
$this->setVar('officer_level', 1);
|
||||
}
|
||||
|
||||
// 부대 처리
|
||||
$troopLeaderID = $this->getVar('troop');
|
||||
if($troopLeaderID == $generalID){
|
||||
if ($troopLeaderID == $generalID) {
|
||||
//부대장일 경우
|
||||
// 모두 탈퇴
|
||||
$db->update('general', [
|
||||
'troop'=>0
|
||||
'troop' => 0
|
||||
], 'troop=%i', $troopLeaderID);
|
||||
// 부대 삭제
|
||||
$db->delete('troop', 'troop_leader=%i', $troopLeaderID);
|
||||
}
|
||||
|
||||
|
||||
if($sendDyingMessage){
|
||||
if($dyingMessage){
|
||||
if ($sendDyingMessage) {
|
||||
if ($dyingMessage) {
|
||||
$logger->pushGlobalActionLog($dyingMessage);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$dyingMessageObj = new TextDecoration\DyingMessage($this);
|
||||
$logger->pushGlobalActionLog($dyingMessageObj->getText());
|
||||
}
|
||||
@@ -597,9 +685,9 @@ class General implements iAction{
|
||||
}
|
||||
|
||||
$db->update('select_pool', [
|
||||
'general_id'=>null,
|
||||
'owner'=>null,
|
||||
'reserved_until'=>null,
|
||||
'general_id' => null,
|
||||
'owner' => null,
|
||||
'reserved_until' => null,
|
||||
], 'general_id=%i', $generalID);
|
||||
|
||||
$db->delete('general', 'no=%i', $generalID);
|
||||
@@ -609,17 +697,18 @@ class General implements iAction{
|
||||
$this->updatedVar = [];
|
||||
|
||||
$db->update('nation', [
|
||||
'gennum'=>$db->sqleval('gennum - 1')
|
||||
'gennum' => $db->sqleval('gennum - 1')
|
||||
], 'nation=%i', $this->getVar('nation'));
|
||||
}
|
||||
|
||||
function rebirth(){
|
||||
function rebirth()
|
||||
{
|
||||
$logger = $this->getLogger();
|
||||
|
||||
$generalName = $this->getName();
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if($ownerID){
|
||||
if ($ownerID) {
|
||||
$this->mergeTotalInheritancePoint();
|
||||
resetInheritanceUser($ownerID, true);
|
||||
}
|
||||
@@ -639,7 +728,7 @@ class General implements iAction{
|
||||
$this->multiplyVar('dex4', 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);
|
||||
}
|
||||
|
||||
@@ -649,23 +738,24 @@ class General implements iAction{
|
||||
$logger->pushGeneralHistoryLog('나이가 들어 은퇴하고, 자손에게 관직을 물려줌');
|
||||
}
|
||||
|
||||
function increaseRankVar(string $key, int $value){
|
||||
if(!key_exists($key, static::RANK_COLUMN)){
|
||||
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
|
||||
function increaseRankVar(string $key, int $value)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
if(key_exists($key, $this->rankVarRead)){
|
||||
if (key_exists($key, $this->rankVarRead)) {
|
||||
$this->rankVarSet[$key] = $this->rankVarRead[$key] + $value;
|
||||
unset($this->rankVarRead[$key]);
|
||||
return;
|
||||
}
|
||||
|
||||
if(key_exists($key, $this->rankVarIncrease)){
|
||||
if (key_exists($key, $this->rankVarIncrease)) {
|
||||
$this->rankVarIncrease[$key] += $value;
|
||||
return;
|
||||
}
|
||||
@@ -673,31 +763,32 @@ class General implements iAction{
|
||||
$this->rankVarIncrease[$key] = $value;
|
||||
}
|
||||
|
||||
function setRankVar(string $key, int $value){
|
||||
if(!key_exists($key, static::RANK_COLUMN)){
|
||||
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
|
||||
function setRankVar(string $key, int $value)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
else if(key_exists($key, $this->rankVarIncrease)){
|
||||
} else if (key_exists($key, $this->rankVarIncrease)) {
|
||||
unset($this->rankVarIncrease[$key]);
|
||||
}
|
||||
$this->rankVarSet[$key]=$value;
|
||||
$this->rankVarSet[$key] = $value;
|
||||
}
|
||||
|
||||
function getRankVar(string $key):int{
|
||||
if(!key_exists($key, static::RANK_COLUMN)){
|
||||
throw new \InvalidArgumentException('올바르지 않은 인자 :'.$key);
|
||||
function getRankVar(string $key): int
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
if(!key_exists($key, $this->rankVarRead)){
|
||||
throw new \RuntimeException('인자가 없음 : '.$key);
|
||||
if (!key_exists($key, $this->rankVarRead)) {
|
||||
throw new \RuntimeException('인자가 없음 : ' . $key);
|
||||
}
|
||||
|
||||
return $this->rankVarRead[$key];
|
||||
@@ -706,8 +797,9 @@ class General implements iAction{
|
||||
/**
|
||||
* @param \MeekroDB $db
|
||||
*/
|
||||
function applyDB($db):bool{
|
||||
if($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()){
|
||||
function applyDB($db): bool
|
||||
{
|
||||
if ($this->lastTurn && $this->getLastTurn() != $this->getResultTurn()) {
|
||||
$this->setVar('last_turn', $this->getResultTurn()->toJson());
|
||||
}
|
||||
$updateVals = $this->getUpdatedValues();
|
||||
@@ -716,31 +808,31 @@ class General implements iAction{
|
||||
$generalID = $this->getID();
|
||||
$result = false;
|
||||
|
||||
if($updateVals){
|
||||
if ($updateVals) {
|
||||
$db->update('general', $updateVals, 'no=%i', $generalID);
|
||||
$result = $result || $db->affectedRows() > 0;
|
||||
if(key_exists('nation', $updateVals)){
|
||||
if (key_exists('nation', $updateVals)) {
|
||||
$db->update('rank_data', [
|
||||
'nation_id'=>$updateVals['nation']
|
||||
'nation_id' => $updateVals['nation']
|
||||
], 'general_id = %i', $generalID);
|
||||
$result = true;
|
||||
}
|
||||
$this->flushUpdateValues();
|
||||
}
|
||||
|
||||
if($this->rankVarIncrease){
|
||||
foreach($this->rankVarIncrease as $rankKey => $rankVal){
|
||||
if ($this->rankVarIncrease) {
|
||||
foreach ($this->rankVarIncrease as $rankKey => $rankVal) {
|
||||
$db->update('rank_data', [
|
||||
'value'=>$db->sqleval('value + %i', $rankVal)
|
||||
'value' => $db->sqleval('value + %i', $rankVal)
|
||||
], 'general_id = %i AND type = %s', $generalID, $rankKey);
|
||||
}
|
||||
$result = true;
|
||||
}
|
||||
|
||||
if($this->rankVarSet){
|
||||
foreach($this->rankVarSet as $rankKey => $rankVal){
|
||||
if ($this->rankVarSet) {
|
||||
foreach ($this->rankVarSet as $rankKey => $rankVal) {
|
||||
$db->update('rank_data', [
|
||||
'value'=>$rankVal
|
||||
'value' => $rankVal
|
||||
], 'general_id = %i AND type = %s', $generalID, $rankKey);
|
||||
$this->rankVarRead[$rankKey] = $rankVal;
|
||||
}
|
||||
@@ -754,7 +846,8 @@ class General implements iAction{
|
||||
return $result;
|
||||
}
|
||||
|
||||
function checkStatChange():bool{
|
||||
function checkStatChange(): bool
|
||||
{
|
||||
$logger = $this->getLogger();
|
||||
$limit = GameConst::$upgradeLimit;
|
||||
|
||||
@@ -766,16 +859,15 @@ class General implements iAction{
|
||||
|
||||
$result = false;
|
||||
|
||||
foreach($table as [$statNickName, $statName]){
|
||||
$statExpName = $statName.'_exp';
|
||||
foreach ($table as [$statNickName, $statName]) {
|
||||
$statExpName = $statName . '_exp';
|
||||
|
||||
if($this->getVar($statExpName) < 0){
|
||||
if ($this->getVar($statExpName) < 0) {
|
||||
$logger->pushGeneralActionLog("<R>{$statNickName}</>이 <C>1</> 떨어졌습니다!", ActionLogger::PLAIN);
|
||||
$this->increaseVar($statExpName, $limit);
|
||||
$this->increaseVar($statName, -1);
|
||||
$result = true;
|
||||
}
|
||||
else if($this->getVar($statExpName) >= $limit){
|
||||
} else if ($this->getVar($statExpName) >= $limit) {
|
||||
$logger->pushGeneralActionLog("<S>{$statNickName}</>이 <C>1</> 올랐습니다!", ActionLogger::PLAIN);
|
||||
$this->increaseVar($statExpName, -$limit);
|
||||
$this->increaseVar($statName, 1);
|
||||
@@ -786,9 +878,10 @@ class General implements iAction{
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
|
||||
public function getPreTurnExecuteTriggerList(General $general): ?GeneralTriggerCaller
|
||||
{
|
||||
$caller = new GeneralTriggerCaller();
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -796,9 +889,9 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
|
||||
if(!$iObj){
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -807,8 +900,9 @@ class General implements iAction{
|
||||
|
||||
return $caller;
|
||||
}
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
|
||||
foreach(array_merge([
|
||||
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux = null): float
|
||||
{
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -816,8 +910,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -826,9 +920,10 @@ class General implements iAction{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux=null){
|
||||
public function onCalcStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
//xxx: $general?
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -836,8 +931,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -846,9 +941,10 @@ class General implements iAction{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcOpposeStat(General $general, string $statName, $value, $aux=null){
|
||||
public function onCalcOpposeStat(General $general, string $statName, $value, $aux = null)
|
||||
{
|
||||
//xxx: $general?
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -856,8 +952,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -866,8 +962,9 @@ class General implements iAction{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcStrategic(string $turnType, string $varType, $value){
|
||||
foreach(array_merge([
|
||||
public function onCalcStrategic(string $turnType, string $varType, $value)
|
||||
{
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -875,8 +972,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -885,8 +982,9 @@ class General implements iAction{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function onCalcNationalIncome(string $type, $amount){
|
||||
foreach(array_merge([
|
||||
public function onCalcNationalIncome(string $type, $amount)
|
||||
{
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -894,8 +992,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -904,11 +1002,12 @@ class General implements iAction{
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function getWarPowerMultiplier(WarUnit $unit):array{
|
||||
public function getWarPowerMultiplier(WarUnit $unit): array
|
||||
{
|
||||
//xxx:$unit
|
||||
$att = 1;
|
||||
$def = 1;
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -916,8 +1015,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -927,9 +1026,10 @@ class General implements iAction{
|
||||
}
|
||||
return [$att, $def];
|
||||
}
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
public function getBattleInitSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
$caller = new WarUnitTriggerCaller();
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -937,8 +1037,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -947,7 +1047,8 @@ class General implements iAction{
|
||||
|
||||
return $caller;
|
||||
}
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
|
||||
public function getBattlePhaseSkillTriggerList(WarUnit $unit): ?WarUnitTriggerCaller
|
||||
{
|
||||
$caller = new WarUnitTriggerCaller(
|
||||
new WarUnitTrigger\che_필살시도($unit),
|
||||
new WarUnitTrigger\che_필살발동($unit),
|
||||
@@ -957,7 +1058,7 @@ class General implements iAction{
|
||||
new WarUnitTrigger\che_계략발동($unit),
|
||||
new WarUnitTrigger\che_계략실패($unit)
|
||||
);
|
||||
foreach(array_merge([
|
||||
foreach (array_merge([
|
||||
$this->nationType,
|
||||
$this->officerLevelObj,
|
||||
$this->specialDomesticObj,
|
||||
@@ -965,8 +1066,8 @@ class General implements iAction{
|
||||
$this->personalityObj,
|
||||
$this->getCrewTypeObj(),
|
||||
$this->inheritBuffObj,
|
||||
], $this->itemObjs) as $iObj){
|
||||
if(!$iObj){
|
||||
], $this->itemObjs) as $iObj) {
|
||||
if (!$iObj) {
|
||||
continue;
|
||||
}
|
||||
/** @var iAction $iObj */
|
||||
@@ -976,12 +1077,13 @@ class General implements iAction{
|
||||
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'];
|
||||
$defaultEventColumn = [
|
||||
'no', 'name', 'owner', 'city', 'nation', 'officer_level', 'officer_city',
|
||||
'special', 'special2', 'personal',
|
||||
'horse', 'weapon', 'book', 'item', 'last_turn'
|
||||
'horse', 'weapon', 'book', 'item', 'last_turn', 'aux',
|
||||
];
|
||||
$fullColumn = [
|
||||
'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',
|
||||
];
|
||||
|
||||
if($reqColumns === null){
|
||||
if ($reqColumns === null) {
|
||||
return [$fullColumn, array_keys(static::RANK_COLUMN)];
|
||||
}
|
||||
|
||||
$rankColumn = [];
|
||||
$subColumn = [];
|
||||
foreach($reqColumns as $column){
|
||||
if(key_exists($column, static::RANK_COLUMN)){
|
||||
foreach ($reqColumns as $column) {
|
||||
if (key_exists($column, static::RANK_COLUMN)) {
|
||||
$rankColumn[] = $column;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$subColumn[] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
if($constructMode > 1){
|
||||
if ($constructMode > 1) {
|
||||
return [array_unique(array_merge($defaultEventColumn, $subColumn)), $rankColumn];
|
||||
}
|
||||
|
||||
@@ -1023,31 +1124,30 @@ class General implements iAction{
|
||||
* @return \sammo\General[]
|
||||
* @throws MustNotBeReachedException
|
||||
*/
|
||||
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column=null, int $constructMode=2):array{
|
||||
if($generalIDList === []){
|
||||
static public function createGeneralObjListFromDB(?array $generalIDList, ?array $column = null, int $constructMode = 2): array
|
||||
{
|
||||
if ($generalIDList === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
if($constructMode > 0){
|
||||
if ($constructMode > 0) {
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$year = null;
|
||||
$month = null;
|
||||
}
|
||||
|
||||
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
|
||||
|
||||
if($generalIDList === null){
|
||||
if ($generalIDList === null) {
|
||||
$rawGenerals = Util::convertArrayToDict(
|
||||
$db->query('SELECT %l FROM general WHERE 1', Util::formatListOfBackticks($column)),
|
||||
'no'
|
||||
);
|
||||
$generalIDList = array_keys($rawGenerals);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$rawGenerals = Util::convertArrayToDict(
|
||||
$db->query('SELECT %l FROM general WHERE no IN %li', Util::formatListOfBackticks($column), $generalIDList),
|
||||
'no'
|
||||
@@ -1056,14 +1156,14 @@ class General implements iAction{
|
||||
|
||||
|
||||
$rawRanks = [];
|
||||
if($rankColumn){
|
||||
if ($rankColumn) {
|
||||
$rawValue = $db->queryAllLists(
|
||||
'SELECT `general_id`, `type`, `value` FROM rank_data WHERE general_id IN %li AND `type` IN %ls',
|
||||
$generalIDList,
|
||||
$rankColumn
|
||||
);
|
||||
foreach($rawValue as [$generalID, $rankType, $rankValue]){
|
||||
if(!key_exists($generalID, $rawRanks)){
|
||||
foreach ($rawValue as [$generalID, $rankType, $rankValue]) {
|
||||
if (!key_exists($generalID, $rawRanks)) {
|
||||
$rawRanks[$generalID] = [];
|
||||
}
|
||||
$rawRanks[$generalID][$rankType] = $rankValue;
|
||||
@@ -1071,27 +1171,27 @@ class General implements iAction{
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach($generalIDList as $generalID){
|
||||
if(!key_exists($generalID, $rawGenerals)){
|
||||
foreach ($generalIDList as $generalID) {
|
||||
if (!key_exists($generalID, $rawGenerals)) {
|
||||
$result[$generalID] = new DummyGeneral($constructMode > 0);
|
||||
continue;
|
||||
}
|
||||
if(key_exists($generalID, $rawRanks) && count($rawRanks[$generalID]??[]) !== count($rankColumn)){
|
||||
throw new \RuntimeException('column의 수가 일치하지 않음 : '.$generalID);
|
||||
if (key_exists($generalID, $rawRanks) && count($rawRanks[$generalID] ?? []) !== count($rankColumn)) {
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
if($constructMode > 0){
|
||||
if ($constructMode > 0) {
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$year = null;
|
||||
$month = null;
|
||||
}
|
||||
@@ -1099,14 +1199,14 @@ class General implements iAction{
|
||||
[$column, $rankColumn] = static::mergeQueryColumn($column, $constructMode);
|
||||
|
||||
$rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID);
|
||||
if(!$rawGeneral){
|
||||
if (!$rawGeneral) {
|
||||
return new DummyGeneral($constructMode > 0);
|
||||
}
|
||||
|
||||
$rawRankValues = [];
|
||||
if($rankColumn){
|
||||
if ($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;
|
||||
}
|
||||
}
|
||||
@@ -1123,21 +1223,22 @@ class General implements iAction{
|
||||
* @param array $env
|
||||
* @return GeneralCommand[]
|
||||
*/
|
||||
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env){
|
||||
if(!$generalList){
|
||||
static public function getReservedTurnByGeneralList(array $generalList, int $turnIdx, array $env)
|
||||
{
|
||||
if (!$generalList) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$generalIDList = array_map(function(General $general){
|
||||
$generalIDList = array_map(function (General $general) {
|
||||
return $general->getID();
|
||||
}, $generalList);
|
||||
|
||||
$db = DB::db();
|
||||
$result = [];
|
||||
$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();
|
||||
if(!key_exists($generalID, $rawCmds)){
|
||||
if (!key_exists($generalID, $rawCmds)) {
|
||||
$result[$generalID] = buildGeneralCommandClass(null, $general, $env);
|
||||
continue;
|
||||
}
|
||||
@@ -1154,21 +1255,22 @@ class General implements iAction{
|
||||
* @param array $env
|
||||
* @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같은게 있어야하지 않을까?
|
||||
if(!$generalList){
|
||||
if (!$generalList) {
|
||||
return [];
|
||||
}
|
||||
|
||||
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){
|
||||
throw new \OutOfRangeException('$turnIdxTo 범위 초과'.$turnIdxTo);
|
||||
if ($turnIdxTo <= $turnIdxFrom || GameConst::$maxTurn < $turnIdxTo) {
|
||||
throw new \OutOfRangeException('$turnIdxTo 범위 초과' . $turnIdxTo);
|
||||
}
|
||||
|
||||
$generalIDList = array_map(function(General $general){
|
||||
$generalIDList = array_map(function (General $general) {
|
||||
return $general->getID();
|
||||
}, $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);
|
||||
$orderedRawCmds = [];
|
||||
foreach($rawCmds as $rawCmd){
|
||||
foreach ($rawCmds as $rawCmd) {
|
||||
$generalID = $rawCmd['general_id'];
|
||||
$turnIdx = $rawCmd['turn_idx'];
|
||||
if(!key_exists($generalID, $orderedRawCmds)){
|
||||
if (!key_exists($generalID, $orderedRawCmds)) {
|
||||
$orderedRawCmds[$generalID] = [];
|
||||
}
|
||||
$orderedRawCmds[$generalID][$turnIdx] = $rawCmd;
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach($generalList as $general){
|
||||
foreach ($generalList as $general) {
|
||||
$generalID = $general->getID();
|
||||
$result[$generalID] = [];
|
||||
if(!key_exists($generalID, $orderedRawCmds)){
|
||||
foreach(Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx){
|
||||
if (!key_exists($generalID, $orderedRawCmds)) {
|
||||
foreach (Util::range($turnIdxFrom, $turnIdxTo) as $turnIdx) {
|
||||
$result[$generalID][$turnIdx] = buildGeneralCommandClass(null, $general, $env);
|
||||
}
|
||||
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']));
|
||||
}
|
||||
}
|
||||
@@ -1205,109 +1307,113 @@ class General implements iAction{
|
||||
/**
|
||||
* @return int|float
|
||||
*/
|
||||
public function getInheritancePoint(string $key, &$aux=null, bool $forceCalc=false){
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
public function getInheritancePoint(string $key, &$aux = null, bool $forceCalc = false)
|
||||
{
|
||||
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
|
||||
if ($inheritType === null) {
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
if (!$ownerID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
if ($this->getVar('npc') != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
[$storeType, $multiplier,] = $inheritType;
|
||||
|
||||
$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}");
|
||||
[$value, $aux] = $inheritStor->getValue($key);
|
||||
return $value;
|
||||
}
|
||||
|
||||
if(is_array($storeType)){
|
||||
if (is_array($storeType)) {
|
||||
[$storSubType, $storSubKey] = $storeType;
|
||||
if($storSubType === 'rank'){
|
||||
if ($storSubType === 'rank') {
|
||||
return $this->getRankVar($storSubKey) * $multiplier;
|
||||
}
|
||||
if($storSubType === 'raw'){
|
||||
if ($storSubType === 'raw') {
|
||||
return $this->getVar($storSubKey) * $multiplier;
|
||||
}
|
||||
if($storSubType === 'aux'){
|
||||
return ($this->getAuxVar($storSubKey)??0) * $multiplier;
|
||||
if ($storSubType === 'aux') {
|
||||
return ($this->getAuxVar($storSubKey) ?? 0) * $multiplier;
|
||||
}
|
||||
throw new \InvalidArgumentException("{$storSubType}은 참조 할 수 없는 유산 세부키임");
|
||||
}
|
||||
|
||||
if($storeType !== false){
|
||||
if ($storeType !== false) {
|
||||
throw new \InvalidArgumentException("{$storeType}은 올바르지 않은 유산 키임");
|
||||
}
|
||||
|
||||
$extractFn = function(){ return [0, null];};
|
||||
switch($key){
|
||||
case 'dex':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$totalDex = 0;
|
||||
foreach(array_keys(GameUnitConst::allType()) as $armType){
|
||||
$totalDex += $this->getVar("dex{$armType}");
|
||||
}
|
||||
return [$totalDex * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
case 'betting':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$betWin = $this->getRankVar('betwin');
|
||||
$betWinRate = $this->getRankVar('betwingold')/max(1, $this->getRankVar('betgold'));
|
||||
$extractFn = function () {
|
||||
return [0, null];
|
||||
};
|
||||
switch ($key) {
|
||||
case 'dex':
|
||||
$extractFn = function () use ($multiplier) {
|
||||
$totalDex = 0;
|
||||
foreach (array_keys(GameUnitConst::allType()) as $armType) {
|
||||
$totalDex += $this->getVar("dex{$armType}");
|
||||
}
|
||||
return [$totalDex * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
case 'betting':
|
||||
$extractFn = function () use ($multiplier) {
|
||||
$betWin = $this->getRankVar('betwin');
|
||||
$betWinRate = $this->getRankVar('betwingold') / max(1, $this->getRankVar('betgold'));
|
||||
|
||||
return [$betWin * $multiplier * pow($betWinRate, 2), null];
|
||||
};
|
||||
break;
|
||||
case 'max_belong':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong')??0);
|
||||
return [$maxBelong * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
|
||||
return [$betWin * $multiplier * pow($betWinRate, 2), null];
|
||||
};
|
||||
break;
|
||||
case 'max_belong':
|
||||
$extractFn = function () use ($multiplier) {
|
||||
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong') ?? 0);
|
||||
return [$maxBelong * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
|
||||
}
|
||||
|
||||
[$value, $aux] = ($extractFn)();
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function setInheritancePoint(string $key, $value, $aux=null){
|
||||
if(!is_int($value) && !is_float($value)){
|
||||
public function setInheritancePoint(string $key, $value, $aux = null)
|
||||
{
|
||||
if (!is_int($value) && !is_float($value)) {
|
||||
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
|
||||
}
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
|
||||
if ($inheritType === null) {
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
if($storeType !== true){
|
||||
[$storeType, $multiplier,] = $inheritType;
|
||||
if ($storeType !== true) {
|
||||
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
|
||||
}
|
||||
if($multiplier != 1 && $value != 0){
|
||||
if ($multiplier != 1 && $value != 0) {
|
||||
throw new \InvalidArgumentException("{$key}는 1:1 유산 포인트가 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
if (!$ownerID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
if ($this->getVar('npc') != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
if($gameStor->isunited != 0){
|
||||
if ($gameStor->isunited != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1315,39 +1421,40 @@ class General implements iAction{
|
||||
$inheritStor->setValue($key, [$value, $aux]);
|
||||
}
|
||||
|
||||
public function increaseInheritancePoint(string $key, $value, $aux=null){
|
||||
if(!is_int($value) && !is_float($value)){
|
||||
public function increaseInheritancePoint(string $key, $value, $aux = null)
|
||||
{
|
||||
if (!is_int($value) && !is_float($value)) {
|
||||
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
|
||||
}
|
||||
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
$inheritType = static::INHERITANCE_KEY[$key] ?? null;
|
||||
if ($inheritType === null) {
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
if($storeType !== true){
|
||||
[$storeType, $multiplier,] = $inheritType;
|
||||
if ($storeType !== true) {
|
||||
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
if (!$ownerID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
if ($this->getVar('npc') != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
if($gameStor->isunited != 0){
|
||||
if ($gameStor->isunited != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
@@ -1355,22 +1462,23 @@ class General implements iAction{
|
||||
$inheritStor->setValue($key, [$newValue, $aux]);
|
||||
}
|
||||
|
||||
public function mergeTotalInheritancePoint(){
|
||||
public function mergeTotalInheritancePoint()
|
||||
{
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
if (!$ownerID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
if ($this->getVar('npc') != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||
$inheritStor->cacheAll();
|
||||
foreach(static::INHERITANCE_KEY as $key=>[$storType, ,]){
|
||||
foreach (static::INHERITANCE_KEY as $key => [$storType,,]) {
|
||||
$aux = null;
|
||||
$point = $this->getInheritancePoint($key, $aux, true);
|
||||
if($storType === true){
|
||||
if ($storType === true) {
|
||||
continue;
|
||||
}
|
||||
$inheritStor->setValue($key, [$point, $aux]);
|
||||
@@ -1383,4 +1491,4 @@ class General implements iAction{
|
||||
$month = $gameStor->month;
|
||||
$oldInheritStor->setValue("{$serverID}_{$ownerID}_{$this->getID()}_{$year}_{$month}", $inheritStor->getAll(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+771
-789
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ class che_도시치료 extends BaseGeneralTrigger{
|
||||
/** @var \sammo\General $general */
|
||||
$general = $this->object;
|
||||
$logger = $general->getLogger();
|
||||
|
||||
|
||||
if($general->getVar('injury') > 0){
|
||||
$general->updateVar('injury', 0);
|
||||
$general->activateSkill('pre.부상경감', 'pre.치료');
|
||||
@@ -25,8 +25,8 @@ class che_도시치료 extends BaseGeneralTrigger{
|
||||
$db = DB::db();
|
||||
|
||||
$patients = $db->queryAllLists(
|
||||
'SELECT no,name,nation FROM general WHERE city=%i AND injury > 10 AND no != %i',
|
||||
$general->getCityID(),
|
||||
'SELECT no,name,nation FROM general WHERE city=%i AND injury > 10 AND no != %i',
|
||||
$general->getCityID(),
|
||||
$general->getID()
|
||||
);
|
||||
|
||||
@@ -56,7 +56,7 @@ class che_도시치료 extends BaseGeneralTrigger{
|
||||
return $env;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(count($cureList) == 1){
|
||||
$josaUl = JosaUtil::pick($curedPatientName, "을");
|
||||
$logger->pushGeneralActionLog("<C>의술</>을 펼쳐 도시의 장수 <Y>{$curedPatientName}</>{$josaUl} 치료합니다!", ActionLogger::PLAIN);
|
||||
|
||||
@@ -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'];
|
||||
if ($pickType == '무') {
|
||||
$dexVal = Util::choiceRandom([
|
||||
@@ -681,7 +681,7 @@ class GeneralBuilder{
|
||||
'turntime'=>$turntime,
|
||||
'killturn'=>$killturn,
|
||||
'age'=>$age,
|
||||
'belong'=>1,
|
||||
'belong'=>0,
|
||||
'personal'=>$this->ego,
|
||||
'special'=>$this->specialDomestic,
|
||||
'specage'=>$this->specAge,
|
||||
|
||||
@@ -86,7 +86,7 @@ class SpecialityHelper{
|
||||
if($leadership > GameConst::$chiefStatMin){
|
||||
$myCond |= self::STAT_LEADERSHIP;
|
||||
}
|
||||
|
||||
|
||||
if($strength >= $intel * 0.95 && $strength > GameConst::$chiefStatMin){
|
||||
$myCond |= self::STAT_STRENGTH;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class SpecialityHelper{
|
||||
}
|
||||
if($strength < GameConst::$chiefStatMin){
|
||||
$myCond |= self::STAT_NOT_STRENGTH;
|
||||
}
|
||||
}
|
||||
if($intel < GameConst::$chiefStatMin){
|
||||
$myCond |= self::STAT_NOT_INTEL;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class SpecialityHelper{
|
||||
$myCond |= self::STAT_INTEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $myCond;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ class SpecialityHelper{
|
||||
$specialObj = buildGeneralSpecialWarClass(GameConst::$defaultSpecialWar);
|
||||
$result[GameConst::$defaultSpecialWar] = $specialObj;
|
||||
}
|
||||
|
||||
|
||||
foreach(GameConst::$availableSpecialWar as $specialID){
|
||||
$specialObj = buildGeneralSpecialWarClass($specialID);
|
||||
$result[$specialID] = $specialObj;
|
||||
@@ -220,7 +220,7 @@ class SpecialityHelper{
|
||||
if(in_array($specialID, $prevSpecials)){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($weightType === static::WEIGHT_PERCENT){
|
||||
$pAbs[$specialID] = $weight;
|
||||
@@ -229,7 +229,7 @@ class SpecialityHelper{
|
||||
$pRel[$specialID] = $weight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($pAbs){
|
||||
if($pRel){
|
||||
$pAbs[0] = max(0, 100 - array_sum($pAbs));
|
||||
@@ -280,7 +280,7 @@ class SpecialityHelper{
|
||||
if(in_array($specialID, $prevSpecials)){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($cond & self::REQ_DEXTERITY){
|
||||
$reqDex[$specialID] = $weight;
|
||||
@@ -296,7 +296,7 @@ class SpecialityHelper{
|
||||
if($reqDex){
|
||||
return Util::choiceRandomUsingWeight($reqDex);
|
||||
}
|
||||
|
||||
|
||||
if($pAbs){
|
||||
if($pRel){
|
||||
$pAbs[0] = max(0, 100 - array_sum($pAbs));
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,9 @@ class WarUnitGeneral extends WarUnit
|
||||
$semiTurn = $general->getTurnTime();
|
||||
} else if ($oppose !== null) {
|
||||
$semiTurn = $oppose->getGeneral()->getTurnTime();
|
||||
} else {
|
||||
LogText("WarUnitGeneral::setOppose", "defender인데 oppose가 null {$general->getID()}, {$general->getTurnTime()}");
|
||||
$semiTurn = $general->getTurnTime();
|
||||
}
|
||||
$phase = $this->getRealPhase();
|
||||
$semiTurn = substr($semiTurn, 0, strlen($semiTurn) - 2);
|
||||
@@ -205,7 +208,7 @@ class WarUnitGeneral extends WarUnit
|
||||
if ($this->isAttacker) {
|
||||
if ($officerLevel == 12) {
|
||||
$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;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -14,6 +14,7 @@ class che_반계시도 extends BaseWarUnitTrigger{
|
||||
|
||||
public function __construct(WarUnit $unit, int $raiseType = 0, float $prob = 0.4){
|
||||
$this->object = $unit;
|
||||
$this->raiseType = $raiseType;
|
||||
$this->prob = $prob;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class che_전투치료발동 extends BaseWarUnitTrigger{
|
||||
}
|
||||
$selfEnv['치료발동'] = true;
|
||||
|
||||
$oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <C>치료</>했다!", ActionLogger::PLAIN);
|
||||
$oppose->getLogger()->pushGeneralBattleDetailLog("상대가 <R>치료</>했다!", ActionLogger::PLAIN);
|
||||
$self->getLogger()->pushGeneralBattleDetailLog("<C>치료</>했다!", ActionLogger::PLAIN);
|
||||
|
||||
$oppose->multiplyWarPowerMultiply(0.5);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["CreateManyNPC", 10, 10],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["CreateManyNPC", 10, 10],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["CreateManyNPC", 10, 10],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"title": "【가상모드19b】 진유저무쌍! (대형 지도)",
|
||||
"startYear": 180,
|
||||
"history": [
|
||||
"<C>●</>180년 1월:<L><b>【가상모드19ㅠ】</b>진유저무쌍! (대형 지도)</>",
|
||||
"<C>●</>180년 1월:<L><b>【가상모드19】</b>진유저무쌍! (대형 지도)</>",
|
||||
"<C>●</>180년 1월:<L><b>【이벤트】</b></>고대장수 다 덤벼라! 유저가 최강이다!"
|
||||
],
|
||||
"stat": {
|
||||
|
||||
@@ -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"]
|
||||
]
|
||||
]
|
||||
|
||||
}
|
||||
@@ -9,26 +9,26 @@
|
||||
"const": {
|
||||
"joinRuinedNPCProp":0,
|
||||
"availableSpecialWar":[
|
||||
"che_귀병", "che_신산", "che_환술", "che_집중", "che_신중", "che_반계",
|
||||
"che_귀병", "che_신산", "che_환술", "che_집중", "che_신중", "che_반계",
|
||||
"che_보병", "che_궁병", "che_기병", "che_공성",
|
||||
"che_돌격", "che_무쌍", "che_위압",
|
||||
"che_돌격", "che_무쌍", "che_위압",
|
||||
"che_저격", "che_필살", "che_징병", "che_의술", "che_격노", "che_척사"
|
||||
],
|
||||
"allItems":{
|
||||
"horse":{
|
||||
"che_명마_01_노기":0, "che_명마_02_조랑":0, "che_명마_03_노새":0,
|
||||
"che_명마_04_나귀":0, "che_명마_05_갈색마":0, "che_명마_06_흑색마":0,
|
||||
|
||||
"che_명마_07_백마":2, "che_명마_07_기주마":2,
|
||||
"che_명마_04_나귀":0, "che_명마_05_갈색마":0, "che_명마_06_흑색마":0,
|
||||
|
||||
"che_명마_07_백마":2, "che_명마_07_기주마":2,
|
||||
"che_명마_08_양주마":2, "che_명마_09_과하마":2,
|
||||
"che_명마_10_대완마":2, "che_명마_11_서량마":2,
|
||||
"che_명마_10_대완마":2, "che_명마_11_서량마":2,
|
||||
"che_명마_12_사륜거":2, "che_명마_13_절영":1, "che_명마_13_적로":1,
|
||||
"che_명마_14_적란마":1, "che_명마_14_조황비전":1, "che_명마_15_한혈마":1, "che_명마_15_적토마":1
|
||||
},
|
||||
"weapon":{
|
||||
"che_무기_01_단도":0, "che_무기_02_단궁":0, "che_무기_03_단극":0,
|
||||
"che_무기_04_목검":0, "che_무기_05_죽창":0, "che_무기_06_소부":0,
|
||||
|
||||
|
||||
"che_무기_07_동추":1, "che_무기_07_철편":1, "che_무기_07_철쇄":1, "che_무기_07_맥궁":1,
|
||||
"che_무기_08_유성추":1, "che_무기_08_철질여골":1, "che_무기_09_쌍철극":1, "che_무기_09_동호비궁":1,
|
||||
"che_무기_10_삼첨도":1, "che_무기_10_대부":1, "che_무기_11_고정도":1, "che_무기_11_이광궁":1,
|
||||
@@ -37,18 +37,18 @@
|
||||
},
|
||||
"book":{
|
||||
"che_서적_01_효경전":0, "che_서적_02_회남자":0, "che_서적_03_변도론":0,
|
||||
"che_서적_04_건상역주":0, "che_서적_05_여씨춘추":0, "che_서적_06_사민월령":0,
|
||||
|
||||
"che_서적_04_건상역주":0, "che_서적_05_여씨춘추":0, "che_서적_06_사민월령":0,
|
||||
|
||||
"che_서적_07_위료자":1, "che_서적_07_사마법":1, "che_서적_07_한서":1, "che_서적_07_논어":1,
|
||||
"che_서적_08_전론":1, "che_서적_08_사기":1, "che_서적_09_장자":1, "che_서적_09_역경":1,
|
||||
"che_서적_10_시경":1, "che_서적_10_구국론":1, "che_서적_11_상군서":1, "che_서적_11_춘추전":1,
|
||||
"che_서적_12_산해경":1, "che_서적_12_맹덕신서":1, "che_서적_13_관자":1, "che_서적_13_병법24편":1,
|
||||
"che_서적_10_시경":1, "che_서적_10_구국론":1, "che_서적_11_상군서":1, "che_서적_11_춘추전":1,
|
||||
"che_서적_12_산해경":1, "che_서적_12_맹덕신서":1, "che_서적_13_관자":1, "che_서적_13_병법24편":1,
|
||||
"che_서적_14_한비자":1, "che_서적_14_오자병법":1, "che_서적_15_노자":1, "che_서적_15_손자병법":1
|
||||
},
|
||||
"item":{
|
||||
"che_치료_환약":0, "che_저격_수극":0, "che_사기_탁주":0,
|
||||
"che_훈련_청주":0, "che_계략_이추":0, "che_계략_향낭":0,
|
||||
|
||||
|
||||
"event_전투특기_격노":0, "event_전투특기_공성":0, "event_전투특기_궁병":0,
|
||||
"event_전투특기_귀병":0, "event_전투특기_기병":0, "event_전투특기_돌격":0, "event_전투특기_무쌍":0,
|
||||
"event_전투특기_반계":0, "event_전투특기_보병":0, "event_전투특기_신산":0, "event_전투특기_신중":0,
|
||||
@@ -60,7 +60,7 @@
|
||||
"events":[
|
||||
[
|
||||
["Date", "==", null, 12],
|
||||
["CreateManyNPC", 30],
|
||||
["CreateManyNPC", 10, 10],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"events": [
|
||||
[
|
||||
["Date", "==", null, 12],
|
||||
["CreateManyNPC", 100],
|
||||
["CreateManyNPC", 100, 0],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<div class="buttonPlate bg1">
|
||||
<div>
|
||||
<a href="a_status.php" target="_blank"><button type="button" class="toolbarButton">세력도</button></a>
|
||||
<a href="a_kingdomList.php" target="_blank"><button type="button" class="toolbarButton">세력일람</button></a>
|
||||
<a href="a_genList.php" target="_blank"><button type="button" class="toolbarButton">장수일람</button></a>
|
||||
<a href="a_bestGeneral.php" target="_blank"><button type="button" class="toolbarButton">명장일람</button></a>
|
||||
<a href="a_history.php" target="_blank"><button type="button" class="toolbarButton">연감</button></a>
|
||||
<a href="a_hallOfFame.php" target="_blank"><button type="button" class="toolbarButton">명예의전당</button></a>
|
||||
<a href="a_emperior.php" target="_blank"><button type="button" class="toolbarButton">왕조일람</button></a>
|
||||
<a href="a_traffic.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" class="open-window"><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" class="open-window"><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" class="open-window"><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" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
|
||||
</div>
|
||||
<div>
|
||||
<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/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="<?=$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>
|
||||
|
||||
@@ -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_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='b_genList.php' target='_blank'><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_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' 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_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_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_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='b_myPage.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 정보&설정</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_betting.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' class="open-window"><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>베 팅 장</button></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
+5
-5
@@ -149,7 +149,7 @@
|
||||
<div class="col col-md-1 col-3">
|
||||
<label
|
||||
><input type="checkbox" v-model="displayInherit" />{{
|
||||
displayTable ? "숨기기" : "보이기"
|
||||
displayInherit ? "숨기기" : "보이기"
|
||||
}}</label
|
||||
>
|
||||
</div>
|
||||
@@ -305,7 +305,7 @@ import {
|
||||
CTableRow,
|
||||
CTableHeaderCell,
|
||||
CTableDataCell,
|
||||
} from "@coreui/vue/src";
|
||||
} from "@coreui/vue/src/components/table";
|
||||
import { getIconPath } from "./util/getIconPath";
|
||||
import { isBrightColor } from "./util/isBrightColor";
|
||||
import {
|
||||
@@ -458,21 +458,21 @@ export default defineComponent({
|
||||
},
|
||||
inheritTurnTimeMinute(newValue: number) {
|
||||
if (!this.inheritTurnTimeSet) {
|
||||
this.args.inheritTurntime = 0;
|
||||
this.args.inheritTurntime = undefined;
|
||||
return;
|
||||
}
|
||||
this.args.inheritTurntime = newValue * 60 + this.inheritTurnTimeSecond;
|
||||
},
|
||||
inheritTurnTimeSecond(newValue: number) {
|
||||
if (!this.inheritTurnTimeSet) {
|
||||
this.args.inheritTurntime = 0;
|
||||
this.args.inheritTurntime = undefined;
|
||||
return;
|
||||
}
|
||||
this.args.inheritTurntime = this.inheritTurnTimeMinute * 60 + newValue;
|
||||
},
|
||||
inheritTurnTimeSet(newValue: boolean) {
|
||||
if (!newValue) {
|
||||
this.args.inheritTurntime = 0;
|
||||
this.args.inheritTurntime = undefined;
|
||||
return;
|
||||
}
|
||||
this.args.inheritTurntime =
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<NumberInputWithInfo
|
||||
v-model="nationPolicy.reqHumanWarUrgentRice"
|
||||
:step="100"
|
||||
title="유저전투장 긴급포상 금"
|
||||
title="유저전투장 긴급포상 쌀"
|
||||
>유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br />0이면
|
||||
기본 병종으로 {{ (defaultStatMax * 100).toLocaleString() }} * 6명 사살
|
||||
가능한 쌀을 기준으로 하며, 그 수치는 현재
|
||||
|
||||
@@ -893,7 +893,7 @@ $(function ($) {
|
||||
}
|
||||
showBattleResult(result);
|
||||
|
||||
}, function (result) {
|
||||
}, function () {
|
||||
alert('전투 개시 실패!');
|
||||
});
|
||||
}
|
||||
@@ -933,7 +933,7 @@ $(function ($) {
|
||||
}
|
||||
reorderDefender(result.order);
|
||||
|
||||
}, function (result) {
|
||||
}, function () {
|
||||
alert('재정렬 실패!');
|
||||
});
|
||||
}
|
||||
@@ -968,7 +968,7 @@ $(function ($) {
|
||||
|
||||
});
|
||||
|
||||
$('#importModal').on('show.bs.modal', function (e) {
|
||||
$('#importModal').on('show.bs.modal', function () {
|
||||
if (!initGeneralList) {
|
||||
const $list = $('#modalSelector');
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"currentCity": "currentCity.ts",
|
||||
"hallOfFame": "hallOfFame.ts",
|
||||
"history": "history.ts",
|
||||
"join": "legacy/join.ts",
|
||||
"select_general_from_pool": "select_general_from_pool.ts",
|
||||
"extKingdoms": "extKingdoms.ts",
|
||||
"common": "common_deprecated.ts"
|
||||
|
||||
+127
-10
@@ -1,7 +1,7 @@
|
||||
import $ from 'jquery';
|
||||
import '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 { JQValidateForm, NamedRules } from '../util/jqValidateForm';
|
||||
import axios from 'axios';
|
||||
@@ -11,9 +11,12 @@ import { unwrap_any } from '../util/unwrap_any';
|
||||
import { sha512 } from 'js-sha512';
|
||||
import { unwrap } from '../util/unwrap';
|
||||
import { InvalidResponse } from '../defs';
|
||||
import internal from 'stream';
|
||||
import { delay } from '../util/delay';
|
||||
|
||||
type LoginResponse = {
|
||||
result: true,
|
||||
nextToken: [number, string] | undefined,
|
||||
} | {
|
||||
result: false,
|
||||
reqOTP: boolean,
|
||||
@@ -29,6 +32,19 @@ type OTPResponse = {
|
||||
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 {
|
||||
interface Window {
|
||||
getOAuthToken: (mode: string, scope_list: string[]) => void;
|
||||
@@ -41,6 +57,92 @@ declare const kakao_oauth_redirect_uri: string;
|
||||
|
||||
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) {
|
||||
if (mode === undefined) {
|
||||
mode = 'login';
|
||||
@@ -115,6 +217,9 @@ async function doLoginUsingOAuth() {
|
||||
}
|
||||
|
||||
if (result.result) {
|
||||
if (result.nextToken) {
|
||||
regNextToken(result.nextToken);
|
||||
}
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
@@ -156,9 +261,16 @@ function postOAuthResult(mode: string) {
|
||||
window.postOAuthResult = postOAuthResult;
|
||||
|
||||
|
||||
$(function ($) {
|
||||
$(async function ($) {
|
||||
setAxiosXMLHttpRequest();
|
||||
|
||||
//로그인 먼저 해볼 것
|
||||
if(getToken()){
|
||||
void tryAutoLogin();
|
||||
await delay(100);
|
||||
}
|
||||
|
||||
|
||||
type LoginFormType = {
|
||||
username: string,
|
||||
password: string,
|
||||
@@ -194,13 +306,16 @@ $(function ($) {
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_login.php',
|
||||
url: 'api.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
})
|
||||
data: {
|
||||
path: ["Login", "LoginByID"],
|
||||
args: {
|
||||
username: values.username,
|
||||
password: hash_pw,
|
||||
}
|
||||
}
|
||||
});
|
||||
result = response.data;
|
||||
}
|
||||
@@ -212,6 +327,9 @@ $(function ($) {
|
||||
|
||||
|
||||
if (result.result) {
|
||||
if (result.nextToken) {
|
||||
regNextToken(result.nextToken);
|
||||
}
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
@@ -268,12 +386,11 @@ $(function ($) {
|
||||
getOAuthToken('change_pw', 'talk_message');
|
||||
});
|
||||
|
||||
$('#btn_kakao_login').on('click', function(e){
|
||||
$('#btn_kakao_login').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
getOAuthToken('login', ['account_email','talk_message']);
|
||||
getOAuthToken('login', ['account_email', 'talk_message']);
|
||||
})
|
||||
|
||||
|
||||
//TODO: 모바일에서 크기 비례 지도 다시 띄우기?
|
||||
/*
|
||||
if (document.body.clientWidth < 700) {
|
||||
|
||||
+2
-3
@@ -1,5 +1,4 @@
|
||||
import { template } from "lodash";
|
||||
import { NationPolicy, NPCChiefActions, NPCGeneralActions } from "./defs";
|
||||
import { NPCChiefActions, NPCGeneralActions } from "./defs";
|
||||
|
||||
export const NPCPriorityBtnHelpMessage: {
|
||||
[v in NPCChiefActions | NPCGeneralActions]: string;
|
||||
@@ -34,7 +33,7 @@ export const NPCPriorityBtnHelpMessage: {
|
||||
NPC후방발령:
|
||||
"NPC전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.",
|
||||
NPC포상:
|
||||
"금/쌀이 부족한 유저장에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.",
|
||||
"금/쌀이 부족한 NPC에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.",
|
||||
NPC전방발령:
|
||||
"후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.",
|
||||
유저장내정발령:
|
||||
|
||||
+30
-6
@@ -3,7 +3,12 @@
|
||||
<div
|
||||
id="container"
|
||||
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">
|
||||
<template v-for="(text, key) in inheritanceViewText" :key="key">
|
||||
@@ -235,6 +240,20 @@
|
||||
</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>
|
||||
</template>
|
||||
|
||||
@@ -263,6 +282,14 @@ type InheritanceType =
|
||||
|
||||
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>;
|
||||
|
||||
const inheritanceViewText: Record<
|
||||
@@ -442,6 +469,7 @@ export default defineComponent({
|
||||
availableSpecialWar,
|
||||
availableUnique,
|
||||
specificUniqueAmount: inheritActionCost.minSpecificUnique,
|
||||
lastInheritPointLogs,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -617,11 +645,7 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
//TODO: JosaUtil
|
||||
if (
|
||||
!confirm(
|
||||
`${amount} 포인트로 ${uniqueName}(을)를 입찰하겠습니까?`
|
||||
)
|
||||
) {
|
||||
if (!confirm(`${amount} 포인트로 ${uniqueName}(을)를 입찰하겠습니까?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -192,6 +192,19 @@ $(function ($) {
|
||||
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);
|
||||
reloadCommandList();
|
||||
activateFlip();
|
||||
|
||||
+1
-1
@@ -516,7 +516,7 @@ export async function reloadWorldMap(option: loadMapOption, drawTarget = '.world
|
||||
//터치스크린 탭
|
||||
|
||||
if (!option.neutralView && is_touch_device()) {
|
||||
$objs.on('touchstart', function (e) {
|
||||
$objs.on('touchstart', function () {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -171,6 +171,7 @@ $(function ($) {
|
||||
});
|
||||
|
||||
$('#set_my_setting').on('click', async function (e) {
|
||||
e.preventDefault();
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
@@ -186,6 +187,9 @@ $(function ($) {
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
if(!result.result){
|
||||
throw result.reason;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
|
||||
@@ -203,7 +203,7 @@ function printGenerals(value: NPCToken) {
|
||||
const time = Date.now() + value.pickMoreSeconds * 1000;
|
||||
$('#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;
|
||||
});
|
||||
|
||||
|
||||
+11
-8
@@ -17,7 +17,7 @@ $me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
$currentInheritBuff = [];
|
||||
foreach ($me->getAuxVar('inheritBuff')??[] as $buff => $buffLevel) {
|
||||
foreach ($me->getAuxVar('inheritBuff') ?? [] as $buff => $buffLevel) {
|
||||
if (!key_exists($buff, TriggerInheritBuff::BUFF_KEY_TEXT)) {
|
||||
continue;
|
||||
}
|
||||
@@ -43,15 +43,15 @@ foreach (GameConst::$availableSpecialWar as $specialWarKey) {
|
||||
}
|
||||
|
||||
$availableUnique = [];
|
||||
foreach (GameConst::$allItems as $subItems){
|
||||
foreach($subItems as $itemKey=>$amount){
|
||||
if($amount == 0){
|
||||
foreach (GameConst::$allItems as $subItems) {
|
||||
foreach ($subItems as $itemKey => $amount) {
|
||||
if ($amount == 0) {
|
||||
continue;
|
||||
}
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$availableUnique[$itemKey] = [
|
||||
'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;
|
||||
}
|
||||
|
||||
$resetTurnTimeLevel = $me->getAuxVar('inheritResetTurnTime') ?? 0;
|
||||
$resetSpecialWarLevel = $me->getAuxVar('inheritResetSpecialWar') ?? 0;
|
||||
$resetTurnTimeLevel = ($me->getAuxVar('inheritResetTurnTime') ?? -1) + 1;
|
||||
$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>
|
||||
<html>
|
||||
@@ -91,10 +93,11 @@ $resetSpecialWarLevel = $me->getAuxVar('inheritResetSpecialWar') ?? 0;
|
||||
'resetSpecialWar' => calcResetAttrPoint($resetSpecialWarLevel),
|
||||
'randomUnique' => GameConst::$inheritItemRandomPoint,
|
||||
'nextSpecial' => GameConst::$inheritSpecificSpecialPoint,
|
||||
'minSpecificUnique'=>GameConst::$inheritItemUniqueMinPoint,
|
||||
'minSpecificUnique' => GameConst::$inheritItemUniqueMinPoint,
|
||||
],
|
||||
'availableSpecialWar' => $avilableSpecialWar,
|
||||
'availableUnique' => $availableUnique,
|
||||
'lastInheritPointLogs' => $lastInheritPointLogs,
|
||||
]) ?>
|
||||
</head>
|
||||
|
||||
|
||||
-181
@@ -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
@@ -230,7 +230,7 @@ if ($server == $baseServerName) {
|
||||
__DIR__ . '/' . $server . '/d_setting/VersionGit.php',
|
||||
[
|
||||
'verionGit' => $version,
|
||||
'hash' => $hash
|
||||
'hash' => $gitHash
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
+123
-82
@@ -1,25 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
require(__DIR__.'/../vendor/autoload.php');
|
||||
require(__DIR__ . '/../vendor/autoload.php');
|
||||
require('lib.join.php');
|
||||
|
||||
|
||||
//TODO: KakaoOauth를 API로 정식으로 이동
|
||||
|
||||
WebUtil::requireAJAX();
|
||||
|
||||
use \kakao\Kakao_REST_API_Helper as Kakao_REST_API_Helper;
|
||||
|
||||
$RootDB = RootDB::db();
|
||||
$session = Session::getInstance();
|
||||
if($session->isLoggedIn()){
|
||||
if ($session->isLoggedIn()) {
|
||||
$session->logout();
|
||||
}
|
||||
|
||||
$canLogin = RootDB::db()->queryFirstField('SELECT `LOGIN` FROM `system` WHERE `NO` = 1');
|
||||
if($canLogin != 'Y'){
|
||||
if ($canLogin != 'Y') {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'현재는 로그인이 금지되어있습니다!',
|
||||
'noRetry'=>true
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '현재는 로그인이 금지되어있습니다!',
|
||||
'noRetry' => true
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -32,173 +37,209 @@ $refresh_token_expires = $session->refresh_token_expires;
|
||||
$email = $session->kaccount_email;
|
||||
|
||||
|
||||
if(!$access_token || !$expires){
|
||||
if (!$access_token || !$expires) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오로그인이 이루어지지 않았습니다.'
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오로그인이 이루어지지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
//TODO: join과 login의 동작이 비슷하다. helper class로 묶자.
|
||||
$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([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'로그인 토큰 만료.'.$refresh_token_expires.' 다시 카카오로그인을 수행해주세요.'
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '로그인 토큰 만료.' . $refresh_token_expires . ' 다시 카카오로그인을 수행해주세요.'
|
||||
]);
|
||||
}
|
||||
|
||||
if($expires < $now){
|
||||
if ($expires < $now) {
|
||||
$session->kaccount_email = null;
|
||||
$email = null;
|
||||
|
||||
$result = $restAPI->refresh_access_token($refresh_token);
|
||||
if(!isset($refresh_token)){
|
||||
if (!isset($refresh_token)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다'
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오 로그인 과정 중 추가 갱신 절차를 실패했습니다'
|
||||
]);
|
||||
}
|
||||
|
||||
$access_token = $result['access_token'];
|
||||
$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_expires = TimeUtil::nowAddSeconds($result['refresh_token_expires_in']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!$email){
|
||||
if (!$email) {
|
||||
$me = $restAPI->meWithEmail();
|
||||
$me['code'] = Util::array_get($me['code'], 0);
|
||||
if ($me['code']< 0) {
|
||||
if ($me['code'] < 0) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오로그인이 정상적으로 수행되지 않았습니다.'
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오로그인이 정상적으로 수행되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$kakao_account = $me['kakao_account']??null;
|
||||
$kakao_account = $me['kakao_account'] ?? null;
|
||||
if (!$kakao_account) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오 로그인 정보를 제대로 받아오지 못했습니다.'
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오 로그인 정보를 제대로 받아오지 못했습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
if(!($kakao_account['has_email']??false)){
|
||||
if (!($kakao_account['has_email'] ?? false)) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'이메일 정보 공유를 허가해 주셔야 합니다.',
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '이메일 정보 공유를 허가해 주셔야 합니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
$validEmail = $kakao_account['is_email_valid']??false;
|
||||
$verifiedEmail = $kakao_account['is_email_verified']??false;
|
||||
$validEmail = $kakao_account['is_email_valid'] ?? false;
|
||||
$verifiedEmail = $kakao_account['is_email_verified'] ?? false;
|
||||
|
||||
if(!$validEmail || !$verifiedEmail){
|
||||
if (!$validEmail || !$verifiedEmail) {
|
||||
$restAPI->unlink();
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오 계정 이메일이 아직 인증되지 않았습니다',
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오 계정 이메일이 아직 인증되지 않았습니다',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$email = $kakao_account['email'];
|
||||
$session->kaccount_email = $email;
|
||||
}
|
||||
|
||||
|
||||
$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();
|
||||
$session->access_token = null;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.',
|
||||
'aux'=>$session->tmpx,
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => '카카오로그인에 해당하는 계정이 없습니다. 재 가입을 시도해주세요.',
|
||||
'aux' => $session->tmpx,
|
||||
]);
|
||||
}
|
||||
|
||||
if($userInfo['delete_after']){
|
||||
if($userInfo['delete_after'] < $now){
|
||||
if ($userInfo['delete_after']) {
|
||||
if ($userInfo['delete_after'] < $now) {
|
||||
$restAPI->unlink();
|
||||
$session->access_token = null;
|
||||
$RootDB->delete('member', 'no=%i', $userInfo['no']);
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>"기간 만기로 삭제되었습니다. 재 가입을 시도해주세요.",
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => "기간 만기로 삭제되었습니다. 재 가입을 시도해주세요.",
|
||||
]);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$restAPI->unlink();
|
||||
$session->access_token = null;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>"삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'reason' => "삭제 요청된 계정입니다.[{$userInfo['delete_after']}]"
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$oauthInfo = Json::decode($userInfo['oauth_info'])??[];
|
||||
$oauthInfo = Json::decode($userInfo['oauth_info']) ?? [];
|
||||
$oauthInfo['accessToken'] = $access_token;
|
||||
$oauthInfo['accessTokenValidUntil'] = $expires;
|
||||
if($refresh_token){
|
||||
if ($refresh_token) {
|
||||
$oauthInfo['refreshToken'] = $refresh_token;
|
||||
$oauthInfo['refreshTokenValidUntil'] = $refresh_token_expires;
|
||||
}
|
||||
|
||||
RootDB::db()->update('member', [
|
||||
'oauth_info'=>Json::encode($oauthInfo)
|
||||
'oauth_info' => Json::encode($oauthInfo)
|
||||
], 'no=%i', $userInfo['no']);
|
||||
|
||||
|
||||
$tokenValidUntil = $userInfo['token_valid_until'];
|
||||
|
||||
if(!$tokenValidUntil || $tokenValidUntil < $now){
|
||||
if(!createOTPbyUserNO($userInfo['no'])){
|
||||
if (!$tokenValidUntil || $tokenValidUntil < $now) {
|
||||
if (!createOTPbyUserNO($userInfo['no'])) {
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'인증 코드를 보내는데 실패했습니다.'
|
||||
]);
|
||||
'result' => false,
|
||||
'reqOTP' => false,
|
||||
'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([
|
||||
'result'=>false,
|
||||
'reqOTP'=>true,
|
||||
'reason'=>'인증 코드를 입력해주세요.'
|
||||
'result' => false,
|
||||
'reqOTP' => true,
|
||||
'reason' => '인증 코드를 입력해주세요.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$RootDB->insert('member_log',[
|
||||
'member_no'=>$userInfo['no'],
|
||||
'action_type'=>'login',
|
||||
'action'=>Json::encode([
|
||||
'ip'=>Util::get_client_ip(true),
|
||||
'type'=>'kakao'
|
||||
$RootDB->insert('member_log', [
|
||||
'member_no' => $userInfo['no'],
|
||||
'action_type' => 'login',
|
||||
'action' => Json::encode([
|
||||
'ip' => Util::get_client_ip(true),
|
||||
'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([
|
||||
'result'=>true,
|
||||
'reqOTP'=>false,
|
||||
'reason'=>'로그인 되었습니다.'
|
||||
]);
|
||||
'result' => true,
|
||||
'reqOTP' => false,
|
||||
'nextToken' => [$tokenID, $token],
|
||||
'reason' => '로그인 되었습니다.'
|
||||
]);
|
||||
|
||||
+13
-15
@@ -27,8 +27,8 @@
|
||||
"axios": "^0.21.4",
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap5": "npm:bootstrap@^5.1.1",
|
||||
"core-js": "^3.17.2",
|
||||
"date-fns": "^2.23.0",
|
||||
"core-js": "^3.17.3",
|
||||
"date-fns": "^2.24.0",
|
||||
"downloadjs": "^1.4.7",
|
||||
"jquery": "^3.6.0",
|
||||
"js-sha512": "^0.8.0",
|
||||
@@ -45,39 +45,37 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.15.4",
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/preset-env": "^7.15.4",
|
||||
"@babel/preset-env": "^7.15.6",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@coreui/vue": "^4.0.0-beta.2",
|
||||
"@types/bootstrap": "^5.1.4",
|
||||
"@types/jquery": "^3.5.6",
|
||||
"@types/lodash": "^4.14.172",
|
||||
"@types/node": "^16.7.13",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.0",
|
||||
"@typescript-eslint/parser": "^4.31.0",
|
||||
"@vue/compiler-sfc": "^3.2.10",
|
||||
"@types/lodash": "^4.14.173",
|
||||
"@types/node": "^16.9.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
||||
"@typescript-eslint/parser": "^4.31.1",
|
||||
"@vue/compiler-sfc": "^3.2.12",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"babel-preset-modern-browsers": "^15.0.2",
|
||||
"bootstrap-vue-3": "^0.0.3",
|
||||
"bootswatch": "^5.1.1",
|
||||
"clean-terminal-webpack-plugin": "^3.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"esbuild-loader": "^2.15.1",
|
||||
"eslint": "^7.32.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",
|
||||
"sass": "^1.39.0",
|
||||
"sass": "^1.41.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"style-loader": "^3.2.1",
|
||||
"ts-loader": "^9.2.5",
|
||||
"typescript": "^4.4.2",
|
||||
"typescript": "^4.4.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-eslint-parser": "^7.11.0",
|
||||
"vue-loader": "^16.5.0",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"webpack": "^5.52.0",
|
||||
"webpack": "^5.53.0",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-cli": "^4.8.0"
|
||||
},
|
||||
|
||||
@@ -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' => '로그인 되었습니다.'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class APIHelper
|
||||
|
||||
$sessionMode = $obj->getRequiredSessionMode();
|
||||
if ($sessionMode === BaseAPI::NO_SESSION) {
|
||||
$session = null;
|
||||
$session = Session::getInstance();//XXX: NoSession이면 진짜 NoSession이어야..?
|
||||
} else {
|
||||
if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) {
|
||||
$session = Session::requireGameLogin();
|
||||
@@ -71,7 +71,7 @@ class APIHelper
|
||||
[$lastModified, $etag] = $cacheResult;
|
||||
|
||||
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) {
|
||||
header("Etag: $etag");
|
||||
@@ -94,10 +94,10 @@ class APIHelper
|
||||
], $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());
|
||||
} catch (mixed $e) {
|
||||
Json::dieWithReason($e);
|
||||
Json::dieWithReason(strval($e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ class Json
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
/** @return never */
|
||||
public static function die($value, $flag = self::NO_CACHE)
|
||||
{
|
||||
//NOTE: REST 형식에 맞게, ok(), fail()로 쪼개는게 낫지 않을까 생각해봄.
|
||||
|
||||
@@ -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, '인증 코드를 입력해주세요'];
|
||||
}
|
||||
}
|
||||
+16
-10
@@ -10,8 +10,9 @@ namespace sammo;
|
||||
* @property string $ip IP
|
||||
* @property bool $reqOTP 인증 코드 필요
|
||||
* @property array $acl 권한
|
||||
* @property int|null $tokenID 토큰ID
|
||||
* @property string $tokenValidUntil 로그인 토큰 길이
|
||||
*
|
||||
*
|
||||
* @property int $generalID 장수 번호 (게임 로그인 필요)
|
||||
* @property string $generalName 장수 이름 (게임 로그인 필요)
|
||||
*/
|
||||
@@ -35,7 +36,7 @@ class Session
|
||||
const GAME_KEY_GENERAL_ID = '_g_no';
|
||||
const GAME_KEY_GENERAL_NAME = '_g_name';
|
||||
const GAME_KEY_EXPECTED_DEADTIME = '_g_deadtime';
|
||||
|
||||
|
||||
|
||||
private $writeClosed = false;
|
||||
private $sessionID = null;
|
||||
@@ -170,7 +171,7 @@ class Session
|
||||
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('userName', $userName);
|
||||
@@ -180,6 +181,7 @@ class Session
|
||||
$this->set('acl', $acl);
|
||||
$this->set('reqOTP', $reqOTP);
|
||||
$this->set('tokenValidUntil', $tokenValidUntil);
|
||||
$this->set('tokenID', $tokenID);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -197,7 +199,11 @@ class Session
|
||||
if (class_exists('\\sammo\\UniqueConst')) {
|
||||
$this->logoutGame();
|
||||
}
|
||||
|
||||
|
||||
if($this->tokenID??null){
|
||||
RootDB::db()->delete('login_token', 'id = %i', $this->tokenID);
|
||||
}
|
||||
|
||||
$this->set('userID', null);
|
||||
$this->set('userName', null);
|
||||
$this->set('userGrade', null);
|
||||
@@ -261,7 +267,7 @@ class Session
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
$turnterm = $gameStor->turnterm;
|
||||
$isUnited = $gameStor->isunited != 0;
|
||||
|
||||
@@ -319,7 +325,7 @@ class Session
|
||||
} else {
|
||||
$obj = self::getInstance();
|
||||
}
|
||||
|
||||
|
||||
return $obj->userGrade;
|
||||
}
|
||||
|
||||
@@ -335,12 +341,12 @@ class Session
|
||||
} else {
|
||||
$obj = self::getInstance();
|
||||
}
|
||||
|
||||
|
||||
return $obj->userID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static function getGeneralID(bool $requireLogin = false, string $exitPath = '..')
|
||||
{
|
||||
@@ -349,7 +355,7 @@ class Session
|
||||
} else {
|
||||
$obj = self::getInstance();
|
||||
}
|
||||
|
||||
|
||||
return $obj->generalID??0;
|
||||
}
|
||||
|
||||
@@ -367,7 +373,7 @@ class Session
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($this->userID) {
|
||||
return true;
|
||||
} else {
|
||||
|
||||
+26
-26
@@ -156,7 +156,7 @@ class Util extends \utilphp\util
|
||||
else{
|
||||
$text = str_replace("_tK_{$key}_", $value, $text);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
file_put_contents($destFilePath, $text);
|
||||
|
||||
@@ -182,7 +182,7 @@ class Util extends \utilphp\util
|
||||
else{
|
||||
$head[] = "class $newClassName extends $srcClassName";
|
||||
}
|
||||
|
||||
|
||||
$head[] = '{';
|
||||
$head[] = '';
|
||||
$head = join("\n", $head);
|
||||
@@ -203,7 +203,7 @@ class Util extends \utilphp\util
|
||||
}
|
||||
$result = file_put_contents($destFilePath, $head.join("\n", $body).$tail, LOCK_EX);
|
||||
assert($result);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -281,12 +281,12 @@ class Util extends \utilphp\util
|
||||
public static function convertArrayToDict($arr, $keyName)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
|
||||
foreach ($arr as $obj) {
|
||||
$key = $obj[$keyName];
|
||||
$result[$key] = $obj;
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ class Util extends \utilphp\util
|
||||
public static function convertDictToArray($dict, bool $withKey=true)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
|
||||
foreach($dict as $key=>$value){
|
||||
if($withKey){
|
||||
$result[] = [$key, $value];
|
||||
@@ -318,7 +318,7 @@ class Util extends \utilphp\util
|
||||
$result[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ class Util extends \utilphp\util
|
||||
foreach($dict as $dictKey=>$value){
|
||||
$result[$dictKey] = $value[$key];
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ class Util extends \utilphp\util
|
||||
}
|
||||
$idx = $key + 1;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -368,20 +368,20 @@ class Util extends \utilphp\util
|
||||
if ($dict === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (is_array($dict) && empty($dict)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if ($depth <= 0) {
|
||||
return $dict;
|
||||
}
|
||||
|
||||
|
||||
foreach ($dict as $key=>$value) {
|
||||
if ($value === null) {
|
||||
unset($dict[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!Util::isDict($value)) {
|
||||
continue;
|
||||
}
|
||||
@@ -393,7 +393,7 @@ class Util extends \utilphp\util
|
||||
$dict[$key] = $newValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $dict;
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ class Util extends \utilphp\util
|
||||
|
||||
return (float)$matches[1] / 100;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* $min과 $max 사이의 값으로 교정
|
||||
@@ -552,7 +552,7 @@ class Util extends \utilphp\util
|
||||
|
||||
/**
|
||||
* 2중 배열에서 특정 키의 합
|
||||
*
|
||||
*
|
||||
* @param array $array 배열. 1차원 배열 또는 2차원 배열
|
||||
* @param int|string|null $key 2차원 배열에서 참조할 키.
|
||||
* @return int|float 합계
|
||||
@@ -570,14 +570,14 @@ class Util extends \utilphp\util
|
||||
|
||||
/**
|
||||
* 특정 키를 가진 값으로 묶음
|
||||
*
|
||||
*
|
||||
* @param array $array 배열. 1차원 배열 또는 2차원 배열
|
||||
* @param int|string|null $key 2차원 배열에서 참조할 키.
|
||||
* @return array
|
||||
*/
|
||||
public static function arrayGroupBy(array $array, $key, bool $preserveRowKey=false) {
|
||||
$result = array();
|
||||
|
||||
|
||||
if($preserveRowKey){
|
||||
foreach($array as $rowKey=>$val) {
|
||||
if(key_exists($key, $val)){
|
||||
@@ -596,7 +596,7 @@ class Util extends \utilphp\util
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -618,7 +618,7 @@ class Util extends \utilphp\util
|
||||
*
|
||||
* @param array $items 선택하고자 하는 배열
|
||||
*
|
||||
* @return int|float|string|object 선택된 value값.
|
||||
* @return int|float|string|array|object 선택된 value값.
|
||||
*/
|
||||
public static function choiceRandom(array $items)
|
||||
{
|
||||
@@ -700,7 +700,7 @@ class Util extends \utilphp\util
|
||||
else{
|
||||
throw new \InvalidArgumentException('$lhs is not Traversable');
|
||||
}
|
||||
|
||||
|
||||
if($rhs instanceof \Traversable){
|
||||
$rhsIter = new \IteratorIterator($rhs);
|
||||
}
|
||||
@@ -778,11 +778,11 @@ class Util extends \utilphp\util
|
||||
|
||||
/**
|
||||
* Python 3의 range와 동일
|
||||
* @param int $from
|
||||
* @param null|int $to
|
||||
* @param null|int $step
|
||||
* @param int $from
|
||||
* @param null|int $to
|
||||
* @param null|int $step
|
||||
* @return \Traversable
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function range(int $from, ?int $to=null, ?int $step=null):\Traversable{
|
||||
if($to === null){
|
||||
@@ -809,5 +809,5 @@ class Util extends \utilphp\util
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
../nesbot/carbon/bin/carbon
|
||||
+154
-5
@@ -29,7 +29,7 @@ private static $installed = array (
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => 'cf3f40b5787b2a1aed9255775143108ef5b1f278',
|
||||
'name' => 'sammo-hid/sammo',
|
||||
),
|
||||
'versions' =>
|
||||
@@ -70,6 +70,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '84674dd3a7575ba617f5a76d7e9e29a7d3891339',
|
||||
),
|
||||
'doctrine/inflector' =>
|
||||
array (
|
||||
'pretty_version' => '2.0.3',
|
||||
'version' => '2.0.3.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '9cf661f4eb38f7c881cac67c75ea9b00bf97b210',
|
||||
),
|
||||
'erusev/parsedown' =>
|
||||
array (
|
||||
'pretty_version' => '1.7.4',
|
||||
@@ -142,6 +151,87 @@ private static $installed = array (
|
||||
),
|
||||
'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' =>
|
||||
array (
|
||||
'pretty_version' => 'v3.4.0',
|
||||
@@ -169,6 +259,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => 'c6b00f05152ae2c9b04a448f99c7590beb6042f5',
|
||||
),
|
||||
'nesbot/carbon' =>
|
||||
array (
|
||||
'pretty_version' => '2.53.1',
|
||||
'version' => '2.53.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f4655858a784988f880c1b8c7feabbf02dfdf045',
|
||||
),
|
||||
'netresearch/jsonmapper' =>
|
||||
array (
|
||||
'pretty_version' => 'v4.0.0',
|
||||
@@ -216,12 +315,12 @@ private static $installed = array (
|
||||
),
|
||||
'phan/phan' =>
|
||||
array (
|
||||
'pretty_version' => '5.0.0',
|
||||
'version' => '5.0.0.0',
|
||||
'pretty_version' => '5.2.1',
|
||||
'version' => '5.2.1.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'f36b6b9a2f4143a25f35ce94d712ceb0527e9d90',
|
||||
'reference' => 'd724bbb8fc3ba89179868bb5220ecdf6a9c1636b',
|
||||
),
|
||||
'php-extended/php-system' =>
|
||||
array (
|
||||
@@ -277,6 +376,13 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
|
||||
),
|
||||
'psr/container-implementation' =>
|
||||
array (
|
||||
'provided' =>
|
||||
array (
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' =>
|
||||
array (
|
||||
'pretty_version' => '1.0.1',
|
||||
@@ -310,6 +416,15 @@ private static $installed = array (
|
||||
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' =>
|
||||
array (
|
||||
'pretty_version' => '3.0.3',
|
||||
@@ -335,7 +450,7 @@ private static $installed = array (
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '5310c2e7f6f872cbb923ed71b72ef01b8df4aaaf',
|
||||
'reference' => 'cf3f40b5787b2a1aed9255775143108ef5b1f278',
|
||||
),
|
||||
'scssphp/scssphp' =>
|
||||
array (
|
||||
@@ -472,6 +587,31 @@ private static $installed = array (
|
||||
),
|
||||
'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' =>
|
||||
array (
|
||||
'pretty_version' => '0.0.2',
|
||||
@@ -490,6 +630,15 @@ private static $installed = array (
|
||||
),
|
||||
'reference' => '5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb',
|
||||
),
|
||||
'voku/portable-ascii' =>
|
||||
array (
|
||||
'pretty_version' => '1.5.6',
|
||||
'version' => '1.5.6.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '80953678b19901e5165c56752d087fc11526017c',
|
||||
),
|
||||
'webmozart/assert' =>
|
||||
array (
|
||||
'pretty_version' => '1.10.0',
|
||||
|
||||
Vendored
+5
-1
@@ -8,12 +8,15 @@ $baseDir = dirname($vendorDir);
|
||||
return array(
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
|
||||
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.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',
|
||||
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
|
||||
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
|
||||
@@ -25,6 +28,7 @@ return array(
|
||||
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
|
||||
'6714be961f4a45ae8b9a99d5d55c5d07' => $vendorDir . '/tysonandre/var_representation_polyfill/src/var_representation.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'ef65a1626449d89d0811cf9befce46f0' => $vendorDir . '/illuminate/events/functions.php',
|
||||
'5b154887902198b16314243c6e0e3e19' => $vendorDir . '/pguardiario/phpuri/phpuri.php',
|
||||
'870dc64919afa8b0f700701bb2c6a783' => $baseDir . '/f_config/config.php',
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user