diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 10c01d36..9c7553a0 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,39 +1,42 @@ module.exports = { - root: true, - parser: "vue-eslint-parser", - parserOptions: { - "project": "./tsconfig.json" - }, - ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'webpack.config.cjs', '*.js'], - overrides: [{ - files: ['*.ts', '*.tsx', "*.vue"], - }], - plugins: [ - "@typescript-eslint", + root: true, + parser: "vue-eslint-parser", + "env": { + "browser": true, + "es2021": true + }, + ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'webpack.config.cjs', '*.js'], + overrides: [{ + files: ['*.ts', '*.tsx', "*.vue"], + }], + plugins: [ + "@typescript-eslint" + ], - ], - extends: [ - "eslint:recommended", - 'plugin:vue/essential', - '@vue/typescript', - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - rules: { - '@typescript-eslint/no-floating-promises': 'error', - "vue/no-multiple-template-root": "off", - "vue/no-v-for-template-key": "off", - "vue/multi-word-component-names": "off",//TODO: 삭제 - }, - settings: { - 'import/resolver': { - alias: { - map: [ - ['@', './hwe/ts'], - ['@util', './hwe/ts/util'], - ['@scss', './hwe/scss'], - ] - } - } - }, -} \ No newline at end of file + extends: [ + "eslint:recommended", + "plugin:vue/vue3-essential", + "plugin:@typescript-eslint/recommended" + ], + parserOptions: { + "sourceType": "module", + "project": "./tsconfig.json", + "ecmaVersion": 2021, + "parser": "@typescript-eslint/parser", + extraFileExtensions: ['.vue'] + }, + rules: { + '@typescript-eslint/no-floating-promises': 'error', + }, + settings: { + 'import/resolver': { + alias: { + map: [ + ['@', './hwe/ts'], + ['@util', './hwe/ts/util'], + ['@scss', './hwe/scss'], + ] + } + } + }, +}; diff --git a/f_install/install.php b/f_install/install.php index 27c46db6..e1c1b265 100644 --- a/f_install/install.php +++ b/f_install/install.php @@ -13,13 +13,17 @@ require(__DIR__ . '/../vendor/autoload.php'); 설치 + - - - - - + + + + + + + + diff --git a/hwe/_119.php b/hwe/_119.php index 1017a904..513301d1 100644 --- a/hwe/_119.php +++ b/hwe/_119.php @@ -24,7 +24,7 @@ $plock = $db->queryFirstField('SELECT plock FROM plock'); - + diff --git a/hwe/_admin1.php b/hwe/_admin1.php index a622e36e..8e9fd584 100644 --- a/hwe/_admin1.php +++ b/hwe/_admin1.php @@ -22,7 +22,7 @@ $admin = getAdmin(); - + diff --git a/hwe/_admin2.php b/hwe/_admin2.php index 5721e97c..87b2bb2b 100644 --- a/hwe/_admin2.php +++ b/hwe/_admin2.php @@ -23,7 +23,7 @@ $db = DB::db(); - + diff --git a/hwe/_admin4.php b/hwe/_admin4.php index 0f05ba32..2ef4c18f 100644 --- a/hwe/_admin4.php +++ b/hwe/_admin4.php @@ -23,8 +23,9 @@ $ipGroupList = Util::arrayGroupBy( 'ip_c' ); -function colorBlockedName($general){ - if(!$general['blocked']){ +function colorBlockedName($general) +{ + if (!$general['blocked']) { return $general['name']; } return "{$general['name']}"; @@ -40,7 +41,7 @@ function colorBlockedName($general){ - + @@ -108,14 +109,14 @@ function colorBlockedName($general){ IP ID -$users): ?> - - ',array_map('\sammo\colorBlockedName', $users))?> - ',array_column($users, 'lastconnect'))?> - ',array_column($users, 'ip'))?> - ',array_column($users, 'owner'))?> - - + $users) : ?> + + ', array_map('\sammo\colorBlockedName', $users)) ?> + ', array_column($users, 'lastconnect')) ?> + ', array_column($users, 'ip')) ?> + ', array_column($users, 'owner')) ?> + + - + @@ -212,7 +212,7 @@ GROUP BY B.nation $query .= " order by avg(B.dex5) desc"; break; } - foreach($db->query($query) as $nation){ + foreach ($db->query($query) as $nation) { $gen = $db->queryFirstRow('SELECT COUNT(*) as cnt, ROUND(AVG(gold)) as avgg, ROUND(AVG(rice)) as avgr, @@ -221,7 +221,7 @@ GROUP BY B.nation ROUND(AVG(intel), 1) as avgi, ROUND(AVG(explevel), 1) as avge, SUM(crew) as crew -from general where nation=%i',$nation['nation']); +from general where nation=%i', $nation['nation']); $city = $db->queryFirstRow('SELECT COUNT(*) as cnt, SUM(pop) as pop, SUM(pop_max) as pop_max, @@ -312,7 +312,7 @@ from city where nation=%i', $nation['nation']); ?> query('SELECT * from statistic where month=1 or no=1') as $stat){ + foreach ($db->query('SELECT * from statistic where month=1 or no=1') as $stat) { echo " {$stat['year']} diff --git a/hwe/_admin7.php b/hwe/_admin7.php index 1a3ecfd1..25078733 100644 --- a/hwe/_admin7.php +++ b/hwe/_admin7.php @@ -86,7 +86,7 @@ $generalObj = General::createGeneralObjFromDB($gen); - + diff --git a/hwe/_admin8.php b/hwe/_admin8.php index 9fd01fba..b9fb03c0 100644 --- a/hwe/_admin8.php +++ b/hwe/_admin8.php @@ -1,4 +1,5 @@ + -외교정보 - - - - - - + 외교정보 + + + + + + + - - - -
외 교 정 보
-
- 정렬순서 : - - -
-
- - +
외 교 관 계
+ + + + + + +
외 교 정 보
+
+ 정렬순서 : + + +
+
+ + + + + + + + + + + query('SELECT * from diplomacy where me < you order by state desc') as $dip) { + $me = $dip['me']; + $you = $dip['you']; + + if ($dip['state'] == 2) { + continue; + } + + switch ($dip['state']) { + case 0: + $state = "교 전"; + break; + case 1: + $state = "선포중"; + break; + case 2: + $state = "통 상"; + break; + case 7: + $state = "불가침"; + break; + } + + $date = TimeUtil::now(); + + echo " - - - - - -query('SELECT * from diplomacy where me < you order by state desc') as $dip){ - $me = $dip['me']; - $you = $dip['you']; - - if ($dip['state'] == 2) { - continue; - } - - switch ($dip['state']) { - case 0: $state = "교 전"; break; - case 1: $state = "선포중"; break; - case 2: $state = "통 상"; break; - case 7: $state = "불가침"; break; - } - - $date = TimeUtil::now(); - - echo " - - - + + "; -} -?> -
외 교 관 계
국 가 명국 가 명상 태기 간
국 가 명국 가 명상 태기 간
$nationName[$me]$nationName[$you]$nationName[$me]$nationName[$you] $state {$dip['term']} 개월
- - - -
+ } + ?> + + + + + + + + +
- + + \ No newline at end of file diff --git a/hwe/a_bestGeneral.php b/hwe/a_bestGeneral.php index 7efac72a..37967b4d 100644 --- a/hwe/a_bestGeneral.php +++ b/hwe/a_bestGeneral.php @@ -27,13 +27,10 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates'); <?= UniqueConst::$serverName ?>: 명장일람 - - - - + diff --git a/hwe/a_emperior.php b/hwe/a_emperior.php index 6294f2d3..8444f331 100644 --- a/hwe/a_emperior.php +++ b/hwe/a_emperior.php @@ -18,12 +18,9 @@ increaseRefresh("왕조일람", 1); <?= UniqueConst::$serverName ?>: 왕조일람 - - - - + diff --git a/hwe/a_emperior_detail.php b/hwe/a_emperior_detail.php index 1a3ea255..a852745c 100644 --- a/hwe/a_emperior_detail.php +++ b/hwe/a_emperior_detail.php @@ -1,4 +1,5 @@ registerFunction('ConvertLog', '\sammo\ConvertLog'); $templates->registerFunction('newColor', '\sammo\newColor'); increaseRefresh("왕조일람", 1); -$emperior = $db->queryFirstRow('SELECT * FROM emperior WHERE `no`=%i',$select); -$serverID = $emperior['server_id']??($emperior['serverID']??null); +$emperior = $db->queryFirstRow('SELECT * FROM emperior WHERE `no`=%i', $select); +$serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null); ?> @@ -22,193 +23,199 @@ $serverID = $emperior['server_id']??($emperior['serverID']??null); - - - -<?=UniqueConst::$serverName?>: 왕조일람 - - - + + + + <?= UniqueConst::$serverName ?>: 왕조일람 + + + - - +
역 대 왕 조
- -
-
+ + + -
역 대 왕 조
+ +
+
+
+ - + if ($emperior) : + ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
국 가 수
(최종 / 최대)
장 수 수
(최종 / 최대)
등 장 국 가
국가별 성향
장 수 성 격
장 수 특 기
; bgcolor= colspan=6> - (月) -
국 력성 향
장 수속 령
총 인 구인 구 율
국 고병 량
황 제 승 상 
위 장 군 사 공 
표 기 장 군 태 위 
거 기 장 군 사 도 
오 호 장 군
건 안 칠 자
장 수 들
(공헌도 순서)
역 사 기 록
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
국 가 수
(최종 / 최대)
장 수 수
(최종 / 최대)
등 장 국 가
국가별 성향
장 수 성 격
장 수 특 기
; bgcolor= colspan=6> + (月) +
국 력성 향
장 수속 령
총 인 구인 구 율
국 고병 량
황 제 승 상 
위 장 군 사 공 
표 기 장 군 태 위 
거 기 장 군 사 도 
오 호 장 군
건 안 칠 자
장 수 들
(공헌도 순서)
역 사 기 록
-query('SELECT * FROM ng_old_nations WHERE server_id=%s ORDER BY date DESC', $serverID); - foreach($nations as $nation){ - if(!$nation['nation']??null){ - continue; - } - $nation += Json::decode($nation['data']); - - $nation['typeName'] = getNationType($nation['type']); - $nation['levelName'] = getNationLevel($nation['level']); - /** @var int[]|null $nationGenerals */ - $nationGenerals = $nation['generals']; - - if($nationGenerals){ - $generals = $db->query('SELECT `general_no`, `name`, `last_yearmonth` FROM ng_old_generals WHERE server_id=%s AND general_no IN %li', $serverID, $nationGenerals); - - if(count($generals) != count($nationGenerals) && $serverID == UniqueConst::$serverID){ - $liveGenerals = $nationGenerals; - foreach($generals as $general){ - if(in_array($general['general_no'], $nationGenerals)){ - unset($nationGenerals[$general['general_no']]); - } - } - $liveGenerals = $db->query('SELECT `no`as`general_no`, `name` FROM general WHERE no IN %li', $liveGenerals); - $nation['generalsFull'] = array_merge($liveGenerals, $generals); - } - else{ - $nation['generalsFull'] = $generals; - } - } - else{ - $nation['generalsFull'] = []; - } - - if(key_exists('aux', $nation) && !is_array($nation['aux'])){ - $nation += Json::decode($nation['aux']); - } - - echo $templates->render('oldNation', $nation); + if (!$serverID) { + $serverID = UniqueConst::$serverID; } -} -?> - - - -
+ if ($showServers) { + $nations = $db->query('SELECT * FROM ng_old_nations WHERE server_id=%s ORDER BY date DESC', $serverID); + foreach ($nations as $nation) { + if (!$nation['nation'] ?? null) { + continue; + } + $nation += Json::decode($nation['data']); + + $nation['typeName'] = getNationType($nation['type']); + $nation['levelName'] = getNationLevel($nation['level']); + /** @var int[]|null $nationGenerals */ + $nationGenerals = $nation['generals']; + + if ($nationGenerals) { + $generals = $db->query('SELECT `general_no`, `name`, `last_yearmonth` FROM ng_old_generals WHERE server_id=%s AND general_no IN %li', $serverID, $nationGenerals); + + if (count($generals) != count($nationGenerals) && $serverID == UniqueConst::$serverID) { + $liveGenerals = $nationGenerals; + foreach ($generals as $general) { + if (in_array($general['general_no'], $nationGenerals)) { + unset($nationGenerals[$general['general_no']]); + } + } + $liveGenerals = $db->query('SELECT `no`as`general_no`, `name` FROM general WHERE no IN %li', $liveGenerals); + $nation['generalsFull'] = array_merge($liveGenerals, $generals); + } else { + $nation['generalsFull'] = $generals; + } + } else { + $nation['generalsFull'] = []; + } + + if (key_exists('aux', $nation) && !is_array($nation['aux'])) { + $nation += Json::decode($nation['aux']); + } + + echo $templates->render('oldNation', $nation); + } + } + ?> + + + + + + + + +
+ \ No newline at end of file diff --git a/hwe/a_genList.php b/hwe/a_genList.php index c8f62b0b..b83e4e3b 100644 --- a/hwe/a_genList.php +++ b/hwe/a_genList.php @@ -45,12 +45,9 @@ if ($gameStor->isunited) { <?= UniqueConst::$serverName ?>: 장수일람 - - - - + diff --git a/hwe/a_hallOfFame.php b/hwe/a_hallOfFame.php index b4b89813..68c573c4 100644 --- a/hwe/a_hallOfFame.php +++ b/hwe/a_hallOfFame.php @@ -47,13 +47,10 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) { <?= UniqueConst::$serverName ?>: 명예의 전당 - - - - + diff --git a/hwe/a_history.php b/hwe/a_history.php index cb4c9618..cffb467f 100644 --- a/hwe/a_history.php +++ b/hwe/a_history.php @@ -99,15 +99,13 @@ $nations = Json::decode($history['nations']); <?= UniqueConst::$serverName ?>: 연감 - - - - + + - - - - - - diff --git a/hwe/a_traffic.php b/hwe/a_traffic.php index 615e76df..106e9397 100644 --- a/hwe/a_traffic.php +++ b/hwe/a_traffic.php @@ -54,12 +54,7 @@ if ($admin['maxonline'] < $curonline) { - - - - - + + diff --git a/hwe/a_vote.php b/hwe/a_vote.php index 92fed25d..e526689f 100644 --- a/hwe/a_vote.php +++ b/hwe/a_vote.php @@ -30,12 +30,7 @@ $vote = $admin['vote'] ?: ['-']; - - - - - + + + diff --git a/hwe/b_currentCity.php b/hwe/b_currentCity.php index 2e1813e4..38d63e50 100644 --- a/hwe/b_currentCity.php +++ b/hwe/b_currentCity.php @@ -35,13 +35,9 @@ $templates = new \League\Plates\Engine('templates'); - - - - + diff --git a/hwe/b_dipcenter.php b/hwe/b_dipcenter.php index 452d774d..2300cf45 100644 --- a/hwe/b_dipcenter.php +++ b/hwe/b_dipcenter.php @@ -54,23 +54,15 @@ $nationStor->cacheValues(['notice', 'scout_msg', 'available_war_setting_cnt']); <?= UniqueConst::$serverName ?>: 내무부 - + ($me['officer_level'] >= 5 || $permission == 4), + 'nationMsg' => $nationStor->notice ?? '', + 'scoutMsg' => $nationStor->scout_msg ?? '', + ]) ?> - - - - - - - + @@ -176,51 +168,12 @@ $nationStor->cacheValues(['notice', 'scout_msg', 'available_war_setting_cnt']); } ?> - +
+ +
+
- - - - - - - - - - - - diff --git a/hwe/b_diplomacy.php b/hwe/b_diplomacy.php index 236977cd..7b54f766 100644 --- a/hwe/b_diplomacy.php +++ b/hwe/b_diplomacy.php @@ -92,11 +92,12 @@ $neutralStateCharMap = [ <?= UniqueConst::$serverName ?>: 중원 정보 - - - - + + + + + - - - - - - diff --git a/hwe/b_genList.php b/hwe/b_genList.php index 9295bde6..5d8dd06f 100644 --- a/hwe/b_genList.php +++ b/hwe/b_genList.php @@ -55,12 +55,9 @@ $templates = new \League\Plates\Engine('templates'); <?= UniqueConst::$serverName ?>: 암행부 - - - - + diff --git a/hwe/b_myBossInfo.php b/hwe/b_myBossInfo.php index 54d0c97c..3336c9da 100644 --- a/hwe/b_myBossInfo.php +++ b/hwe/b_myBossInfo.php @@ -35,19 +35,15 @@ $nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nati <?= UniqueConst::$serverName ?>: 인사부 - - - - - + "selected"]; <?= UniqueConst::$serverName ?>: 세력도시 - - - - - + diff --git a/hwe/b_myGenInfo.php b/hwe/b_myGenInfo.php index 8dec4b95..015559e7 100644 --- a/hwe/b_myGenInfo.php +++ b/hwe/b_myGenInfo.php @@ -46,13 +46,9 @@ if ($gameStor->isunited) { <?= UniqueConst::$serverName ?>: 세력장수 - - - - - + diff --git a/hwe/b_myKingdomInfo.php b/hwe/b_myKingdomInfo.php index 05d9c4c2..39c7ccc0 100644 --- a/hwe/b_myKingdomInfo.php +++ b/hwe/b_myKingdomInfo.php @@ -29,13 +29,9 @@ if ($nationID == 0) { <?= UniqueConst::$serverName ?>: 세력정보 - - - - - + diff --git a/hwe/b_myPage.php b/hwe/b_myPage.php index bc6b26e8..270e945a 100644 --- a/hwe/b_myPage.php +++ b/hwe/b_myPage.php @@ -53,14 +53,10 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1; - - - - - - + + diff --git a/hwe/b_processing.php b/hwe/b_processing.php index dc3b1a60..5a398fab 100644 --- a/hwe/b_processing.php +++ b/hwe/b_processing.php @@ -76,11 +76,7 @@ $cssList = $commandObj->getCSSFiles(); - - - - + @@ -233,7 +225,6 @@ uasort($troops, function ($lhs, $rhs) {
국 가 방 침 & 임관 권유 메시지
-
-
-
- 국가 방침 -
-
- -
-
- -
-
-
-
-
-
- 임관 권유 -
-
- -
-
-
870px x 200px를 넘어서는 내용은 표시되지 않습니다.
- -
-
-
-
- -
예 산 & 정 책
- \ No newline at end of file diff --git a/hwe/battle_simulator.php b/hwe/battle_simulator.php index 7277f3a7..7e7f6cb7 100644 --- a/hwe/battle_simulator.php +++ b/hwe/battle_simulator.php @@ -46,18 +46,15 @@ if ($nationID) { - - - - + diff --git a/hwe/c_dipcenter.php b/hwe/c_dipcenter.php index 41fa6f56..19785b1d 100644 --- a/hwe/c_dipcenter.php +++ b/hwe/c_dipcenter.php @@ -7,8 +7,8 @@ include "func.php"; // $btn, $msg, $scoutmsg, $rate, $bill, $secretlimit $btn = Util::getPost('btn'); -$msg = Util::getPost('msg'); -$scoutmsg = Util::getPost('scoutMsg'); +//$msg = Util::getPost('msg'); +//$scoutmsg = Util::getPost('scoutMsg'); $rate = Util::getPost('rate', 'int'); $bill = Util::getPost('bill', 'int'); $secretlimit = Util::getPost('secretlimit', 'int'); @@ -34,14 +34,14 @@ if ($permission < 0) { $nationID = $me['nation']; $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); -if ($btn == "국가방침 수정") { +/*if ($btn == "국가방침 수정") { $msg = mb_substr($msg, 0, 16384); //$msg = StringUtil:: $nationStor->notice = WebUtil::htmlPurify($msg); } elseif ($btn == "임관 권유문 수정") { $scoutmsg = mb_substr($scoutmsg, 0, 1000); $nationStor->scout_msg = WebUtil::htmlPurify($scoutmsg); -} elseif ($btn == "세율") { +} else*/if ($btn == "세율") { $rate = Util::valueFit($rate, 5, 30); $db->update('nation', [ 'rate' => $rate, diff --git a/hwe/func_legacy.php b/hwe/func_legacy.php index a2e4d070..bfc56589 100644 --- a/hwe/func_legacy.php +++ b/hwe/func_legacy.php @@ -1,58 +1,72 @@ - - - -접속제한 - - - - - - - - - -접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : )
-(자신의 턴이 되면 다시 접속 가능합니다. 당신의 건강을 위해 잠시 쉬어보시는 것은 어떨까요? ^^)
-
- - + + + + + 접속제한 + + + + + + + + + + + 접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : )
+ (자신의 턴이 되면 다시 접속 가능합니다. 당신의 건강을 위해 잠시 쉬어보시는 것은 어떨까요? ^^)
+
+ + + -
-
+
+
"; return $str; } -function optionsForCities(callable $infoCall=null) { +function optionsForCities(callable $infoCall = null) +{ - if(!$infoCall){ - return join('', array_map(function($city){ + if (!$infoCall) { + return join('', array_map(function ($city) { return ""; }, CityConst::all())); } $infoList = []; $noInfoList = []; - foreach(CityConst::all() as $city){ + foreach (CityConst::all() as $city) { $info = $infoCall($city); - if(!$info){ + if (!$info) { $noInfoList[] = ""; continue; } @@ -62,7 +76,8 @@ function optionsForCities(callable $infoCall=null) { return join('', array_merge($infoList, $noInfoList)); } -function Submit($url, $msg="", $msg2="") { +function Submit($url, $msg = "", $msg2 = "") +{ echo "a"; // 파폭 버그 때문 echo " @@ -74,49 +89,62 @@ function Submit($url, $msg="", $msg2="") { } -function GetNationColors() { - $colors = array("#FF0000", "#800000", "#A0522D", "#FF6347", "#FFA500", "#FFDAB9", "#FFD700", "#FFFF00", +function GetNationColors() +{ + $colors = array( + "#FF0000", "#800000", "#A0522D", "#FF6347", "#FFA500", "#FFDAB9", "#FFD700", "#FFFF00", "#7CFC00", "#00FF00", "#808000", "#008000", "#2E8B57", "#008080", "#20B2AA", "#6495ED", "#7FFFD4", "#AFEEEE", "#87CEEB", "#00FFFF", "#00BFFF", "#0000FF", "#000080", "#483D8B", "#7B68EE", "#BA55D3", - "#800080", "#FF00FF", "#FFC0CB", "#F5F5DC", "#E0FFFF", "#FFFFFF", "#A9A9A9"); + "#800080", "#FF00FF", "#FFC0CB", "#F5F5DC", "#E0FFFF", "#FFFFFF", "#A9A9A9" + ); return $colors; } -function backButton() { +function backButton() +{ return "
"; } -function CoreBackButton() { +function CoreBackButton() +{ return "
"; } -function closeButton() { +function closeButton() +{ return "
"; } -function printCitiesBasedOnDistance(int $cityNo, int $maxDistance=1):string { +function printCitiesBasedOnDistance(int $cityNo, int $maxDistance = 1): string +{ $distanceList = searchDistance($cityNo, $maxDistance, true); $result = []; - for($dist = 1; $dist <= $maxDistance; $dist++){ - $cityList = array_map(function($cityID){ + for ($dist = 1; $dist <= $maxDistance; $dist++) { + $cityList = array_map(function ($cityID) { return CityConst::byID($cityID)->name; }, Util::array_get($distanceList[$dist], [])); $cityStr = join(', ', $cityList); - switch($dist) { - case 1: $color = "magenta"; break; - case 2: $color = "orange"; break; - default: $color = "yellow"; break; + switch ($dist) { + case 1: + $color = "magenta"; + break; + case 2: + $color = "orange"; + break; + default: + $color = "yellow"; + break; } $result[] = "{$dist}칸 떨어진 도시 : {$cityStr}"; @@ -125,7 +153,8 @@ function printCitiesBasedOnDistance(int $cityNo, int $maxDistance=1):string { } -function info($type=0) { +function info($type = 0) +{ $db = DB::db(); $gameStor = KVStorage::getStorage($db, 'game_env'); @@ -136,14 +165,14 @@ function info($type=0) { $gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc < 2'); $npccount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc >= 2'); - switch($type) { - case 0: - return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)
등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; - case 1: - return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)          등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; - case 2: - return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)"; - case 3: - return "등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; + switch ($type) { + case 0: + return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)
등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; + case 1: + return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)          등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; + case 2: + return "현재 : {$admin['year']}年 {$admin['month']}月 ($termtype 서버)"; + case 3: + return "등록 장수 : 유저 {$gencount} / {$admin['maxgeneral']} 명 + NPC {$npccount} 명"; } } diff --git a/hwe/func_template.php b/hwe/func_template.php index 17287026..8b029dba 100644 --- a/hwe/func_template.php +++ b/hwe/func_template.php @@ -11,10 +11,10 @@ namespace sammo; * TODO: side effect를 제거 */ - /** - * 관리자 권한이 필요함을 출력. - * @return void - */ +/** + * 관리자 권한이 필요함을 출력. + * @return void + */ function requireAdminPermissionHTML() { ob_start(); @@ -28,8 +28,8 @@ function requireAdminPermissionHTML() - - + + @@ -119,7 +119,7 @@ function displaySpecialDomesticInfo(?string $type): string ]); } -function allButton(bool $seizeNPCMode, array $opts=[]) +function allButton(bool $seizeNPCMode, array $opts = []) { if ($seizeNPCMode) { $site = "a_npcList.php"; @@ -143,7 +143,7 @@ function allButton(bool $seizeNPCMode, array $opts=[]) } -function commandButton(array $opts=[]) +function commandButton(array $opts = []) { $session = Session::getInstance(); $userID = Session::getUserID(); @@ -196,13 +196,13 @@ function formatDefenceTrain(int $value): string { if ($value === 999) { return "×"; - } else if ($value >= 90){ + } else if ($value >= 90) { return "☆"; } else if ($value >= 80) { return "◎"; } else if ($value >= 60) { return "○"; - } else{ + } else { return "△"; } } @@ -253,36 +253,49 @@ function getInvitationList(array $nationList) } -function getAutorunInfo($autorunOption){ - $templates = new \League\Plates\Engine(__DIR__.'/templates'); +function getAutorunInfo($autorunOption) +{ + $templates = new \League\Plates\Engine(__DIR__ . '/templates'); $auto_info = []; - foreach($autorunOption['options'] as $auto_option => $value){ + foreach ($autorunOption['options'] as $auto_option => $value) { assert($value); - switch($auto_option){ - case 'develop': $auto_info['내정'] = '내정'; break; - case 'warp': $auto_info['순간이동'] = '순간이동'; break; - case 'recruit': $auto_info['징병'] = $auto_info['징병']??'징병'; break; - case 'recruit_high': $auto_info['징병'] = '모병'; break; - case 'train': $auto_info['훈사'] = '훈련/사기진작'; break; - case 'battle': $auto_info['출병'] = '출병'; break; - case 'chief': $auto_info['사령턴'] = '사령턴'; break; + switch ($auto_option) { + case 'develop': + $auto_info['내정'] = '내정'; + break; + case 'warp': + $auto_info['순간이동'] = '순간이동'; + break; + case 'recruit': + $auto_info['징병'] = $auto_info['징병'] ?? '징병'; + break; + case 'recruit_high': + $auto_info['징병'] = '모병'; + break; + case 'train': + $auto_info['훈사'] = '훈련/사기진작'; + break; + case 'battle': + $auto_info['출병'] = '출병'; + break; + case 'chief': + $auto_info['사령턴'] = '사령턴'; + break; } } $limit = Util::toInt($autorunOption['limit_minutes']); - if($limit >= 43200){ + if ($limit >= 43200) { $auto_info['제한'] = '항상 유효'; - } - else if($limit % 60 == 0){ - $auto_info['제한'] = ($limit/60).'시간 유효'; - } - else{ - $auto_info['제한'] = ($limit).'분 유효'; + } else if ($limit % 60 == 0) { + $auto_info['제한'] = ($limit / 60) . '시간 유효'; + } else { + $auto_info['제한'] = ($limit) . '분 유효'; } $auto_info = join(', ', array_values($auto_info)); return $templates->render('tooltip', [ - 'text'=>'자율행동', - 'info'=>$auto_info, - 'style'=>'text-decoration:underline', - 'copyable_info'=>true + 'text' => '자율행동', + 'info' => $auto_info, + 'style' => 'text-decoration:underline', + 'copyable_info' => true ]); -} \ No newline at end of file +} diff --git a/hwe/index.php b/hwe/index.php index 512b5c6c..b2c0b649 100644 --- a/hwe/index.php +++ b/hwe/index.php @@ -118,15 +118,9 @@ if (!$otherTextInfo) { - - - - - + - - DB::prefix(), diff --git a/hwe/install.php b/hwe/install.php index 3a624bc9..25969c90 100644 --- a/hwe/install.php +++ b/hwe/install.php @@ -31,11 +31,8 @@ if ($session->userGrade < 5 && !$allowReset) { - - - - + diff --git a/hwe/install_db.php b/hwe/install_db.php index b815cde4..b2779906 100644 --- a/hwe/install_db.php +++ b/hwe/install_db.php @@ -24,12 +24,9 @@ if ($session->userGrade == 5) { - - - - + diff --git a/hwe/j_image_upload.php b/hwe/j_image_upload.php deleted file mode 100644 index 582b6864..00000000 --- a/hwe/j_image_upload.php +++ /dev/null @@ -1,111 +0,0 @@ -setReadOnly(); -$userID = $session::getUserID(); -$serverID = UniqueConst::$serverID; - -$image = $_FILES['img']; -switch ($image['error']) { - case UPLOAD_ERR_OK: - break; - case UPLOAD_ERR_NO_FILE: - Json::die([ - 'result'=>false, - 'reason'=>'파일이 없습니다.' - ]); - case UPLOAD_ERR_INI_SIZE: - case UPLOAD_ERR_FORM_SIZE: - Json::die([ - 'result'=>false, - 'reason'=>'업로드된 파일이 지나치게 큽니다.' - ]); - default: - Json::die([ - 'result'=>false, - 'reason'=>'업로드되지 않았습니다.' - ]); -} - -if(!is_uploaded_file($image['tmp_name'])) { - Json::die([ - 'result'=>false, - 'reason'=>'제대로 파일이 업로드되지 않았습니다.' - ]); -} - -if($image['size'] > 1048576) { - //파일크기 검사 - Json::die([ - 'result'=>false, - 'reason'=>'1MB 이하로 올려주세요!' - ]); -} - -$size = getImageSize($image['tmp_name']); - -$imageType = $size[2]; -$availableImageType = array('.jpg'=>IMAGETYPE_JPEG, '.png'=>IMAGETYPE_PNG, '.gif'=>IMAGETYPE_GIF); -$newExt = array_search($imageType, $availableImageType, true); - -if(!$newExt) { - Json::die([ - 'result'=>false, - 'reason'=>'jpg, gif, png 파일이 아닙니다!' - ]); -} - -$db = RootDB::db(); -$imgStor = KVStorage::getStorage($db, 'img_storage'); - -$picName = hash_file('md5', $image['tmp_name']); -$newPicName = "$picName$newExt"; - -$destDir = AppConf::getUserIconPathFS().'/uploaded_image'; -$dest = $destDir.'/'.$newPicName; - -if(!file_exists($dest)){ - if (!file_exists($destDir)) { - mkdir($destDir); - } - if(!is_dir($destDir)) { - Json::die([ - 'result'=>false, - 'reason'=>'버그! 업로드 경로 확인!' - ]); - } - if(!is_writable($destDir)){ - Json::die([ - 'result'=>false, - 'reason'=>'버그! 업로드 권한 확인!' - ]); - } - - $dest = $destDir.'/'.$newPicName; - - if(!move_uploaded_file($image['tmp_name'], $dest)) { - Json::die([ - 'result'=>false, - 'reason'=>'업로드에 실패했습니다!' - ]); - } -} - -$storedStatus = $imgStor->$newPicName??[]; -$imgKey = "$serverID:$userID"; -if(!key_exists($imgKey, $storedStatus)){ - $storedStatus[$imgKey] = TimeUtil::now(); -} - -$imgStor->$newPicName = $storedStatus; - -Json::die([ - 'result'=>true, - 'reason'=>'성공', - 'path'=>AppConf::getUserIconPathWeb().'/uploaded_image/'.$newPicName -]); \ No newline at end of file diff --git a/hwe/recent_map.php b/hwe/recent_map.php index 8583b35b..c09f537c 100644 --- a/hwe/recent_map.php +++ b/hwe/recent_map.php @@ -19,14 +19,12 @@ include "func.php"; 'serverNick' => DB::prefix(), 'serverID' => UniqueConst::$serverID ]) ?> - - - + \ No newline at end of file diff --git a/hwe/ts/Join.vue b/hwe/ts/PageJoin.vue similarity index 99% rename from hwe/ts/Join.vue rename to hwe/ts/PageJoin.vue index 85c39fa5..f8f351e5 100644 --- a/hwe/ts/Join.vue +++ b/hwe/ts/PageJoin.vue @@ -389,7 +389,7 @@ type APIArgs = { }; export default defineComponent({ - name: "Join", + name: "PageJoin", components: { TopBackBar, CTable, diff --git a/hwe/ts/NPCControl.vue b/hwe/ts/PageNPCControl.vue similarity index 99% rename from hwe/ts/NPCControl.vue rename to hwe/ts/PageNPCControl.vue index 1cedfde6..345cbc10 100644 --- a/hwe/ts/NPCControl.vue +++ b/hwe/ts/PageNPCControl.vue @@ -511,7 +511,7 @@ declare const lastSetters: { }; export default defineComponent({ - name: "NPCControl", + name: "PageNPCControl", components: { TopBackBar, NumberInputWithInfo, diff --git a/hwe/ts/PartialDipcenter.vue b/hwe/ts/PartialDipcenter.vue new file mode 100644 index 00000000..fd025887 --- /dev/null +++ b/hwe/ts/PartialDipcenter.vue @@ -0,0 +1,124 @@ + + \ No newline at end of file diff --git a/hwe/ts/ReservedCommand.vue b/hwe/ts/PartialReservedCommand.vue similarity index 99% rename from hwe/ts/ReservedCommand.vue rename to hwe/ts/PartialReservedCommand.vue index 32da8014..35dab1eb 100644 --- a/hwe/ts/ReservedCommand.vue +++ b/hwe/ts/PartialReservedCommand.vue @@ -287,7 +287,7 @@ function isDropdownChildren(e?: Event): boolean { const searchModeKey = `sammo_${serverID}_searchMode`; export default defineComponent({ - name: "ReservedCommand", + name: "PartialReservedCommand", methods: { updateNow() { diff --git a/hwe/ts/build_exports.json b/hwe/ts/build_exports.json index ead7fb94..d681655e 100644 --- a/hwe/ts/build_exports.json +++ b/hwe/ts/build_exports.json @@ -13,7 +13,6 @@ "bossInfo": "bossInfo.ts", "myPage": "myPage.ts", "extExpandCity": "extExpandCity.ts", - "dipcenter": "dipcenter.ts", "diplomacy": "diplomacy.ts", "currentCity": "currentCity.ts", "hallOfFame": "hallOfFame.ts", @@ -27,6 +26,8 @@ "v_board": "v_board.ts", "v_NPCControl": "v_NPCControl.ts", "v_join": "v_join.ts", - "v_main": "v_main.ts" + "v_main": "v_main.ts", + "v_dipcenter": "v_dipcenter.ts" + } } \ No newline at end of file diff --git a/hwe/ts/components/BoardArticle.vue b/hwe/ts/components/BoardArticle.vue index 56b6bb14..1ce03eb8 100644 --- a/hwe/ts/components/BoardArticle.vue +++ b/hwe/ts/components/BoardArticle.vue @@ -50,7 +50,7 @@ \ No newline at end of file diff --git a/hwe/ts/summernote-image-flip.ts b/hwe/ts/summernote-image-flip.ts index 67723ccd..9dd5c88b 100644 --- a/hwe/ts/summernote-image-flip.ts +++ b/hwe/ts/summernote-image-flip.ts @@ -1,6 +1,6 @@ /* Forked from https://github.com/asiffermann/summernote-image-title */ import $ from 'jquery'; -import 'summernote/dist/summernote-bs4.js'; +import 'summernote/dist/summernote-bs5.js'; $(function ($) { $.extend(true, $.summernote.lang, { diff --git a/hwe/ts/tiptap-ext/BackgroundColor.ts b/hwe/ts/tiptap-ext/BackgroundColor.ts new file mode 100644 index 00000000..1b964cb3 --- /dev/null +++ b/hwe/ts/tiptap-ext/BackgroundColor.ts @@ -0,0 +1,70 @@ +import { Extension } from '@tiptap/core' +import '@tiptap/extension-text-style' + +export type BackgroundColorOptions = { + types: string[], +} + +declare module '@tiptap/core' { + interface Commands { + backgroundColor: { + /** + * Set the text color + */ + setBackgroundColor: (color: string) => ReturnType, + /** + * Unset the text color + */ + unsetBackgroundColor: () => ReturnType, + } + } +} + +export const BackgroundColor = Extension.create({ + name: 'backgroundColor', + + addOptions() { + return { + types: ['textStyle'], + } + }, + + addGlobalAttributes() { + return [ + { + types: this.options.types, + attributes: { + backgroundColor: { + default: null, + parseHTML: element => element.style.backgroundColor.replace(/['"]+/g, ''), + renderHTML: attributes => { + if (!attributes.backgroundColor) { + return {} + } + + return { + style: `background-color: ${attributes.backgroundColor}`, + } + }, + }, + }, + }, + ] + }, + + addCommands() { + return { + setBackgroundColor: backgroundColor => ({ chain }) => { + return chain() + .setMark('textStyle', { backgroundColor }) + .run() + }, + unsetBackgroundColor: () => ({ chain }) => { + return chain() + .setMark('textStyle', { backgroundColor: null }) + .removeEmptyTextStyle() + .run() + }, + } + }, +}) diff --git a/hwe/ts/tiptap-ext/CustomImage.ts b/hwe/ts/tiptap-ext/CustomImage.ts new file mode 100644 index 00000000..5d6e2b1a --- /dev/null +++ b/hwe/ts/tiptap-ext/CustomImage.ts @@ -0,0 +1,82 @@ +//https://github.com/joevallender/tiptap2-image-example/blob/main/src/extensions/custom-image-3.js +import Image, { ImageOptions } from '@tiptap/extension-image' +import { mergeAttributes } from '@tiptap/core' + +export interface CustomImageOptions extends ImageOptions { + sizes: string[], +} + +declare module '@tiptap/core' { + interface Commands { + setImage: (options: { src: string, alt?: string, title?: string, size: string }) => ReturnType, + } +} + +export default Image.extend({ + name: 'custom-image', + + addOptions() { + return { + ...Image.options, + sizes: ['original', 'small', 'medium', 'large'], + } + }, + addAttributes() { + return { + src: { + default: null, + }, + alt: { + default: null, + }, + title: { + default: null, + }, + size: { + default: 'original', + rendered: false + }, + align: { + default: 'center', + rendered: false + } + } + }, + + addCommands() { + return { + // This is unchanged from the original + // Image setImage function + // However, if I extended addComands in + // the same way as addAttributes `this` + // seemed to lose context, so I've just + // copied it in here directly + setImage: (options) => ({ tr, commands }) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (tr.selection?.node?.type?.name == 'custom-image') { + return commands.updateAttributes('custom-image', options) + } + else { + return commands.insertContent({ + type: this.name, + attrs: options + }) + } + }, + } + }, + + renderHTML({ node, HTMLAttributes }) { + // When we render the HTML, grab the + // size and add an appropriate + // corresponding class + + HTMLAttributes.class = ' custom-image-' + node.attrs.size; + HTMLAttributes.class += ' custom-image-align-' + node.attrs.align; + return [ + 'img', + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes) + ] + } +}) \ No newline at end of file diff --git a/hwe/ts/tiptap-ext/FontSize.ts b/hwe/ts/tiptap-ext/FontSize.ts new file mode 100644 index 00000000..d2829991 --- /dev/null +++ b/hwe/ts/tiptap-ext/FontSize.ts @@ -0,0 +1,70 @@ +import { Extension } from '@tiptap/core'; +import '@tiptap/extension-text-style'; + +type FontSizeOptions = { + types: string[], +} + +declare module '@tiptap/core' { + interface Commands { + fontSize: { + /** + * Set the font size attribute + */ + setFontSize: (size: string) => ReturnType, + /** + * Unset the font size attribute + */ + unsetFontSize: () => ReturnType, + } + } +} + +export const FontSize = Extension.create({ + name: 'fontSize', + + addOptions() { + return { + types: ['textStyle'], + } + }, + addGlobalAttributes() { + return [ + { + types: this.options.types, + attributes: { + fontSize: { + default: null, + parseHTML: element => element.style.fontSize.replace(/['"]+/g, ''), + renderHTML: attributes => { + if (!attributes.fontSize) { + return {} + } + + return { + style: `font-size: ${attributes.fontSize}`, + } + }, + }, + }, + }, + ] + }, + + addCommands() { + return { + setFontSize: fontSize => ({ chain }) => { + return chain() + .setMark('textStyle', { fontSize }) + .run() + }, + unsetFontSize: () => ({ chain }) => { + return chain() + .setMark('textStyle', { fontSize: null }) + .removeEmptyTextStyle() + .run() + }, + } + }, + +}); \ No newline at end of file diff --git a/hwe/ts/util/getBase64FromFileObject.ts b/hwe/ts/util/getBase64FromFileObject.ts new file mode 100644 index 00000000..db3758b7 --- /dev/null +++ b/hwe/ts/util/getBase64FromFileObject.ts @@ -0,0 +1,17 @@ +import { unwrap } from "./unwrap"; + +//https://stackoverflow.com/questions/36280818/how-to-convert-file-to-base64-in-javascript +export function getBase64FromFileObject(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => { + let encoded = unwrap(reader.result).toString().replace(/^data:(.*,)?/, ''); + if ((encoded.length % 4) > 0) { + encoded += '='.repeat(4 - (encoded.length % 4)); + } + resolve(encoded); + }; + reader.onerror = error => reject(error); + }); +} \ No newline at end of file diff --git a/hwe/ts/v_NPCControl.ts b/hwe/ts/v_NPCControl.ts index 6827386e..110ad44a 100644 --- a/hwe/ts/v_NPCControl.ts +++ b/hwe/ts/v_NPCControl.ts @@ -1,7 +1,7 @@ import "@scss/common/bootstrap5.scss"; import { createApp } from 'vue' -import NPCControl from '@/NPCControl.vue'; +import NPCControl from '@/PageNPCControl.vue'; import BootstrapVue3 from 'bootstrap-vue-3' import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest'; diff --git a/hwe/ts/v_board.ts b/hwe/ts/v_board.ts index 5b0c498e..a44a58f3 100644 --- a/hwe/ts/v_board.ts +++ b/hwe/ts/v_board.ts @@ -1,5 +1,5 @@ import { createApp } from 'vue' -import Board from '@/Board.vue'; +import PageBoard from '@/PageBoard.vue'; import BootstrapVue3 from 'bootstrap-vue-3' import "@scss/common/bootstrap5.scss"; import 'bootstrap-vue-3/dist/bootstrap-vue-3.css' @@ -9,6 +9,6 @@ declare const isSecretBoard: boolean; setAxiosXMLHttpRequest(); -createApp(Board, { +createApp(PageBoard, { isSecretBoard }).use(BootstrapVue3).mount('#app') \ No newline at end of file diff --git a/hwe/ts/dipcenter.ts b/hwe/ts/v_dipcenter.ts similarity index 91% rename from hwe/ts/dipcenter.ts rename to hwe/ts/v_dipcenter.ts index 3fd91d7b..938f91a3 100644 --- a/hwe/ts/dipcenter.ts +++ b/hwe/ts/v_dipcenter.ts @@ -1,21 +1,21 @@ -import $ from 'jquery'; -import 'bootstrap'; -import 'summernote/dist/summernote-bs4'; -import 'summernote/dist/summernote-bs4.css'; -import '@/summernote-image-flip'; -import '@/summernote-ko-KR'; -import { activateFlip } from "@/legacy/activateFlip"; +import { createApp } from 'vue' +import PartialDipcenter from '@/PartialDipcenter.vue'; +import BootstrapVue3 from 'bootstrap-vue-3'; +import { htmlReady } from './util/htmlReady'; +//import { activateFlip } from './legacy/activateFlip'; +//import { activateFlip } from "@/legacy/activateFlip"; import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest'; +//import { htmlReady } from './util/htmlReady'; -declare const editable: boolean; +createApp(PartialDipcenter).use(BootstrapVue3).mount('#editorForm'); +setAxiosXMLHttpRequest(); -declare const storedData: { - nationMsg: string, - scoutMsg: string, -} -$(function ($) { - setAxiosXMLHttpRequest(); +htmlReady(function(){ + //activateFlip(); +}) + + /* function guiEditorInit($obj: JQuery, editable: boolean) { const $submitBtn = $obj.find('.submit'); const $noticeInput = $obj.find('.input_form'); @@ -145,5 +145,4 @@ $(function ($) { guiEditorInit($('#noticeForm'), editable); guiEditorInit($('#scoutMsgForm'), editable); activateFlip(); - -}) \ No newline at end of file + */ \ No newline at end of file diff --git a/hwe/ts/v_inheritPoint.ts b/hwe/ts/v_inheritPoint.ts index fc5f9372..1868b7e5 100644 --- a/hwe/ts/v_inheritPoint.ts +++ b/hwe/ts/v_inheritPoint.ts @@ -1,7 +1,7 @@ import "@scss/common/bootstrap5.scss"; import { createApp } from 'vue' -import InheritPoint from '@/inheritPoint.vue'; +import PageInheritPoint from '@/PageInheritPoint.vue'; import BootstrapVue3 from 'bootstrap-vue-3' -createApp(InheritPoint).use(BootstrapVue3).mount('#app'); \ No newline at end of file +createApp(PageInheritPoint).use(BootstrapVue3).mount('#app'); \ No newline at end of file diff --git a/hwe/ts/v_join.ts b/hwe/ts/v_join.ts index 74972f5b..748ea326 100644 --- a/hwe/ts/v_join.ts +++ b/hwe/ts/v_join.ts @@ -1,7 +1,7 @@ import { createApp } from 'vue' -import Join from '@/Join.vue'; +import PageJoin from '@/PageJoin.vue'; import BootstrapVue3 from 'bootstrap-vue-3' import "@scss/common/bootstrap5.scss"; -import 'bootstrap-vue-3/dist/bootstrap-vue-3.css' +import "@scss/editor_component.scss"; -createApp(Join).use(BootstrapVue3).mount('#app') \ No newline at end of file +createApp(PageJoin).use(BootstrapVue3).mount('#app') \ No newline at end of file diff --git a/hwe/ts/v_main.ts b/hwe/ts/v_main.ts index d20f92e7..83b6f15a 100644 --- a/hwe/ts/v_main.ts +++ b/hwe/ts/v_main.ts @@ -1,11 +1,12 @@ import '@scss/main.scss'; +import "@scss/common_legacy.scss"; exportWindow(scrollHardTo, 'scrollHardTo'); import { exportWindow } from '@util/exportWindow'; import { scrollHardTo } from '@util/scrollHardTo'; import { createApp } from 'vue' -import ReservedCommand from '@/ReservedCommand.vue'; +import PartialReservedCommand from '@/PartialReservedCommand.vue'; import BootstrapVue3 from 'bootstrap-vue-3' import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest'; import Multiselect from 'vue-multiselect'; @@ -15,6 +16,6 @@ import { auto500px } from './util/auto500px'; setAxiosXMLHttpRequest(); -createApp(ReservedCommand).use(BootstrapVue3).component('v-multiselect', Multiselect).mount('#reservedCommandList'); +createApp(PartialReservedCommand).use(BootstrapVue3).component('v-multiselect', Multiselect).mount('#reservedCommandList'); auto500px(); \ No newline at end of file diff --git a/hwe/v_NPCControl.php b/hwe/v_NPCControl.php index bf0058b9..2bf353ec 100644 --- a/hwe/v_NPCControl.php +++ b/hwe/v_NPCControl.php @@ -110,13 +110,8 @@ $lastSetters = [ 'defaultStatNPCMax' => GameConst::$defaultStatNPCMax, 'defaultStatMax' => GameConst::$defaultStatMax, ]) ?> - - - - - - + diff --git a/hwe/v_board.php b/hwe/v_board.php index af5288ca..cc8df8be 100644 --- a/hwe/v_board.php +++ b/hwe/v_board.php @@ -44,15 +44,11 @@ $boardName = $isSecretBoard ? '기밀실' : '회의실'; - - - - - $isSecretBoard, ]) ?> +
diff --git a/hwe/v_inheritPoint.php b/hwe/v_inheritPoint.php index ff288aac..c2d4db99 100644 --- a/hwe/v_inheritPoint.php +++ b/hwe/v_inheritPoint.php @@ -75,12 +75,8 @@ $lastInheritPointLogs = $db->query('SELECT server_id, year, month, date, text FR - - - - - + $items, 'currentInheritBuff' => $currentInheritBuff, diff --git a/hwe/v_join.php b/hwe/v_join.php index 75233fe4..a405877d 100644 --- a/hwe/v_join.php +++ b/hwe/v_join.php @@ -81,12 +81,9 @@ foreach(CityConst::all() as $city){ - - - - - + + UniqueConst::$serverID, 'nationList' => array_values($nationList), diff --git a/i_entrance/admin_userlist.php b/i_entrance/admin_userlist.php index 3257d92a..1999cc96 100644 --- a/i_entrance/admin_userlist.php +++ b/i_entrance/admin_userlist.php @@ -15,14 +15,11 @@ require(__DIR__ . '/../vendor/autoload.php'); - - - - - + + diff --git a/i_entrance/entrance.php b/i_entrance/entrance.php index 6663c37f..7db36e05 100644 --- a/i_entrance/entrance.php +++ b/i_entrance/entrance.php @@ -26,21 +26,16 @@ $acl = $session->acl; - - - - - - - - - + + + + diff --git a/i_entrance/user_info.php b/i_entrance/user_info.php index 5cf54173..8e15f529 100644 --- a/i_entrance/user_info.php +++ b/i_entrance/user_info.php @@ -15,16 +15,13 @@ require(__DIR__ . '/../vendor/autoload.php'); - - - - - + + diff --git a/index.php b/index.php index f4af944f..eaacd088 100644 --- a/index.php +++ b/index.php @@ -52,14 +52,8 @@ foreach (ServConfig::getServerList() as $setting) { var kakao_oauth_redirect_uri = ''; - - - - - - - + diff --git a/j_updateServer.php b/j_updateServer.php index 50ed0f47..8542a83e 100644 --- a/j_updateServer.php +++ b/j_updateServer.php @@ -140,7 +140,7 @@ if (!$v->validate()) { $target = Util::getPost('target'); $server = basename($request['server']); - +$settingBasePath = __DIR__ . "/{$server}/d_setting/"; $allowFullUpdate = in_array('fullUpdate', $session->acl[$server] ?? []); $allowFullUpdate |= $session->userGrade >= 6; @@ -244,20 +244,28 @@ if ($server == $baseServerName) { $version = getVersion(); $gitHash = getHash(); if ( - hash_file("sha256", __DIR__ . '/' . $server . '/d_setting/VersionGit.dynamic.orig.php') == - hash_file("sha256", __DIR__ . '/' . $server . '/d_setting/VersionGit.php') + hash_file("sha256", $settingBasePath . 'VersionGit.dynamic.orig.php') == + hash_file("sha256", $settingBasePath . 'VersionGit.php') ) { + + if (file_exists($settingBasePath . 'VersionGit.json')) { + unlink($settingBasePath . 'VersionGit.json'); + } $result = true; } else { $result = Util::generateFileUsingSimpleTemplate( - __DIR__ . '/' . $server . '/d_setting/VersionGit.orig.php', - __DIR__ . '/' . $server . '/d_setting/VersionGit.php', + $settingBasePath . 'VersionGit.orig.php', + $settingBasePath . 'VersionGit.php', [ 'verionGit' => $version, 'hash' => $gitHash ], true ); + file_put_contents($settingBasePath . 'VersionGit.json', Json::encode([ + 'versionGit' => $version, + 'hash' => $gitHash, + ])); } //git 업데이트했는데, package.json이 바뀌면 곤란하니까 @@ -333,14 +341,18 @@ $zip->close(); $version = getVersion($target); $gitHash = getHash($target); $result = Util::generateFileUsingSimpleTemplate( - __DIR__ . '/' . $server . '/d_setting/VersionGit.orig.php', - __DIR__ . '/' . $server . '/d_setting/VersionGit.php', + $settingBasePath . 'VersionGit.orig.php', + $settingBasePath . 'VersionGit.php', [ 'verionGit' => $version, 'hash' => $gitHash ], true ); +file_put_contents($settingBasePath . 'VersionGit.json', Json::encode([ + 'versionGit' => $version, + 'hash' => $gitHash, +])); genJS($server); $storage->$server = [$target, $version]; diff --git a/oauth_kakao/join.php b/oauth_kakao/join.php index 9dfabe59..8b7a8747 100644 --- a/oauth_kakao/join.php +++ b/oauth_kakao/join.php @@ -30,12 +30,8 @@ if ($canJoin != 'Y') { 회원가입 - - - - - + diff --git a/package.json b/package.json index d1b8245b..46d9a025 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,27 @@ "license": "MIT", "type": "module", "dependencies": { + "@popperjs/core": "^2.11.0", + "@tiptap/extension-color": "^2.0.0-beta.9", + "@tiptap/extension-image": "^2.0.0-beta.24", + "@tiptap/extension-link": "^2.0.0-beta.33", + "@tiptap/extension-text-align": "^2.0.0-beta.29", + "@tiptap/extension-text-style": "^2.0.0-beta.23", + "@tiptap/extension-underline": "^2.0.0-beta.22", + "@tiptap/starter-kit": "^2.0.0-beta.156", + "@tiptap/vue-3": "^2.0.0-beta.83", "@types/bootstrap": "^5.1.6", "@types/downloadjs": "^1.4.2", "@types/linkifyjs": "^2.1.4", + "@types/quill": "^2.0.9", "@types/select2": "^4.0.54", - "@types/summernote": "^0.8.6", + "@types/uuid": "^8.3.3", + "@vueup/vue-quill": "^1.0.0-beta.7", "async-validator": "^4.0.7", "axios": "^0.24.0", "bootstrap": "^5.1.3", "bootstrap-vue-3": "^0.1.0", + "buffer": "^6.0.3", "core-js": "^3.19.3", "date-fns": "^2.27.0", "downloadjs": "^1.4.7", @@ -38,7 +50,7 @@ "lodash": "^4.17.21", "query-string": "^7.0.1", "select2": "^4.0", - "summernote": "^0.8.20", + "uuid": "^8.3.2", "vue": "^3.2.2", "vue-multiselect": "^3.0.0-alpha.2", "vue-types": "^4.1.1", @@ -55,22 +67,23 @@ "@types/node": "^16.11.12", "@typescript-eslint/eslint-plugin": "^5.6.0", "@typescript-eslint/parser": "^5.6.0", - "@vue/compiler-sfc": "^3.2.24", + "@vue/compiler-sfc": "^3.2.26", "@vue/eslint-config-typescript": "^9.1.0", "babel-plugin-lodash": "^3.3.4", "babel-preset-modern-browsers": "^15.0.2", "bootswatch": "^5.1.3", "clean-terminal-webpack-plugin": "^3.0.0", "css-loader": "^6.5.1", - "esbuild-loader": "^2.16.0", + "esbuild-loader": "^2.17.0", "eslint": "^8.4.1", + "eslint-plugin-vue": "^8.2.0", "file-loader": "^6.2.0", "mini-css-extract-plugin": "^2.4.5", "pre-commit": "^1.2.2", - "sass": "^1.44.0", + "sass": "^1.45.0", "sass-loader": "^12.4.0", "style-loader": "^3.3.1", - "typescript": "^4.5.2", + "typescript": "^4.5.3", "url-loader": "^4.1.1", "vue-eslint-parser": "^8.0.1", "vue-loader": "^16.5.0", diff --git a/showErrorLog.php b/showErrorLog.php index 5917a601..fdad1df0 100644 --- a/showErrorLog.php +++ b/showErrorLog.php @@ -57,8 +57,9 @@ $err_logs = $fdb->select('err_log', [ - - + + + diff --git a/src/sammo/WebUtil.php b/src/sammo/WebUtil.php index cc93c471..5bb24034 100644 --- a/src/sammo/WebUtil.php +++ b/src/sammo/WebUtil.php @@ -139,6 +139,48 @@ class WebUtil return static::preloadAsset($path, 'script'); } + public static function printDist(string $type, string|array $entryName, bool $isDefer = false) + { + if (is_string($entryName)) { + $entryName = [$entryName]; + } + + $serverBasePath = \phpUri::parse(ServConfig::$serverWebPath)->path; + + if ($type == 'gateway') { + $serverBasePath .= "/dist_js/{$type}"; + $basePath = dirname(__DIR__, 2) . "/dist_js/{$type}"; + } else { + if (!class_exists('\\sammo\\VersionGit') || is_subclass_of('\\sammo\\VersionGit', '\\sammo\\VersionGitDynamic')) { + $version = DB::prefix() . '_dynamic'; + } else { + $version = VersionGit::getVersion(); + } + $serverBasePath .= "/dist_js/{$version}/{$type}"; + $basePath = dirname(__DIR__, 2) . "/dist_js/{$version}/{$type}"; + } + + $outputs = ["\n"]; + + foreach (["vendors", "common_ts", ...$entryName] as $moduleName) { + foreach (['js', 'css'] as $ext) { + $checkPath = $basePath . "/{$moduleName}.{$ext}"; + if (!file_exists($checkPath)) { + $outputs[] = "\n"; + continue; + } + $mtime = filemtime($checkPath); + if ($ext == 'css') { + $outputs[] = "\n"; + } else if ($ext == 'js') { + $typeText = $isDefer ? 'defer' : ''; + $outputs[] = "\n"; + } + } + } + return join("", $outputs); + } + public static function printJS(string $path, bool $isDefer = false) { //async 옵션 고려? @@ -214,13 +256,12 @@ class WebUtil return $purifier->purify($text); } - public static function errorBackMsg(string $msg, ?string $target=null): string + public static function errorBackMsg(string $msg, ?string $target = null): string { $jmsg = Json::encode($msg); - if(!$target){ + if (!$target) { $moveNext = 'history.go(-1);'; - } - else{ + } else { $moveNext = "location.replace('{$target}');"; } diff --git a/webpack.config.cjs b/webpack.config.cjs index f887875a..06e57d8a 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -6,12 +6,47 @@ const { resolve } = require('path'); const CleanTerminalPlugin = require('clean-terminal-webpack-plugin'); const { ESBuildMinifyPlugin } = require('esbuild-loader') const webpack = require('webpack'); +const fs = require('fs'); module.exports = (env, argv) => { const target = env.target ?? 'hwe'; const mode = argv.mode ?? 'production'; const tsDir = resolve(__dirname, `${target}/ts/`); const build_exports = require(`${tsDir}/build_exports.json`); + const versionGitPath = resolve(__dirname, target, 'd_setting', 'VersionGit.json'); + + const versionValue = (() => { + if (!fs.existsSync(versionGitPath)) { + return undefined; + } + const versionInfo = JSON.parse(fs.readFileSync(versionGitPath, 'utf-8')); + return versionInfo.versionGit; + })() + const versionTarget = versionValue ?? `${target}_dynamic`; + const outputPath = resolve(__dirname, 'dist_js', versionTarget); + fs.mkdirSync(outputPath, { + recursive: true + }); + + const genBuildHook = function (oTarget) { + const checkFilePath = resolve(outputPath, `build_${oTarget}.txt`); + let emitDone = false; + let writeDone = false; + return function (percentage, msg, ...args) { + if (msg == 'emitting') { + emitDone = true; + } + if (percentage == 0) { + if (fs.existsSync(checkFilePath)) { + fs.unlinkSync(checkFilePath); + } + } else if (percentage == 1 && emitDone && !writeDone) { + fs.writeFileSync(checkFilePath, new Date().toISOString(), 'utf-8'); + writeDone = true; + } + }; + }; + //TODO: esbuild에 browserslist 사용 가능하면 적용 //서버마다 ts 파일 구성이 다를 가능성이 높기 때문에 어떤 파일이 필요한지는 ts/build_exports.json을 확인한다. @@ -24,8 +59,35 @@ module.exports = (env, argv) => { entryIngame[entry] = `${tsDir}/${filePath}`; } + const optimization = { + splitChunks: { + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + priority: -10, + chunks: 'all', + reuseExistingChunk: true, + }, + default: { + name: 'common_ts', + minChunks: 2, + priority: -20, + chunks: 'all', + reuseExistingChunk: true, + }, + }, + }, + minimizer: [ + new ESBuildMinifyPlugin({ + css: true + }), + ], + moduleIds: 'deterministic', + }; + const ingame_vue = { - name: `ingame_${target}_vue`, + name: `ingame_${versionTarget}_vue`, resolve: { extensions: [".ts", ".tsx", ".vue", ".js"], alias: { @@ -33,41 +95,16 @@ module.exports = (env, argv) => { '@': tsDir, '@scss': path.resolve(tsDir, '../scss'), '@util': path.resolve(tsDir, 'util'), - } + }, }, mode, entry: entryIngameVue, output: { filename: '[name].js', - path: resolve(__dirname, `${target}/dist_js`) + path: resolve(outputPath, 'vue') }, devtool: 'source-map', - optimization: { - splitChunks: { - cacheGroups: { - commons: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors_vue', - priority: -10, - chunks: 'all', - reuseExistingChunk: true, - }, - default: { - name: 'common_vue', - minChunks: 2, - priority: -20, - chunks: 'all', - reuseExistingChunk: true, - }, - }, - }, - minimizer: [ - new ESBuildMinifyPlugin({ - css: true - }), - ], - moduleIds: 'deterministic', - }, + optimization, module: { rules: [ //FROM `vue inspect` and some tweaks @@ -79,7 +116,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'ts', - target: 'es2019', + target: 'es2021', } } ] @@ -92,7 +129,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'tsx', - target: 'es2019', + target: 'es2021', } } ] @@ -105,7 +142,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'js', - target: 'es2019', + target: 'es2021', } } ] @@ -128,55 +165,30 @@ module.exports = (env, argv) => { }, { test: /\.(png|jpe?g|gif|webp)$/, - use: [ - { - loader: 'file-loader', - options: { - name: '../dist_misc/[name].[contenthash:8].[ext]' - } - } - ] + use: ['file-loader'] }, { test: /\.(svg)$/, - use: [ - { - loader: 'file-loader', - options: { - name: '../dist_misc/[name].[contenthash:8].[ext]' - } - } - ] + use: ['file-loader'] }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/, - use: [ - { - loader: 'file-loader', - options: { - name: '../dist_misc/[name].[contenthash:8].[ext]' - } - } - ] + use: ['file-loader'] }, { test: /\.(woff2?|eot|ttf|otf)$/i, - use: [ - { - loader: 'file-loader', - options: { - name: '../dist_misc/[name].[contenthash:8].[ext]' - } - } - ] + use: ['file-loader'] }, ] }, plugins: [ new CleanTerminalPlugin(), new VueLoaderPlugin(), - new MiniCssExtractPlugin({ - filename: '../dist_css/[name].css' + new MiniCssExtractPlugin(), + new webpack.ProgressPlugin({ + percentBy: 'modules', + dependencies: false, + handler: genBuildHook('vue') }), //new BundleAnalyzerPlugin() ], @@ -185,7 +197,7 @@ module.exports = (env, argv) => { }, }; const ingame = { - name: `ingame_${target}`, + name: `ingame_${versionTarget}`, resolve: { extensions: [".js", ".ts", ".tsx"], alias: { @@ -198,33 +210,10 @@ module.exports = (env, argv) => { entry: entryIngame, output: { filename: '[name].js', - path: resolve(__dirname, `${target}/dist_js`) + path: resolve(outputPath, 'ts') }, devtool: 'source-map', - optimization: { - splitChunks: { - cacheGroups: { - commons: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'all', - }, - default: { - name: 'common_ts', - minChunks: 2, - priority: -20, - chunks: 'all', - reuseExistingChunk: true, - }, - }, - }, - minimizer: [ - new ESBuildMinifyPlugin({ - css: true - }), - ], - moduleIds: 'deterministic', - }, + optimization, module: { rules: [{ test: /\.ts$/, @@ -234,7 +223,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'ts', - target: 'es2019', + target: 'es2021', } } ] @@ -247,7 +236,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'tsx', - target: 'es2019', + target: 'es2021', } } ] @@ -260,7 +249,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'js', - target: 'es2019', + target: 'es2021', } } ] @@ -272,22 +261,16 @@ module.exports = (env, argv) => { }, plugins: [ new CleanTerminalPlugin(), - new MiniCssExtractPlugin({ - filename: '../dist_css/[name].css' - }), + new MiniCssExtractPlugin(), + new webpack.ProgressPlugin(genBuildHook('ts')), //new BundleAnalyzerPlugin() ], cache: { type: 'filesystem', }, - externals: { - // require("jquery") is external and available - // on the global var jQuery - "jQuery": "jquery" - } }; const gateway = { - name: 'gateway', + name: `gateway`, resolve: { extensions: [".js", ".ts", ".tsx"], alias: { @@ -307,33 +290,10 @@ module.exports = (env, argv) => { }, output: { filename: '[name].js', - path: path.resolve(__dirname, 'dist_js'), + path: resolve(__dirname, 'dist_js', 'gateway') }, devtool: 'source-map', - optimization: { - splitChunks: { - cacheGroups: { - commons: { - test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'all', - }, - default: { - name: 'common_ts', - minChunks: 2, - priority: -20, - chunks: 'all', - reuseExistingChunk: true, - }, - }, - }, - minimizer: [ - new ESBuildMinifyPlugin({ - css: true - }), - ], - moduleIds: 'deterministic', - }, + optimization, module: { rules: [{ test: /\.ts$/, @@ -343,7 +303,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'ts', - target: 'es2019', + target: 'es2021', } } ] @@ -356,7 +316,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'tsx', - target: 'es2019', + target: 'es2021', } } ] @@ -369,7 +329,7 @@ module.exports = (env, argv) => { loader: 'esbuild-loader', options: { loader: 'js', - target: 'es2019', + target: 'es2021', } } ] @@ -379,9 +339,8 @@ module.exports = (env, argv) => { }] }, plugins: [ - new MiniCssExtractPlugin({ - filename: '../dist_css/[name].css' - }), + new MiniCssExtractPlugin(), + new webpack.ProgressPlugin(genBuildHook('gateway')), //new BundleAnalyzerPlugin() ], cache: { @@ -389,10 +348,22 @@ module.exports = (env, argv) => { }, }; - if (target == 'hwe') { + if (env.WEBPACK_WATCH || !versionValue) { return [gateway, ingame_vue, ingame]; } - else { - return [ingame_vue, ingame]; + + const buildConfList = []; + if (target == 'hwe' && !fs.existsSync(resolve(outputPath, `build_gateway.txt`))) { + buildConfList.push(gateway); } + + if (!fs.existsSync(resolve(outputPath, `build_vue.txt`))) { + buildConfList.push(ingame_vue); + } + + if (!fs.existsSync(resolve(outputPath, `build_ts.txt`))) { + buildConfList.push(ingame); + } + + return buildConfList; }