Compare commits

..
105 Commits
Author SHA1 Message Date
Hide_D 3762d9050c fix: GetCityInfo에서 출력됨 2023-03-26 02:55:42 +09:00
Hide_D 75d88d48b6 feat,wip: GetCityInfo 2023-03-26 02:43:33 +09:00
Hide_D 633defcb21 feat: wip, 도시정보 2023-03-26 01:04:09 +09:00
Hide_D 9e997a7ee2 feat: 도시 장수 정의에 nationID를 추가 2023-03-26 00:58:53 +09:00
Hide_D 9a8f70d87b fix: 감찰부 안보이는 버그 수정
- query로 옮겨서 생기는 문제
2023-03-26 00:58:32 +09:00
Hide_D 7132aeab0c fix: installVue3Components() 호출부 통일 2023-03-26 00:48:05 +09:00
Hide_D 994c73adb2 feat: 설문조사 정보도 DB정보를 이용하여 한번만 처리 2023-03-25 03:07:38 +09:00
Hide_D 9206b74500 feat: 이미 읽은 메시지를 DB에서 처리 2023-03-25 02:09:23 +09:00
Hide_D 5294aefbbd misc: 동향 변경 안내 시간 단축 2023-03-24 03:03:50 +09:00
Hide_D 8f0f586af9 fix: 버그 수정 2023-03-24 02:44:14 +09:00
Hide_D 9121533b93 fix: 국가 승급을 Event로 떼내어야 함
- 부대장 지급보다 앞으로
2023-03-24 02:43:07 +09:00
Hide_D 90bff7b210 misc: 연도 업데이트 2023-03-22 23:22:46 +09:00
Hide_D 55f7b87ced misc: GetConst의 cache key를 getVersion으로 2023-03-22 23:19:28 +09:00
Hide_D bee4de377a feat: 버전 정보 페이지 추가 2023-03-22 23:09:53 +09:00
Hide_D b02911038b fix: 갱신시마다 커맨드 테이블을 다시 불러줘야 함 2023-03-22 22:58:05 +09:00
Hide_D 9b4d5455e5 feat: GetConst에서 버전 정보 반환 2023-03-22 22:54:47 +09:00
Hide_D ca3e64f3b9 feat: MenuItem에 funcCall 타입 추가후 처리 2023-03-22 22:44:42 +09:00
Hide_D 4d2b5ced82 feat: 메뉴 구성에 line 추가 2023-03-22 22:04:35 +09:00
Hide_D e385820301 fix: classMap에서 orig.php만 있고, 본 php는 없는 케이스 고려 2023-03-22 21:50:55 +09:00
Hide_D ec7c97d696 feat: hightlight btn, 토너먼트/베팅장 강조 2023-03-22 02:23:14 +09:00
Hide_D aae730d39c fix: gatewayButton 2023-03-21 01:51:39 +09:00
Hide_D 3c412f2803 fix: cr 시나리오 병종을 현재 버전에 맞게 수정 2023-03-21 01:44:27 +09:00
Hide_D 25769a9435 fix: sqlite3 db ignore 대상 추가 2023-03-21 01:42:25 +09:00
Hide_D 6c76d688b5 fix: 메시지 삭제 안되는 버그
- GetRecentMessage에서 keepRecent 관련 오동작 수정
  - 왜 이걸 넣었는지 생각해보기로..
2023-03-21 01:38:58 +09:00
Hide_D 790c58f2b6 feat: 메시지 빠른 답장 대상 지정 2023-03-20 02:12:57 +09:00
Hide_D 1eba863cc4 misc: 폰트 설정이 다르더라도 툴바 버튼 줄 수 유지 2023-03-20 01:13:21 +09:00
Hide_D fbe5739d82 feat: 메시지 응답시, 읽음 처리 2023-03-20 01:06:53 +09:00
Hide_D f8f8ef7dd3 misc: MainControlBar에 붙은 class 정리 2023-03-20 01:02:41 +09:00
Hide_D ecc375ef41 fix: customize scss에 맞게 다시 수정 2023-03-20 00:16:32 +09:00
Hide_D 9e17e58ecb dep: package update
- decl type 변경 포함
2023-03-20 00:02:04 +09:00
Hide_D 18f7e7b7c1 dep: package update 2023-03-19 23:12:09 +09:00
Hide_D b15b09cc1e dep: package update 2023-03-19 22:59:00 +09:00
Hide_D 49f2f85f79 dep: package-update 2023-03-19 17:45:17 +09:00
Hide_D 2245383d9e dep: remove bootstrap-vue-3 2023-03-19 17:17:45 +09:00
Hide_D e619a6b509 misc: 내무부에서 에디터 폼 최소 높이 높임 2023-03-19 16:59:13 +09:00
Hide_D fb9e750fe2 game: 외교권자가 아니면 외교 메시지 알림 없음 2023-03-19 16:51:06 +09:00
Hide_D 457aa0e4a5 misc: getNewMsgToast 힌트에 따라 수정 2023-03-19 15:38:49 +09:00
Hide_D 761b91b7db fix, refac: bvn에 맞게 tooltip directive 변경
- installVue3Component로 통합
- boostrap-vue-next 0.7.3 directive 문제 우회
2023-03-19 14:41:09 +09:00
Hide_D 31f4472a8a dep: upgrade bv3 bvn 2023-03-19 13:29:58 +09:00
Hide_D a79585f8de fix: 메시지 보러가기를 누르더라도 이미 읽음 처리를 해야함 2023-03-19 12:56:55 +09:00
Hide_D 69fbbbb51a feat: 개인/외교 메시지 수신시 버튼 추가 2023-03-19 12:54:53 +09:00
Hide_D 5eecbfc6f8 misc: package.json 요구로 임시 처리 2023-03-19 12:54:29 +09:00
Hide_D 9121780d82 feat: is1000pxMode에 widthMode 통합 2023-03-18 09:03:37 +09:00
Hide_D 6691aa3526 feat: PageFront에 토너먼트 베팅장 활성시 색 변경 2023-03-18 02:10:13 +09:00
Hide_D 582163ab46 fix: 부대장의 특기를 없앰.
- 특기 수령 년도를 999년으로 변경
2023-03-17 13:28:23 +09:00
Hide_D 394a70319f game: cr 시나리오에서 '척사'를 3등급 병종 문제로 제거 2023-03-17 02:18:23 +09:00
Hide_D 4d340abdcf feat: BaseAPI의 launch()에 타입 지정
- APIRecoveryType이 명시
2023-03-17 01:39:10 +09:00
Hide_D 6b9cfe46a0 feat: APIHelper에서 recovery 반환 타입 경로 추가 2023-03-17 01:18:20 +09:00
Hide_D 1d4707fb20 fix: recovery를 typescript API와 매칭 2023-03-17 01:16:55 +09:00
Hide_D d673024a10 feat: APIRecoveryType을 포함한 리턴 방법 2023-03-17 01:10:59 +09:00
Hide_D 3513aae088 fix: 지도 도시 민감도 문제 수정
- touchend는 touchmove와는 별개이므로 함께 처리
2023-03-17 00:30:22 +09:00
Hide_D 83c43d0261 fix: ProvideNPCTroopLeader 2023-03-16 23:59:24 +09:00
Hide_D 53cd8aeb5d fix: cr 시나리오에 선포가 없는 버그 수정 2023-03-16 19:27:28 +09:00
Hide_D 65b861d7ee fix: cr맵 배경 500px 2023-03-16 12:22:23 +09:00
Hide_D a5432e59d0 fix: CreateManyNPC 경고 제거 2023-03-16 03:49:19 +09:00
Hide_D e67b45e9cd game: 거울세계 구조 수정 2023-03-16 03:20:14 +09:00
Hide_D 8a8d9db7f9 game: 910 이벤트 시나리오 추가 수정
- 기본 이벤트 로직 오버라이드
  - 깃 끊김 없음
- 특수 커맨드(제한없는 건국, 인구이동, 맹훈련)
- 특수맵에 규모 적용
2023-03-16 01:24:06 +09:00
Hide_D 602cf3bf13 game: cr_건국,맹훈련,인구이동 추가
- 특수 맵 커맨드에 맞춤
- 건국: 소,중성 제한 없음
- 맹훈련: 훈련/사기진작의 2/3를 동시에
- 인구이동: 도시의 인구를 다른 곳으로 이동
2023-03-16 01:12:46 +09:00
Hide_D ab2e43e8dd fix: 국가가 하나도 없을 땐 CreateManyNPC가 동작하지 않아야 함 2023-03-16 00:07:04 +09:00
Hide_D 49b39c34eb fix: ProvideNPCTroopLeader는 국가가 없을땐 동작하지 않아야함 2023-03-16 00:04:33 +09:00
Hide_D fb5946fba5 feat: 소재 도시가 공백지여야하는 조건 작성 2023-03-15 23:19:01 +09:00
Hide_D 3ff4d51778 fix: 명령 선택시 지도의 배경이 안보이는 버그 수정 2023-03-15 04:11:50 +09:00
Hide_D 49d1bf4bad game: CR 맵 초기화 2023-03-15 03:48:37 +09:00
Hide_D 6a67a7de98 misc: 도시 렌더러에서 배경 클래스 지정 2023-03-15 02:11:47 +09:00
Hide_D f132d285e9 game: 랜덤임관 모드에서 초기 장수 제한 해제
- 사전 거병이 가능하므로, 시간에 따른 제한은 필요없을 것으로 판단
2023-03-15 01:15:10 +09:00
Hide_D f97b6e10d3 fix: 삼성 브라우저 다크모드 색상 틀어짐 수정 시도 2023-03-13 03:03:05 +09:00
Hide_D 90509516dd fix: Json::decode에서 빈줄은 array조차 아님 2023-03-13 02:44:58 +09:00
Hide_D 0a35505fa4 fix: 트래픽 일람에서 새 줄 파싱 문제 2023-03-13 02:43:44 +09:00
Hide_D 80a674436a fix: PageFront에서 부대 탑승여부가 보이지 않는 버그 2023-03-13 02:32:14 +09:00
Hide_D 50bf2a4614 fix: 도시 상인 % 표기 문제 수정 2023-03-13 00:00:01 +09:00
Hide_D 2f69be49e1 fix: 도시 정보에서 민심을 소수점 한자리로 제한 2023-03-12 18:48:50 +09:00
Hide_D 40fb8a4836 dep: lodash를 lodash-es 로 변경 2023-03-12 17:47:03 +09:00
Hide_D 0da9ffee9b fix: 일부 메인페이지 색상값을 옮겨오지 않은 버그 수정 2023-03-12 17:38:16 +09:00
Hide_D c88e3d1bfe fix: 메인, 사령부의 alert를 toast로 이동 2023-03-12 17:32:00 +09:00
Hide_D ae76ce0abd fix: PageFront 능력치 상승 기준이 엉뚱하게 잡혀있던 버그 수정 2023-03-12 17:17:53 +09:00
Hide_D d17b2518df 전역 하드코드 이벤트를 동적 변경 영역으로 이동 (#230)
기존에 작성해두었던 EventHandler 시스템으로 하드코드 이벤트 이동
- 매달
  - 보급선 설정
  - 전쟁 단기 수입 설정
  - 부대장 부여
- 1월
  - 유산 포인트 계산
  - 도시 인구 변화
  - 수입
  - 관직 제한 해제
  - 재난
  - 상인
  - 새해 알림
  - 특기 부여
- 4월
  - 관직 제한 해제
  - 재난
- 7월
  - 유산 포인트 계산
  - 도시 인구 변화
  - 수입
  - 관직 제한 해제
  - 재난
  - 상인
- 10월
  - 관직 제한 해제
  - 재난
- 천통 시
  - 유산 포인트 계산

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/230
2023-03-12 17:14:49 +09:00
Hide_D 4901a2d384 fix: 거병 시 인구 정보를 0이 아니라 null로 보내는 문제 수정 2023-03-12 16:38:32 +09:00
Hide_D 47bf5cdd17 misc: PageFront 로딩 직후에는 갱신 완료 메시지 없음 2023-03-09 20:32:10 +09:00
Hide_D 076c0cd604 fix: 메인 페이지 로그인, _119 페이지 링크 복구 2023-03-09 20:15:40 +09:00
Hide_D c4ccc451ec fix: 첫 건국 시 국가방침이 null임 2023-03-09 03:03:18 +09:00
Hide_D 3d9bb9c2e0 fix: index.php인경우 Session에 gameLogin 필요 2023-03-09 02:49:28 +09:00
Hide_D 4472cd0bdc fix: 가오픈 기간에 PageFront에 안오는 정보 수정 2023-03-09 02:48:21 +09:00
Hide_D efc36e223c misc: v_front -> index 2023-03-09 02:40:15 +09:00
Hide_D af2b82616f misc: index->old_index.php 2023-03-09 02:39:56 +09:00
Hide_D 6f5d7ff84b feat: Vue3로 새롭게 작성한 메인 페이지 (#229)
- v_front.php
- API 추가
  - General/GetFrontInfo
  - Global/GetGlobalMenu
- DTO 추가
  - MenuItem, MenuMulti, MenuSplit
- 글로벌 메뉴 출력 방식 변경
  - d_setting/GlobalMenu.php

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/229
2023-03-09 02:25:31 +09:00
Hide_D 4ba9468fae fix: 임시 토스트 본문 색상 변경 2023-03-09 02:18:04 +09:00
Hide_D 7905ddb7bf feat: scrollToSelector 2023-03-09 02:17:55 +09:00
Hide_D fdef4caa65 feat: 외부 호출이 불가능한 API 타입 정의 2023-03-09 02:17:41 +09:00
Hide_D ebaf63d541 feat: 10단위 column 분리 2023-03-09 02:17:00 +09:00
Hide_D 0e92973a05 fix: 누락된 메시지 def 수정 2023-03-09 02:16:05 +09:00
Hide_D 6a4fa8ee0d feat: Message 정의를 좀더 상세히 2023-03-09 02:15:42 +09:00
Hide_D 0081c86d1e fix: 국방 줄바꿈 수정 2023-03-05 00:09:59 +09:00
Hide_D 051fdee9b9 fix: MeekroDB에서 바뀐 설정 반영
- 설정하는 옵션이 기본값으로 변경
2023-03-04 14:16:14 +09:00
Hide_D 20330e19df fix: 불가침파기제의 warning 2023-03-01 12:43:30 +09:00
Hide_D bb5c9d8fd6 fix: CityConstBase warning 2023-03-01 12:38:45 +09:00
Hide_D 18ae530edf dep: php package update 2023-03-01 12:38:42 +09:00
Hide_D 294897df54 fix: Test 코드 변경 2023-03-01 12:38:33 +09:00
Hide_D 4fcafe88a7 fix: Session은 singleton이므로 생성자가 public이면 안됨 2023-03-01 04:33:13 +09:00
Hide_D 968e4afc8f fix: DummySession이 login 상태로 취급되지 않음 2023-03-01 04:29:37 +09:00
Hide_D 4193b884b0 fix: APIHelper DummySession 초기화 문제 2023-03-01 04:08:52 +09:00
Hide_D 9371de1b4a feat: PartialReservedCommand에 reloadCommandList 노출 2023-03-01 02:31:13 +09:00
Hide_D c5c7f96c1a feat, refac: 메인 페이지에서 커맨드 리스트를 동적으로 받아옴 2023-03-01 02:17:09 +09:00
Hide_D e721642a10 fix: timeout, retry 지정 2023-02-28 00:44:59 +09:00
Hide_D 4f0b18cc3c fix: DummySession, Session singleton 문제
- DummySession 호출 후 Session 호출시에도 DummySession이 나와야 함
- 함수 상속 관계 재 설정
2023-02-28 00:43:56 +09:00
Hide_D 904e26f56e fix: 토너먼트 자동개최모드 설정 관련 2023-02-24 20:02:58 +09:00
307 changed files with 14653 additions and 7651 deletions
-15
View File
@@ -1,15 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
+2
View File
@@ -67,3 +67,5 @@ ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
*.db-journal
+1
View File
@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="dark">
<title>닫혀 있습니다.</title>
<script>
setTimeout(function(){
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2022 Hide_D, 62che
Copyright (c) 2023 Hide_D, 62che
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+9 -9
View File
@@ -8,23 +8,23 @@
],
"config": {
"platform": {
"php": "8.1"
"php": "8.2"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"league/plates": "^3.5",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"symfony/lock": "^6.0",
"php-extended/php-tail": "^5.0",
"symfony/lock": "^6.2",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^2.1",
"phan/phan": "^5.3",
"nette/caching": "^3.0",
"illuminate/database": "^9.12",
"illuminate/events": "^9.12",
"phan/phan": "^5.4",
"nette/caching": "^3.2",
"illuminate/database": "^10.0",
"illuminate/events": "^10.0",
"php-ds/php-ds": "^1.4",
"hided62/ldto": "^1.0",
"league/uri": "^6.8"
@@ -48,6 +48,6 @@
]
},
"require-dev": {
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^10.0"
}
}
Generated
+798 -781
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -10,6 +10,7 @@ require(__DIR__ . '/../vendor/autoload.php');
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>설치</title>
-5
View File
@@ -61,11 +61,6 @@ class RootDB
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->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
return self::$uDB;
}
+58
View File
@@ -165,3 +165,61 @@
background: url('_tK_gameImagePath_/map/pokemon_v1/back_pal8.png') no-repeat;
background-size: 700px 500px;
}
/*CR 지도*/
.map_theme_cr .map_bglayer1{
background: url('_tK_gameImagePath_/map/cr/bg-fs8.png') no-repeat;
background-size: 700px 500px;
}
.map_theme_cr.map_detail .city_base .city_bg {
background-image: none !important;
width: 39.5px !important;
height: 39.5px !important;
left: 1px !important;
top: -4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail.small_width_map .city_base .city_bg {
background-image: none !important;
width: 28.5px !important;
height: 28.5px !important;
left: 6px !important;
top: 4px !important;
opacity: 0.5;
}
.map_theme_cr.map_detail .city_bg.bFF0000 { background-color: #FF0000; }
.map_theme_cr.map_detail .city_bg.b800000 { background-color: #800000; }
.map_theme_cr.map_detail .city_bg.bA0522D { background-color: #A0522D; }
.map_theme_cr.map_detail .city_bg.bFF6347 { background-color: #FF6347; }
.map_theme_cr.map_detail .city_bg.bFFA500 { background-color: #FFA500; }
.map_theme_cr.map_detail .city_bg.bFFDAB9 { background-color: #FFDAB9; }
.map_theme_cr.map_detail .city_bg.bFFD700 { background-color: #FFD700; }
.map_theme_cr.map_detail .city_bg.bFFFF00 { background-color: #FFFF00; }
.map_theme_cr.map_detail .city_bg.b7CFC00 { background-color: #7CFC00; }
.map_theme_cr.map_detail .city_bg.b00FF00 { background-color: #00FF00; }
.map_theme_cr.map_detail .city_bg.b808000 { background-color: #808000; }
.map_theme_cr.map_detail .city_bg.b008000 { background-color: #008000; }
.map_theme_cr.map_detail .city_bg.b2E8B57 { background-color: #2E8B57; }
.map_theme_cr.map_detail .city_bg.b008080 { background-color: #008080; }
.map_theme_cr.map_detail .city_bg.b20B2AA { background-color: #20B2AA; }
.map_theme_cr.map_detail .city_bg.b6495ED { background-color: #6495ED; }
.map_theme_cr.map_detail .city_bg.b7FFFD4 { background-color: #7FFFD4; }
.map_theme_cr.map_detail .city_bg.bAFEEEE { background-color: #AFEEEE; }
.map_theme_cr.map_detail .city_bg.b87CEEB { background-color: #87CEEB; }
.map_theme_cr.map_detail .city_bg.b00FFFF { background-color: #00FFFF; }
.map_theme_cr.map_detail .city_bg.b00BFFF { background-color: #00BFFF; }
.map_theme_cr.map_detail .city_bg.b0000FF { background-color: #0000FF; }
.map_theme_cr.map_detail .city_bg.b000080 { background-color: #000080; }
.map_theme_cr.map_detail .city_bg.b483D8B { background-color: #483D8B; }
.map_theme_cr.map_detail .city_bg.b7B68EE { background-color: #7B68EE; }
.map_theme_cr.map_detail .city_bg.bBA55D3 { background-color: #BA55D3; }
.map_theme_cr.map_detail .city_bg.b800080 { background-color: #800080; }
.map_theme_cr.map_detail .city_bg.bFF00FF { background-color: #FF00FF; }
.map_theme_cr.map_detail .city_bg.bFFC0CB { background-color: #FFC0CB; }
.map_theme_cr.map_detail .city_bg.bF5F5DC { background-color: #F5F5DC; }
.map_theme_cr.map_detail .city_bg.bE0FFFF { background-color: #E0FFFF; }
.map_theme_cr.map_detail .city_bg.bFFFFFF { background-color: #FFFFFF; }
.map_theme_cr.map_detail .city_bg.bA9A9A9 { background-color: #A9A9A9; }
+1
View File
@@ -21,6 +21,7 @@ $plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
<head>
<title>삼국지 모의전투 HiDCHe</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
+1
View File
@@ -19,6 +19,7 @@ $admin = getAdmin();
<head>
<title>게임관리</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
+1
View File
@@ -20,6 +20,7 @@ $db = DB::db();
<head>
<title>회원관리</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -38,6 +38,7 @@ function colorBlockedName($general)
<head>
<title>멀티관리</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -38,6 +38,7 @@ $sel2[$type2] = "selected";
<head>
<title>일제정보</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -83,6 +83,7 @@ $generalObj = General::createGeneralObjFromDB($gen);
<head>
<title>로그정보</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -30,6 +30,7 @@ $sel[$type] = "selected";
<head>
<title>외교정보</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -28,6 +28,7 @@ $templates = new \League\Plates\Engine(__DIR__ . '/templates');
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명장일람</title>
+1
View File
@@ -14,6 +14,7 @@ increaseRefresh("왕조일람", 1);
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title>
+1
View File
@@ -24,6 +24,7 @@ $serverID = $emperior['server_id'] ?? ($emperior['serverID'] ?? null);
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 왕조일람</title>
+1
View File
@@ -41,6 +41,7 @@ if ($gameStor->isunited) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 장수일람</title>
+1
View File
@@ -43,6 +43,7 @@ if ($scenarioIdx && key_exists($scenarioIdx, $scenarioList[$seasonIdx] ?? [])) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 명예의 전당</title>
+1
View File
@@ -26,6 +26,7 @@ if ($con >= 2) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력일람</title>
+1
View File
@@ -24,6 +24,7 @@ $sel[$type] = "selected";
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 빙의일람</title>
+7
View File
@@ -23,6 +23,12 @@ $online = [];
$curonline = getOnlineNum();
foreach ($log as $i => $value) {
$parse = Json::decode($value);
if(is_array($parse) === false){
continue;
}
if(count($parse) < 5){
continue;
}
$date[$i] = $parse[0];
$year[$i] = $parse[1];
$month[$i] = $parse[2];
@@ -52,6 +58,7 @@ if ($admin['maxonline'] < $curonline) {
<head>
<title><?= UniqueConst::$serverName ?>: 트래픽정보</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+1
View File
@@ -113,6 +113,7 @@ if ($str3) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 베팅장</title>
+1
View File
@@ -34,6 +34,7 @@ $templates = new \League\Plates\Engine('templates');
<head>
<title><?= UniqueConst::$serverName ?>: 도시정보</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
+1
View File
@@ -51,6 +51,7 @@ $templates = new \League\Plates\Engine('templates');
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 암행부</title>
+1
View File
@@ -42,6 +42,7 @@ if ($meLevel >= 5) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 인사부</title>
+1
View File
@@ -33,6 +33,7 @@ $sel = [$type => "selected"];
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력도시</title>
+1
View File
@@ -42,6 +42,7 @@ if ($gameStor->isunited) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력장수</title>
+1
View File
@@ -25,6 +25,7 @@ if ($nationID == 0) {
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 세력정보</title>
+1
View File
@@ -52,6 +52,7 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<title><?= UniqueConst::$serverName ?>: 내정보</title>
+2 -1
View File
@@ -106,6 +106,7 @@ $globalBetTotal = array_sum($globalBet);
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 토너먼트</title>
@@ -131,7 +132,7 @@ $globalBetTotal = array_sum($globalBet);
<td colspan=8>
<button type="button" class="btn btn-secondary" onclick='location.reload()'>갱신</button>
<?php if ($admin['tournament'] == 0) : ?>
<select name=auto size=1 style=color:white;background-color:black;>
<select name=trig size=1 style=color:white;background-color:black;>
<option style=color:white; value=0 <?= !$admin['tnmt_trig'] ? 'selected' : '' ?>>수동진행</option>
<option style=color:white; value=1 <?= $admin['tnmt_trig'] ? 'selected' : '' ?>>자동진행</option>
</select>
+1
View File
@@ -43,6 +43,7 @@ if ($nationID) {
<head>
<title><?= UniqueConst::$serverName ?>: 전투 시뮬레이터</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1100" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+2 -7
View File
@@ -52,8 +52,8 @@ class DB
/**
* DB 객체 생성
*
* @return \MeekroDB
*
* @return \MeekroDB
* @suppress PhanTypeMismatchProperty
*/
public static function db()
@@ -61,11 +61,6 @@ class 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->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
return self::$uDB;
}
+53
View File
@@ -0,0 +1,53 @@
<?php
namespace sammo;
use sammo\DTO\MenuItem;
use sammo\DTO\MenuMulti;
use sammo\DTO\MenuSplit;
//변경을 원한다면 파일을 복제 후 수정
class GlobalMenu {
/** @var (MenuItem|MenuMulti|MenuSplit)[] */
const version = 3;
static ?array $menu = null;
public static function getMenu(): array{
if(static::$menu !== null){
return static::$menu;
}
static::$menu = [
new MenuItem('천통국 베팅', 'v_nationBetting.php', condHighlightVar: 'nationBetting'),
new MenuMulti('게임정보', [
new MenuItem('세력일람', 'a_kingdomList.php', newTab: true),
new MenuItem('장수일람', 'a_genList.php', newTab: true),
new MenuItem('명장일람', 'a_bestGeneral.php', newTab: true),
new MenuItem('명예의전당', 'a_hallOfFame.php', newTab: true),
new MenuItem('왕조일람', 'a_emperior.php', newTab: true),
]),
new MenuItem('연감', 'v_history.php', newTab: true),
new MenuSplit(
new MenuItem('게시판', '/board/community', newTab: true),
[
new MenuItem('건의/제안', '/board/request', newTab: true),
new MenuItem('팁/강좌', '/board/tip', newTab: true),
new MenuItem('패치 내역', '/board/patch', newTab: true),
]
),
new MenuSplit(
new MenuItem('공식 오픈 톡', 'https://open.kakao.com/o/', newTab: true),
[
new MenuItem('잡담 오픈 톡', 'https://open.kakao.com/o/', newTab: true)
],
),
new MenuItem('전투 시뮬레이터', 'battle_simulator.php', newTab: true),
new MenuMulti('기타 정보', [
new MenuItem('접속량정보', 'a_traffic.php', newTab: true),
new MenuItem('빙의일람', 'a_npcList', newTab: true, condShowVar: 'npcMode'),
]),
new MenuItem('설문조사', 'v_vote.php', newTab: true, condHighlightVar: 'vote'),
];
return static::$menu;
}
}
-71
View File
@@ -7,7 +7,6 @@ use Ds\Set;
use sammo\Enums\AuctionType;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use sammo\Event\Action;
require_once 'process_war.php';
require_once 'func_gamerule.php';
@@ -1224,76 +1223,6 @@ function updateOnline()
$gameStor->online_nation = join(', ', $onlineNation);
}
function addAge(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//나이와 호봉 증가
$db->update('general', [
'age' => $db->sqleval('age+1'),
], true);
$db->update('general', [
'belong' => $db->sqleval('belong+1')
], 'nation != 0');
[$startYear, $year, $month] = $gameStor->getValuesAsArray(['startyear', 'year', 'month']);
if ($year >= $startYear + 3) {
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,aux from general where specage<=age and special=%s', GameConst::$defaultSpecialDomestic) as $general) {
$generalID = $general['no'];
$special = SpecialityHelper::pickSpecialDomestic(
$rng,
$general,
(Json::decode($general['aux'])['prev_types_special']) ?? []
);
$specialClass = buildGeneralSpecialDomesticClass($special);
$specialText = $specialClass->getName();
$db->update('general', [
'special' => $special
], 'no=%i', $generalID);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
foreach ($db->query('SELECT no,name,nation,leadership,strength,intel,npc,dex1,dex2,dex3,dex4,dex5,aux from general where specage2<=age and special2=%s', GameConst::$defaultSpecialWar) as $general) {
$generalID = $general['no'];
$generalAux = Json::decode($general['aux']);
$updateVars = [];
if (key_exists('inheritSpecificSpecialWar', $generalAux)) {
$special2 = $generalAux['inheritSpecificSpecialWar'];
unset($generalAux['inheritSpecificSpecialWar']);
$updateVars['aux'] = Json::encode($generalAux);
} else {
$special2 = SpecialityHelper::pickSpecialWar(
$rng,
$general,
($generalAux['prev_types_special2']) ?? []
);
}
$specialClass = buildGeneralSpecialWarClass($special2);
$specialText = $specialClass->getName();
$updateVars['special2'] = $special2;
$db->update('general', $updateVars, 'no=%i', $general['no']);
$logger = new ActionLogger($generalID, $general['nation'], $year, $month);
$josaUl = JosaUtil::pick($specialText, '을');
$logger->pushGeneralActionLog("특기 【<b><L>{$specialText}</></b>】{$josaUl} 익혔습니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("특기 【<b><C>{$specialText}</></b>】{$josaUl} 습득");
}
}
}
function turnDate($curtime)
{
$db = DB::db();
+4 -342
View File
@@ -4,6 +4,7 @@ namespace sammo;
use sammo\DTO\AuctionInfo;
use sammo\Enums\AuctionType;
use sammo\Enums\EventTarget;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
@@ -184,27 +185,6 @@ function updateGeneralNumber()
refreshNationStaticInfo();
}
function updateYearly()
{
//통계
checkStatistic();
}
//관직 변경 해제
function updateQuaterly()
{
$db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [
'chief_set' => 0,
], true);
//관직 변경 제한 해제
$db->update('city', [
'officer_set' => 0,
], true);
}
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly()
{
@@ -220,58 +200,6 @@ function preUpdateMonthly()
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크
checkSupply();
//미보급도시 10% 감소
$db->update('city', [
'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [
'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID);
}
//민심30이하 공백지 처리
$lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) {
continue;
}
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
}
if ($lostCities) {
foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
}
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [
'nation' => 0,
'officer_set' => 0,
'conflict' => '{}',
'term' => 0,
'front' => 0
], 'city IN %li', array_keys($lostCities));
}
//접률감소, 건국제한-1
$db->update('general', [
@@ -289,9 +217,6 @@ function preUpdateMonthly()
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->develcost = $develcost;
//매달 사망자 수입 결산
processWarIncome();
//계략, 전쟁표시 해제
$db->update('city', [
'state' => $db->sqleval(<<<EOD
@@ -498,8 +423,6 @@ function postUpdateMonthly(RandUtil $rng)
if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander($rng);
}
// 작위 업데이트
updateNationState();
updateGeneralNumber();
refreshNationStaticInfo();
// 천통여부 검사
@@ -542,269 +465,6 @@ function checkWander(RandUtil $rng)
}
}
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$year = $admin['year'];
$month = $admin['month'];
$startYear = $admin['startyear'];
$assemblerCnts = [];
$nationCityCounts = [];
foreach($db->queryAllLists('SELECT nation, count(*) FROM city WHERE LEVEL>=4 GROUP BY nation') as [$nationID, $cityCnt]){
$nationCityCounts[$nationID] = $cityCnt;
}
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
$assemblerCnts[$nationID] = $assemblerCnt;
};
$nationLevelByCityCnt = [
0, //방랑군
1, //호족
2, //군벌
5, //주자사
8, //주목
11, //공
16, //왕
21, //황제
];
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$nationID = $nation['nation'];
$cityCnt = $nationCityCounts[$nationID] ?? 0;
/** @var int */
$nationlevel = 0;
foreach($nationLevelByCityCnt as $cmpNationLevel => $cmpCityCnt){
if($cityCnt < $cmpCityCnt){
break;
}
$nationlevel = $cmpNationLevel;
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel,
'gold' => $db->sqleval('gold + %i', $nationlevel * 1000),
'rice' => $db->sqleval('rice + %i', $nationlevel * 1000),
];
$nationName = $nation['name'];
$lordName = $db->queryFirstField('SELECT name FROM general WHERE nation = %i AND officer_level = 12', $nationID);
$oldNationLevelText = getNationLevel($oldLevel);
$nationLevelText = getNationLevel($nationlevel);
$logger = new ActionLogger(0, $nationID, $year, $month, false);
$josaYi = JosaUtil::pick($lordName, '이');
switch ($nationlevel) {
case 7: //황제
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></> {$oldNationLevelText} <Y>{$lordName}</>{$josaYi} <C>{$nationLevelText}</>{$josaRo} 옹립");
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6: //왕
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 책봉");
break;
case 5: //공
case 4: //주목
case 3: //주자사
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명되었습니다.");
$logger->pushNationalHistoryLog("<D><b>{$nationName}</b></>의 <Y>{$lordName}</>{$josaYi} <C>$nationLevelText</>{$josaRo} 임명됨");
break;
case 2: //군벌
$josaRa = JosaUtil::pick($nationName, '라');
$josaRo = JosaUtil::pick($nationLevelText, '로');
$logger->pushGlobalHistoryLog("<Y><b>【작위】</b></><Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나섰습니다.");
$logger->pushNationalHistoryLog("<Y>{$lordName}</>{$josaYi} 독립하여 <D><b>{$nationName}</b></>{$josaRa}는 <C>$nationLevelText</>{$josaRo} 나서다");
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$logger->flush();
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc', 'aux'], 2);
$chiefID = null;
$uniqueLotteryWeightList = [];
$relYear = $year - $startYear;
$maxTrialCountByYear = 1;
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
[$targetYear, $targetTrialCnt] = $tmpVals;
if ($relYear < $targetYear) {
break;
}
$maxTrialCountByYear = $targetTrialCnt;
}
foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) {
$chiefID = $nationGen->getID();
}
$trialCnt = min($maxTrialCountByYear, count(GameConst::$allItems));
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$trialCnt -= 1;
}
}
if ($trialCnt <= 0) {
continue;
}
$score = $nationGen->getVar('belong') + 10;
if ($nationGen->getVar('officer_level') == 12) {
$score += 60;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 30;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 15;
}
$score *= 2 ** $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
$nationLevelUpRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'nationLevelUp',
$year,
$month,
$nationID
)));
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = $nationLevelUpRNG->choiceUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
$givenUniqueRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'givenUnique',
$year,
$month,
$nationID,
$winnerObj->getID(),
)));
giveRandomUniqueItem($givenUniqueRNG, $winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
if ($chiefID) {
$chiefObj = General::createGeneralObjFromDB($chiefID, ['belong', 'npc', 'aux'], 2);
$chiefObj->increaseInheritancePoint(InheritanceKey::unifier, 250 * $levelDiff);
$chiefObj->applyDB($db);
}
}
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
$maxAssemblerCnt = [
1 => 0,
2 => 1,
3 => 3,
4 => 4,
5 => 6,
6 => 7,
7 => 9
][$nationlevel] ?? 0;
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
$troopLeaderRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
UniqueConst::$hiddenSeed,
'troopLeader',
$year,
$month,
$nationID
)));
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
$troopLeaderRng,
sprintf('부대장%4d', $lastAssemblerID),
false,
null,
$nation['nation']
);
$npcObj->setAffinity(999)->setStat(10, 10, 10)
->setSpecialSingle('척사')->setEgo('che_은둔')
->setKillturn(70)->setGoldRice(0, 0)
->setNPCType(5)->fillRemainSpecAsZero($admin);
$npcObj->build($admin);
$npcID = $npcObj->getGeneralID();
$db->insert('troop', [
'troop_leader' => $npcID,
'name' => $npcObj->getGeneralName(),
'nation' => $nation['nation'],
]);
$db->update('general', [
'troop' => $npcID
], 'no=%i', $npcID);
$cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
_setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
$assemblerCnt += 1;
$gameStor->assembler_id = $lastAssemblerID;
}
}
}
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function checkStatistic()
{
$db = DB::db();
@@ -1090,7 +750,9 @@ function checkEmperior()
};
}
}
processSumInheritPointRank();
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::United);
foreach ($allUserGenerals as $genObj) {
$inheritPointManager->mergeTotalInheritancePoint($genObj);
$inheritPointManager->applyInheritanceUser($genObj->getVar('owner'));
+6
View File
@@ -12,6 +12,7 @@ function printLimitMsg($turntime)
<head>
<title>접속제한</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
@@ -118,6 +119,11 @@ function backButton()
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('./')>돌아가기</button><br>";
}
function gatewayButton()
{
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('../')>돌아가기</button><br>";
}
function CoreBackButton()
{
return "<button type='button' class='btn btn-primary back_btn' onclick=location.replace('v_chiefCenter.php')>돌아가기</button><br>";
+1
View File
@@ -25,6 +25,7 @@ function requireAdminPermissionHTML()
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
+16 -281
View File
@@ -4,173 +4,32 @@ namespace sammo;
use sammo\Enums\InheritanceKey;
use sammo\Enums\RankColumn;
use Ds\Map;
use sammo\Enums\ResourceType;
use sammo\Event\Action;
/**
* 시간 단위로 일어나는 이벤트들에 대한 함수 모음
*/
/** @deprecated */
function processSumInheritPointRank(){
$db = DB::db();
$generals = General::createGeneralObjListFromDB(null, null, 2);
$points = new Map();
$points->allocate(count($generals));
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] = 0;
}
foreach(InheritanceKey::cases() as $key){
if($key === InheritanceKey::previous){
continue;
}
$subPoints = InheritancePointManager::getInstance()->getInheritancePointFromAll($generals, $key);
foreach($generals as $general){
$generalID = $general->getID();
$points[$generalID] += $subPoints[$generalID] ?? 0;
}
}
$pointsPairs = [];
foreach($points as $generalID => $point){
$pointsPairs[] = [
'nation_id' => $generals[$generalID]->getNationID(),
'general_id' => $generalID,
'type' => RankColumn::inherit_point_earned_by_merge->value,
'value' => $point,
];
}
//XXX: multiple batch update가 제공되지 않으므로..
$db->delete('rank_data', '`type` = %s', RankColumn::inherit_point_earned_by_merge->value);
$db->insert('rank_data', $pointsPairs);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT SUM(`value`) FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` IN %ls) WHERE D.`type` = %s',
[RankColumn::inherit_point_earned_by_action->value, RankColumn::inherit_point_earned_by_merge->value],
RankColumn::inherit_point_earned->value
);
$db->query(
'UPDATE `rank_data` D SET `value` = (SELECT `value` FROM `rank_data` S WHERE S.general_id = D.general_id AND S.`type` = %s) WHERE D.`type` = %s',
RankColumn::inherit_point_spent_dynamic->value,
RankColumn::inherit_point_spent->value
);
}
//1월마다 실행
function processSpring() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
// 1월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'gold'=>$db->sqleval('IF(gold > 10000, gold * 0.97, gold * 0.99)')
], 'gold > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'gold'=>$db->sqleval('IF(gold > 100000, gold * 0.95, IF(gold > 10000, gold * 0.97, gold * 0.99))')
], 'gold > 1000');
$admin = $gameStor->getValues(['year', 'month']);
pushGlobalHistoryLog(["<R>★</>{$admin['year']}{$admin['month']}월: <S>모두들 즐거운 게임 하고 계신가요? ^^ <Y>매너 있는 플레이</> 부탁드리고, <M>지나친 훼접</>은 삼가주세요~</>"], $admin['year'], $admin['month']);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env);
}
/** @deprecated */
function processGoldIncome() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = [];
$nationList = $db->query('SELECT name,nation,capital,gold,level,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,gold,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getGoldIncome($nationID, $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['gold'] += $income;
// 기본량도 안될경우
if($nation['gold'] < GameConst::$basegold) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['gold'] - GameConst::$basegold < $outcome) {
$realoutcome = $nation['gold'] - GameConst::$basegold;
$nation['gold'] = GameConst::$basegold;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['gold'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['gold'] = Util::valueFit($nation['gold'], GameConst::$basegold);
$adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ")
." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과금 : ".tab2((string)$nation['gold'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 금 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_gold = $income;
$db->update('nation', [
'gold'=>$nation['gold']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$gold = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('gold', $gold);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$goldText = number_format($gold);
$logger->pushGeneralActionLog("봉급으로 금 <C>$goldText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>봄이 되어 봉록에 따라 자금이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::gold->value])->run($e_env);
}
function popIncrease() {
@@ -304,29 +163,6 @@ function getGoldIncome(int $nationID, int $nationLevel, float $taxRate, int $cap
return $cityIncome;
}
function processWarIncome() {
$db = DB::db();
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
foreach(getAllNationStaticInfo() as $nation){
if($nation['level'] <= 0){
continue;
}
$nationID = $nation['nation'];
$income = getWarGoldIncome($nation['type'], $cityListByNation[$nationID]??[]);
$db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $income)
], 'nation=%i', $nationID);
}
// 10%수입, 20%부상병
$db->update('city', [
'pop'=>$db->sqleval('pop + dead * %d', 0.2),
'dead'=>0
], true);
}
function getWarGoldIncome(string $nationType, array $cityList){
$nationTypeObj = buildNationTypeClass($nationType);
@@ -338,115 +174,14 @@ function getWarGoldIncome(string $nationType, array $cityList){
return $cityIncome;
}
//7월마다 실행
function processFall() {
$db = DB::db();
// 7월엔 무조건 내정 1% 감소
$db->update('city',[
'dead'=>0,
'agri'=>$db->sqleval('agri * 0.99'),
'comm'=>$db->sqleval('comm * 0.99'),
'secu'=>$db->sqleval('secu * 0.99'),
'def'=>$db->sqleval('def * 0.99'),
'wall'=>$db->sqleval('wall * 0.99'),
],true);
//인구 증가
popIncrease();
// > 10000 유지비 3%, > 1000 유지비 1%
// 유지비 1%
$db->update('general', [
'rice'=>$db->sqleval('IF(rice > 10000, rice * 0.97, rice * 0.99)')
], 'rice > 1000');
// > 100000 유지비 5%, > 100000 유지비 3%, > 1000 유지비 1%
$db->update('nation', [
'rice'=>$db->sqleval('IF(rice > 100000, rice * 0.95, IF(rice > 10000, rice * 0.97, rice * 0.99))')
], 'rice > 1000');
}
/** @deprecated */
function processRiceIncome() {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$adminLog = [];
$nationList = $db->query('SELECT name,level,nation,capital,rice,rate_tmp,bill,type from nation');
$cityListByNation = Util::arrayGroupBy($db->query('SELECT * FROM city'), 'nation');
$generalRawListByNation = Util::arrayGroupBy($db->query('SELECT no,name,nation,rice,officer_level,dedication,city FROM general WHERE npc != 5'), 'nation');
//국가별 처리
foreach($nationList as $nation) {
$nationID = $nation['nation'];
$generalRawList = $generalRawListByNation[$nationID];
$income = getRiceIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$income += getWallIncome($nation['nation'], $nation['level'], $nation['rate_tmp'], $nation['capital'], $nation['type'], $cityListByNation[$nationID]??[]);
$originoutcome = getOutcome(100, $generalRawList);
$outcome= Util::round($nation['bill'] / 100 * $originoutcome);
// 실제 지급량 계산
$nation['rice'] += $income;
// 기본량도 안될경우
if($nation['rice'] < GameConst::$baserice) {
$realoutcome = 0;
// 실지급률
$ratio = 0;
//기본량은 넘지만 요구량이 안될경우
} elseif($nation['rice'] - GameConst::$baserice < $outcome) {
$realoutcome = $nation['rice'] - GameConst::$baserice;
$nation['rice'] = GameConst::$baserice;
// 실지급률
$ratio = $realoutcome / $originoutcome;
} else {
$realoutcome = $outcome;
$nation['rice'] -= $realoutcome;
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['rice'] = Util::valueFit($nation['rice'], GameConst::$baserice);
$adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ")
." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
." // 실제 : ".tab2((string)$realoutcome,6," ")
." // 지급률 : ".tab2((string)round($ratio*100,2),5," ")
." % // 결과곡 : ".tab2((string)$nation['rice'],6," ");
$incomeText = number_format($income);
$incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_rice = $income;
$db->update('nation', [
'rice'=>$nation['rice']
], 'nation=%i', $nationID);
// 각 장수들에게 지급
foreach ($generalRawList as $rawGeneral) {
$generalObj = new General($rawGeneral, null, null, null, $year, $month, false);
$rice = Util::round(getBill($generalObj->getVar('dedication'))*$ratio);
$generalObj->increaseVar('rice', $rice);
$logger = $generalObj->getLogger();
if($generalObj->getVar('officer_level') > 4){
$logger->pushGeneralActionLog($incomeLog, $logger::PLAIN);
}
$riceText = number_format($rice);
$logger->pushGeneralActionLog("봉급으로 쌀 <C>$riceText</>을 받았습니다.", $logger::PLAIN);
$generalObj->applyDB($db);
}
}
$logger = new ActionLogger(0, 0, $year, $month);
$logger->pushGlobalHistoryLog('<W><b>【지급】</b></>가을이 되어 봉록에 따라 군량이 지급됩니다.');
$logger->flush();
pushAdminLog($adminLog);
$e_env = $gameStor->getValues(['startyear', 'year', 'month']);
$e_env['currentEventID'] = 0;
Action::build(["ProcessIncome", ResourceType::rice->value])->run($e_env);
}
function getRiceIncome(int $nationID, int $nationLevel, float $taxRate, int $capitalID, string $nationType, ?array $cityList) {
+21 -429
View File
@@ -2,452 +2,44 @@
namespace sammo;
use sammo\DTO\VoteInfo;
include "lib.php";
include "func.php";
Session::requireLogin()->loginGame()->setReadOnly();
$session = Session::requireLogin()->loginGame()->setReadOnly();
$userID = Session::getUserID();
$mapName = GameConst::$mapName;
increaseRefresh("메인", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$userID) {
header('Location:..');
die();
}
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
$me = $db->queryFirstRow(
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i',
$userID
);
//그새 사망이면
if ($me === null) {
$session->logoutGame();
header('Location: ../');
die();
}
$gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$generalObj = General::createGeneralObjFromDB($me['no']);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
$lastVoteID = $gameStor->lastVote;
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= $serverName ?>: 메인</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', 'v_main', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<title><?= UniqueConst::$serverName ?>: 메인</title>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'commandList' => getCommandTable($generalObj),
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
'serverName' => UniqueConst::$serverName,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
], false) ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS("js/map/theme_{$mapName}.js") ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printDist('vue', 'v_front', true) ?>
</head>
<body class="img_back sam-color-<?= $nationColorType ?>">
<div id="container" class="bg0">
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></button></div>
</div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(2) ?></div>
<div class="s-border-t col py-2 col-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4">
<?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<div style="display:inline-block;"><?= $plock ? ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell">
<?php
?>
<?php if ($lastVote === null) : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $lastVote->title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-8 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
</div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2">
<?= commandButton([
'splitBtnBegin' => '<div class="btn-group">',
'splitBtnEnd' => '</div>',
'splitZoneSign' => '<button type="button" class="btn btn-sammo-nation dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>',
'splitZoneBegin' => '<ul class="dropdown-menu dropdown-menu-end">',
'splitZoneEnd' => '</ul>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'btn btn-sammo-nation',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
])
?></div>
</div>
</div>
</div>
<div id="actionMiniPlateSub" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-3 d-grid"><button type='button' class="btn btn-dark" onclick="scrollHardTo('reservedCommandList')">명령으로</button></div>
<div class="col-5 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col-md-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div>
<div class="col-md-6" id="general_log-position">
<div class="bg1 center s-border-tb"><b>개인 기록</b></div>
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
</div>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div>
<div id="message_board" class="row gx-0">
<div class="message_input_form bg0 gx-0 row">
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid">
<select id="mailbox_list" size="1" class="form-control bg-dark text-white">
</select>
</div>
<div id="msg_input-col" class="col-12 col-md-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control">
</div>
<div id="msg_submit-col" class="col-6 col-md-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&amp;갱신</button></div>
</div>
<div class="col-md-6 board_side bg0"><a id="public_talk_position"></a>
<div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="national_talk_position"></a>
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="private_talk_position"></a>
<div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="diplomacy_talk_position"></a>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
</section>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div><?= banner() ?>
</div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
</div>
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
<div class="container-fluid px-0">
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto">
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-sammo-base2" id="navbarGlobal" role="button" data-bs-toggle="dropdown" aria-expanded="false">
외부 메뉴
</div>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="navbarGlobal" id="navbarGlobalItems">
<?= allButton($gameStor->npcmode == 1, ['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle btn btn-sammo-nation" id="navbarNation" role="button" data-bs-toggle="dropdown" aria-expanded="false">
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton([
'btnBegin' => '<li>',
'btnEnd' => '</li>',
'splitMainBegin' => '<div class="d-none">',
'splitMainEnd' => '</div>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'dropdown-item',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
]) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-dark" id="navbarQuick" role="button" data-bs-toggle="dropdown" aria-expanded="false">
빠른 이동
</div>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown" id="navbarQuickItems">
<li><a class="dropdown-item disabled">국가 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('nation-msg-position')" class="dropdown-item">방침</button></li>
<li><button type="button" onclick="scrollHardTo('reservedCommandList')" class="dropdown-item">명령</button></li>
<li><button type="button" onclick="scrollHardTo('nation-position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('general-position')" class="dropdown-item">장수</button></li>
<li><button type="button" onclick="scrollHardTo('cityInfo')" class="dropdown-item">도시</button></li>
<li><a class="dropdown-item disabled">동향 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('mapZone')" class="dropdown-item">지도</button></li>
<li><button type="button" onclick="scrollHardTo('general_public_record-position')" class="dropdown-item">동향</button></li>
<li><button type="button" onclick="scrollHardTo('general_log-position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('world_history-position')" class="dropdown-item">정세</button></li>
<li><span>&nbsp;</span></li>
<li><a class="dropdown-item disabled">메시지</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('public_talk_position')" class="dropdown-item">전체</button></li>
<li><button type="button" onclick="scrollHardTo('national_talk_position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('private_talk_position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('diplomacy_talk_position')" class="dropdown-item">외교</button></li>
<li><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></li>
</ul>
</li>
<li class="nav-item">
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
</li>
</ul>
</div>
</div>
</nav>
<body>
<div id="app"></div>
</body>
</html>
+1
View File
@@ -28,6 +28,7 @@ if ($session->userGrade < 5 && !$allowReset) {
<head>
<title>설치</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
+1
View File
@@ -21,6 +21,7 @@ if ($session->userGrade == 5) {
<head>
<title>설치</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
+22
View File
@@ -0,0 +1,22 @@
function getCityPosition(){
return {"1":["서량",127,101],"2":["무도",127,222],"3":["성도",127,344],"4":["건녕",127,384],"5":["안정",167,141],"6":["한중",167,222],"7":["검각",167,263],"8":["자동",167,303],"9":["강주",167,344],"10":["장안",208,182],"11":["영안",208,384],"12":["홍농",248,182],"13":["완",248,222],"14":["양양",248,303],"15":["강릉",248,344],"16":["무릉",248,384],"17":["영릉",248,425],"18":["낙양",289,182],"19":["신야",289,263],"20":["강하",289,344],"21":["장사",289,384],"22":["계양",289,425],"23":["남해",289,465],"24":["업",329,101],"25":["진유",329,141],"26":["허창",329,182],"27":["여남",329,222],"28":["시상",329,344],"29":["평원",370,60],"30":["복양",370,101],"31":["초",370,141],"32":["수춘",370,222],"33":["단양",370,263],"34":["여강",370,303],"35":["계",410,20],"36":["남피",410,60],"37":["소패",410,141],"38":["건업",410,222],"39":["북평",451,20],"40":["북해",451,101],"41":["하비",451,141],"42":["광릉",451,182],"43":["오",451,263],"44":["회계",451,303],"45":["양평",491,20],"46":["국내",532,20],"47":["한",532,60],"48":["사비",532,101],"49":["매소",572,60],"50":["서라벌",572,101],"51":["운남",127,425],"52":["천수",127,182],"53":["졸본",572,20]};
}
function formatCityInfo(city) {
var regionMap = {"하북":1,"1":"하북","중원":2,"2":"중원","서북":3,"3":"서북","서촉":4,"4":"서촉","남중":5,"5":"남중","초":6,"6":"초","오월":7,"7":"오월","동이":8,"8":"동이"};
var levelMap = {"수":1,"1":"수","진":2,"2":"진","관":3,"3":"관","이":4,"4":"이","소":5,"5":"소","중":6,"6":"중","대":7,"7":"대","특":8,"8":"특"};
var region_str = regionMap[city.region];
var level_str = levelMap[city.level];
city.text = '【' + region_str + '|' + level_str + '】' + city.name;
city.region_str = region_str;
city.level_str = level_str;
return city;
}
+3
View File
@@ -9,6 +9,9 @@ $loader->addClassMap((function () {
$d_settingMap = [];
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
$filepath = str_replace('.orig.php', '.php', $filepath);
if(!file_exists($filepath)) {
continue;
}
$filename = basename($filepath);
$classname = explode('.', $filename)[0];
$d_settingMap['sammo\\'.$classname] = $filepath;
+453
View File
@@ -0,0 +1,453 @@
<?php
namespace sammo;
use sammo\DTO\VoteInfo;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->loginGame()->setReadOnly();
$userID = Session::getUserID();
increaseRefresh("메인", 1);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$userID) {
header('Location:..');
die();
}
//턴 실행.
TurnExecutionHelper::executeAllCommand();
if (!$session->isGameLoggedIn()) {
header('Location:..');
die();
}
$me = $db->queryFirstRow(
'SELECT no,con,turntime,newmsg,newvote,`officer_level` from general where owner = %i',
$userID
);
//그새 사망이면
if ($me === null) {
$session->logoutGame();
header('Location: ../');
die();
}
$gameStor->cacheAll(true);
if ($me['newmsg'] == 1 || $me['newvote'] == 1) {
$db->update('general', [
'newmsg' => 0,
'newvote' => 0
], 'owner=%i', $userID);
}
$plock = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$generalObj = General::createGeneralObjFromDB($me['no']);
$generalObj->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $generalObj->getCityID()));
$scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if ($nationID) {
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheAll();
}
if ($gameStor->extended_general == 0) {
$extend = "표준";
} else {
$extend = "확장";
}
if ($gameStor->fiction == 0) {
$fiction = "사실";
} else {
$fiction = "가상";
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else if ($gameStor->npcmode == 1) {
$npcmode = "가능";
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$serverName = UniqueConst::$serverName;
$serverCnt = $gameStor->server_cnt;
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$myNationStatic = getNationStaticInfo($generalObj->getNationID());
$nationColorType = substr($myNationStatic['color'] ?? '#000000', 1);
$autorunUser = ($gameStor->autorun_user) ?? [];
$otherTextInfo = [];
if ($gameStor->join_mode == 'onlyRandom') {
$otherTextInfo[] = '랜덤 임관 전용';
}
if ($autorunUser['limit_minutes'] ?? false) {
$otherTextInfo[] = getAutorunInfo($autorunUser);
}
if (!$otherTextInfo) {
$otherTextInfo = '표준';
} else {
$otherTextInfo = join(', ', $otherTextInfo);
}
$lastVoteID = $gameStor->lastVote;
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?= $serverName ?>: 메인</title>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=500" />
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('vue', 'v_main', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
//deprecated, staticValues를 이용할 것
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'staticValues' => [
'serverName' => $serverName,
'serverCnt' => $serverCnt,
'serverNick' => DB::prefix(),
'serverID' => UniqueConst::$serverID,
'maxTurn' => GameConst::$maxTurn,
'maxPushTurn' => 12,
'serverNow' => TimeUtil::now(false),
'lastExecuted' => $gameStor->turntime,
'isLocked' => $plock,
'isTournamentActive' => $isTournamentActive,
'isBettingActive' => $isBettingActive,
'mapName' => GameConst::$mapName,
'unitSet' => GameConst::$unitSet,
]
]) ?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head>
<body class="img_back sam-color-<?= $nationColorType ?>">
<div id="container" class="bg0">
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></button></div>
</div>
<div class="tb_layout row gx-0">
<div id="server_title" class="row py-2 center">
<h3>삼국지 모의전투 HiDCHe <?= $serverName . $serverCnt ?>기 <span class="avoid-wrap">(<font color=cyan><?= $scenario ?></font>)</span></h3>
</div>
<div class="row center gx-0">
<div class="s-border-t col py-2 col-8 col-md-4" style="color:<?= $color ?>;">
<?= $scenario ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC 수, 상성 : <?= $extend ?>,<?= $fiction ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
NPC선택 : <?= $npcmode ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
토너먼트 : <?= getTournamentTermText($gameStor->turnterm) ?>
</div>
<div class="s-border-t col py-2 col-4 col-md-2" style="color:<?= $color ?>;">
기타 설정: <?= $otherTextInfo ?>
</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(2) ?></div>
<div class="s-border-t col py-2 col-4 col-md-2">전체 접속자 수 : <?= $gameStor->online_user_cnt ?> 명</div>
<div class="s-border-t col py-2 col-4 col-md-2">턴당 갱신횟수 : <?= $gameStor->conlimit ?>회</div>
<div class="s-border-t col py-2 col-8 col-md-4"><?= info(3) ?></div>
<div class="s-border-t py-2 col col-6 col-md-4">
<?php if ($isTournamentActive) : ?>
↑<span style='color:cyan'><?= (['전력전', '통솔전', '일기토', '설전',])[$gameStor->tnmt_type] ?? '' ?> <?= getTournament($gameStor->tournament) ?> <?= getTournamentTime() ?></span>↑
<?php else : ?>
<span style='color:magenta'>현재 토너먼트 경기 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<div style="display:inline-block;"><?= $plock ? ("<span style='color:magenta;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") : ("<span style='color:cyan;'>동작 시각: " . substr($gameStor->turntime, 5, 14) . "</span>") ?></div>
</div>
<div class="s-border-t py-2 col col-6 col-md-2">
<?php if ($auctionCount > 0) : ?>
<span style='color:cyan'><?= $auctionCount ?>건</span> 거래 진행중
<?php else : ?>
<span style='color:magenta'>진행중 거래 없음</span>
<?php endif; ?>
</div>
<div class="s-border-t py-2 col col-6 col-md-4 vote-cell">
<?php
?>
<?php if ($lastVote === null) : ?>
<span style='color:magenta'>진행중 설문 없음</span>
<?php else : ?>
<span style='color:cyan'>설문 진행중</span> : <span><?= $lastVote->title ?></span>
<?php endif; ?>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">접속중인 국가: <?= $gameStor->online_nation ?></div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">운영자 메세지 : <span style='color:yellow;'><?= $gameStor->msg ?></span></div>
</div>
<div class="row gx-0">
<div class="col s-border-t py-2" id="nation-msg-position">
<div class="px-2">【 국가방침 】</div>
<div id='nation-msg-box'>
<div id='nation-msg'><?= nationMsg($generalObj) ?></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col s-border-t px-2 py-2">
【 접속자 】<?= onlinegen($generalObj) ?>
</div>
</div>
<?php if ($session->userGrade >= 5) : ?>
<div class="row">
<div class="col">
<a href='_admin1.php' target='_blank'><button type='button'>게임관리</button></a>
<a href='_admin2.php' target='_blank'><button type='button'>회원관리</button></a>
<a href='_admin4.php' target='_blank'><button type='button'>멀티관리</button></a>
<a href='_admin5.php' target='_blank'><button type='button'>일제정보</button></a>
<a href='_admin7.php' target='_blank'><button type='button'>로그정보</button></a>
<a href='_admin8.php' target='_blank'><button type='button'>외교정보</button></a>
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php elseif ($session->userGrade == 4) : ?>
<div class="row">
<div class="col">
<a href='_119.php' target='_blank'><button type='button'>119</button></a>
</div>
</div>
<?php endif; ?>
<div id="map_view" class="gx-0">
<div id="mapZone" class="view-item"><?= getMapHtml() ?></div>
<div class="view-item" id="reservedCommandZone">
<div id="reservedCommandList"></div>
<div id="actionMiniPlate" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-8 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
</div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="nation-position"><?php myNationInfo($generalObj); ?></div>
<div id="general-position"><?php generalInfo($generalObj); ?></div>
<div id="generalCommandButton" class="row gx-0">
<div class="buttonPlate bg2">
<?= commandButton([
'splitBtnBegin' => '<div class="btn-group">',
'splitBtnEnd' => '</div>',
'splitZoneSign' => '<button type="button" class="btn btn-sammo-nation dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>',
'splitZoneBegin' => '<ul class="dropdown-menu dropdown-menu-end">',
'splitZoneEnd' => '</ul>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'btn btn-sammo-nation',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
])
?></div>
</div>
</div>
</div>
<div id="actionMiniPlateSub" class="gx-0 row">
<div class="col">
<div class="gx-1 row">
<div class="col-3 d-grid"><button type='button' class="btn btn-dark" onclick="scrollHardTo('reservedCommandList')">명령으로</button></div>
<div class="col-5 d-grid"><button type='button' class='btn btn-sammo-base2 refreshPage'>갱 신</button></div>
<div class="col-4 d-grid"><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></div>
</div>
</div>
</div>
<div class="row gx-0">
<div class="col-md-6" id="general_public_record-position">
<div class="bg1 center s-border-tb"><b>장수 동향</b></div>
<div id="general_public_record" style="text-align:left;"><?= formatHistoryToHTML(getGlobalActionLogRecent(15)) ?></div>
</div>
<div class="col-md-6" id="general_log-position">
<div class="bg1 center s-border-tb"><b>개인 기록</b></div>
<div id="general_log" style="text-align:left;"><?= formatHistoryToHTML(getGeneralActionLogRecent($me['no'], 15)) ?></div>
</div>
<div class="col-12" id="world_history-position">
<div class="bg1 center s-border-tb"><b>중원 정세</b></div>
<div id="world_history" colspan=2 style="text-align:left;"><?= formatHistoryToHTML(getGlobalHistoryLogRecent(15)) ?></div>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div>
<div id="message_board" class="row gx-0">
<div class="message_input_form bg0 gx-0 row">
<div id="mailbox_list-col" class="col-6 col-md-2 d-grid">
<select id="mailbox_list" size="1" class="form-control bg-dark text-white">
</select>
</div>
<div id="msg_input-col" class="col-12 col-md-8 d-grid">
<input type="text" id="msg_input" maxlength="99" class="form-control">
</div>
<div id="msg_submit-col" class="col-6 col-md-2 d-grid"><button id="msg_submit" class="btn btn-primary">서신전달&amp;갱신</button></div>
</div>
<div class="col-md-6 board_side bg0"><a id="public_talk_position"></a>
<div class="board_header bg0">전체 메시지(최고99자)</div>
<section class="public_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="public">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="national_talk_position"></a>
<div class="board_header bg0">국가 메시지(최고99자)</div>
<section class="national_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="national">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="private_talk_position"></a>
<div class="board_header bg0">개인 메시지(최고99자)</div>
<section class="private_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="private">이전 메시지 불러오기</button></div>
</section>
</div>
<div class="col-md-6 board_side bg0"><a id="diplomacy_talk_position"></a>
<div class="board_header bg0">외교 메시지(최고99자)</div>
<section class="diplomacy_message">
<div class="d-grid"><button type="button" class="load_old_message btn btn-secondary" data-msg_type="diplomacy">이전 메시지 불러오기</button></div>
</section>
</div>
</div>
<div class="row toolbars gx-0">
<div class="buttonPlate"><?= allButton($gameStor->npcmode == 1) ?></div><?= banner() ?>
</div>
</div>
<?php
if ($con == 1) {
MessageBox("접속제한이 얼마 남지 않았습니다!");
}
if ($me['newmsg'] == 1) {
MessageBox("새로운 서신이 도착했습니다!");
}
if ($me['newvote'] == 1) {
$develcost = $gameStor->develcost * 5;
MessageBox("설문조사에 참여하시면 금{$develcost}과 유니크템을 드립니다! (우측 상단 설문조사 메뉴)");
}
?>
</div>
<nav class="navbar navbar-expand fixed-bottom navbar-dark bg-dark d-sm-block d-md-none p-0" id="navbar500">
<div class="container-fluid px-0">
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mx-auto">
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-sammo-base2" id="navbarGlobal" role="button" data-bs-toggle="dropdown" aria-expanded="false">
외부 메뉴
</div>
<ul class="dropdown-menu dropdown-menu-start" aria-labelledby="navbarGlobal" id="navbarGlobalItems">
<?= allButton($gameStor->npcmode == 1, ['btnBegin' => '<li>', 'btnEnd' => '</li>', 'btnClass' => 'dropdown-item']) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle btn btn-sammo-nation" id="navbarNation" role="button" data-bs-toggle="dropdown" aria-expanded="false">
국가 메뉴
</div>
<ul class="dropdown-menu" aria-labelledby="navbarNation" id="navbarNationItems">
<?= commandButton([
'btnBegin' => '<li>',
'btnEnd' => '</li>',
'splitMainBegin' => '<div class="d-none">',
'splitMainEnd' => '</div>',
'splitSubBtnBegin' => '<li>',
'splitSubBtnEnd' => '</li>',
'btnClass' => 'dropdown-item',
'btnSplitClass' => 'dropdown-item',
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive
]) ?>
</ul>
</li>
<li class="nav-item dropup">
<div class="dropdown-toggle text-white btn btn-dark" id="navbarQuick" role="button" data-bs-toggle="dropdown" aria-expanded="false">
빠른 이동
</div>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown" id="navbarQuickItems">
<li><a class="dropdown-item disabled">국가 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('nation-msg-position')" class="dropdown-item">방침</button></li>
<li><button type="button" onclick="scrollHardTo('reservedCommandList')" class="dropdown-item">명령</button></li>
<li><button type="button" onclick="scrollHardTo('nation-position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('general-position')" class="dropdown-item">장수</button></li>
<li><button type="button" onclick="scrollHardTo('cityInfo')" class="dropdown-item">도시</button></li>
<li><a class="dropdown-item disabled">동향 정보</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('mapZone')" class="dropdown-item">지도</button></li>
<li><button type="button" onclick="scrollHardTo('general_public_record-position')" class="dropdown-item">동향</button></li>
<li><button type="button" onclick="scrollHardTo('general_log-position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('world_history-position')" class="dropdown-item">정세</button></li>
<li><span>&nbsp;</span></li>
<li><a class="dropdown-item disabled">메시지</a></button></li>
<hr class="dropdown-divider">
</hr>
<li><button type="button" onclick="scrollHardTo('public_talk_position')" class="dropdown-item">전체</button></li>
<li><button type="button" onclick="scrollHardTo('national_talk_position')" class="dropdown-item">국가</button></li>
<li><button type="button" onclick="scrollHardTo('private_talk_position')" class="dropdown-item">개인</button></li>
<li><button type="button" onclick="scrollHardTo('diplomacy_talk_position')" class="dropdown-item">외교</button></li>
<li><button type='button' class='btn btn-sammo-base2' onclick="location.replace('../')">로비로</button></li>
</ul>
</li>
<li class="nav-item">
<a class="refreshPage btn btn-sammo-base2 text-white" role="button">갱신</a>
</li>
</ul>
</div>
</div>
</nav>
</body>
</html>
+5 -33
View File
@@ -2,6 +2,7 @@
namespace sammo;
use sammo\Enums\EventTarget;
function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{
@@ -549,23 +550,10 @@ function ConquerCity(array $admin, General $general, array $city)
$gameStor = KVStorage::getStorage($db, 'game_env');
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "OCCUPY_CITY" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
if(TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::OccupyCity)){
$gameStor->cacheAll();
}
if ($e_env !== null) {
$gameStor->resetCache();
}
// 국가 멸망시
if ($defenderNationID && $db->queryFirstField('SELECT count(city) FROM city WHERE nation = %i', $defenderNationID) === 1) {
@@ -661,27 +649,11 @@ function ConquerCity(array $admin, General $general, array $city)
}
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * FROM event WHERE target = "DESTROY_NATION" ORDER BY `priority` DESC, `id` ASC') as $rawEvent) {
if ($e_env === null) {
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent($e_env);
}
if ($e_env !== null) {
$gameStor->resetCache();
}
TurnExecutionHelper::runEventHandler($db, $gameStor, EventTarget::DestroyNation);
// 멸망이 아니면
} else {
// 태수,군사,종사 일반으로...
// 태수,군사,종사 일반으로...
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0,
+1
View File
@@ -11,6 +11,7 @@ include "func.php";
<head>
<meta charset="UTF-8">
<meta name="color-scheme" content="dark">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>최근 지도</title>
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionBuyRice;
use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\General;
@@ -32,7 +33,7 @@ class BidBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Auction;
use sammo\Session;
use DateTimeInterface;
use sammo\AuctionSellRice;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\General;
@@ -31,7 +32,7 @@ class BidSellRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Auction;
use sammo\Session;
use DateTimeInterface;
use sammo\AuctionUniqueItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -33,7 +34,7 @@ class BidUniqueAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$auctionID = $this->args['auctionID'];
$amount = $this->args['amount'];
@@ -8,6 +8,7 @@ use sammo\AuctionSellRice;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\Validator;
use sammo\General;
@@ -29,7 +30,7 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
@@ -8,6 +8,7 @@ use sammo\AuctionUniqueItem;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\Enums\InheritanceKey;
use sammo\InheritancePointManager;
@@ -37,7 +38,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
@@ -8,6 +8,7 @@ use sammo\AuctionUniqueItem;
use sammo\DB;
use sammo\DTO\AuctionBidItem;
use sammo\DTO\AuctionInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\AuctionType;
use sammo\TimeUtil;
use sammo\Util;
@@ -24,7 +25,7 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionBuyRice;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -52,7 +53,7 @@ class OpenBuyRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
/** @var int */
$amount = $this->args['amount'];
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionSellRice;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -52,7 +53,7 @@ class OpenSellRiceAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
/** @var int */
$amount = $this->args['amount'];
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\AuctionUniqueItem;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\General;
@@ -49,7 +50,7 @@ class OpenUniqueAuction extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$itemID = $this->args['itemID'];
$amount = $this->args['amount'];
+2 -1
View File
@@ -7,6 +7,7 @@ use DateTimeInterface;
use sammo\Betting;
use sammo\DB;
use sammo\DTO\BettingItem;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\GameConst;
use sammo\KVStorage;
@@ -39,7 +40,7 @@ class Bet extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
/** @var int */
$bettingID = $this->args['bettingID'];
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\DTO\BettingInfo;
use sammo\Enums\APIRecoveryType;
use sammo\KVStorage;
use sammo\Util;
use sammo\Validator;
@@ -32,7 +33,7 @@ class GetBettingDetail extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\DTO\BettingInfo;
use sammo\Enums\APIRecoveryType;
use sammo\KVStorage;
use sammo\Validator;
@@ -29,7 +30,7 @@ class GetBettingList extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+332
View File
@@ -0,0 +1,332 @@
<?php
namespace sammo\API\City;
use ArrayObject;
use Ds\Set;
use sammo\CityConst;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\General;
use sammo\Json;
use sammo\Session;
use sammo\Util;
use sammo\Validator;
use function sammo\calcLeadershipBonus;
use function sammo\checkLimit;
use function sammo\checkSecretPermission;
use function sammo\getAllNationStaticInfo;
use function sammo\getBillByLevel;
use function sammo\getDedLevelText;
use function sammo\getHonor;
use function sammo\getNationStaticInfo;
use function sammo\getOfficerLevelText;
use function sammo\increaseRefresh;
class GetCityInfo extends \sammo\BaseAPI
{
const FAR_CITY = 0;
const NEAR_CITY = 1;
const ON_CITY = 2;
const OUR_NATION = 3;
static $viewColumns = [
'no' => self::NEAR_CITY,
'name' => self::NEAR_CITY,
'nation' => self::NEAR_CITY,
'npc' => self::NEAR_CITY,
'injury' => self::NEAR_CITY,
'leadership' => self::NEAR_CITY,
'strength' => self::NEAR_CITY,
'intel' => self::NEAR_CITY,
'picture' => self::NEAR_CITY,
'imgsvr' => self::NEAR_CITY,
'city' => self::NEAR_CITY,
'officer_level' => self::NEAR_CITY,
'officer_city' => self::NEAR_CITY,
'defence_train' => self::OUR_NATION,
'crewtype' => self::OUR_NATION,
'crew' => self::ON_CITY,
'train' => self::OUR_NATION,
'atmos' => self::OUR_NATION,
];
static $columnRemap = [
'nation' => 'nationID',
];
static $customViewColumns = [
'officerLevel' => self::NEAR_CITY,
'officerLevelText' => self::NEAR_CITY,
'lbonus' => self::NEAR_CITY,
'reservedCommand' => self::OUR_NATION,
'isOurNation' => self::NEAR_CITY,
];
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('int', 'troopID');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
private function getOfficerLevel($rawGeneral)
{
$level = $rawGeneral['officer_level'];
return $level;
}
private function filterCity(array $rawCity, int $showLevel)
{
$cityID = $rawCity['city'];
$db = DB::db();
$officerList = $db->query(
'SELECT no, npc, name, nation, picture, imgsvr FROM general WHERE city = %i AND 2 <= officer_level AND officer_level <= 4',
$cityID
);
$filteredCity = [
'city' => $cityID,
'name' => $rawCity['name'],
'level' => $rawCity['level'],
'nation' => $rawCity['nation'],
'supply' => $rawCity['supply'],
'pop_max' => $rawCity['pop_max'],
'agri_max' => $rawCity['agri_max'],
'comm_max' => $rawCity['comm_max'],
'secu_max' => $rawCity['secu_max'],
'trade' => $rawCity['trade'],
'def_max' => $rawCity['def_max'],
'wall_max' => $rawCity['wall_max'],
'region' => $rawCity['region'],
'officerList' => $officerList,
];
if ($showLevel >= self::ON_CITY) {
$filteredCity = array_merge($filteredCity, [
'pop' => $rawCity['pop'],
'agri' => $rawCity['agri'],
'comm' => $rawCity['comm'],
'secu' => $rawCity['secu'],
'def' => $rawCity['def'],
'wall' => $rawCity['wall'],
'officer_set' => $rawCity['officer_set'],
]);
}
return $filteredCity;
}
private function getGeneralList(int $cityID, int $nationID, int $showLevel)
{
if ($showLevel == self::FAR_CITY) {
return [
'column' => [],
'list' => []
];
}
$db = DB::db();
$nationStaticList = getAllNationStaticInfo();
$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE city = %i ORDER BY turntime ASC', Util::formatListOfBackticks(array_keys(static::$viewColumns)), $cityID), 'no');
$ourNationGeneralIDList = new Set();
foreach ($rawGeneralList as $rawGeneral) {
if ($rawGeneral['nation'] == $nationID) {
$ourNationGeneralIDList->add($rawGeneral['no']);
}
}
$reservedCommand = [];
$reservedCommandTargetGeneralIDList = [];
foreach ($rawGeneralList as $rawGeneral) {
if ($rawGeneral['nation'] != $nationID) {
continue;
}
if ($rawGeneral['npc'] < 2) {
$reservedCommandTargetGeneralIDList[$rawGeneral['no']] = $rawGeneral['no'];
}
}
if ($reservedCommandTargetGeneralIDList) {
$rawTurnList = $db->query(
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
array_values($reservedCommandTargetGeneralIDList)
);
foreach ($rawTurnList as $rawTurn) {
[
'general_id' => $generalID,
'action' => $action,
'arg' => $arg,
'brief' => $brief,
] = $rawTurn;
if (!key_exists($generalID, $reservedCommand)) {
$reservedCommand[$generalID] = [];
}
$reservedCommand[$generalID][] = [
'action' => $action,
'arg' => $arg,
'brief' => $brief
];
}
}
$specialViewFilter = [
'officerLevel' => fn ($rawGeneral) => $this->getOfficerLevel($rawGeneral),
'officerLevelText' => fn ($rawGeneral) => getOfficerLevelText($this->getOfficerLevel($rawGeneral), $nationStaticList[$rawGeneral['nation']]['level']),
'lbonus' => fn ($rawGeneral) => calcLeadershipBonus($rawGeneral['officer_level'], $nationStaticList[$rawGeneral['nation']]['level']),
'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null,
'isOurNation' => fn ($rawGeneral) => $rawGeneral['nation'] == $nationID,
];
$showFullColumn = $showLevel == self::OUR_NATION || $ourNationGeneralIDList->count() > 0;
$resultColumns = [];
foreach (static::$viewColumns as $column => $reqShowLevel) {
if (!$showFullColumn && $reqShowLevel > $showLevel) {
continue;
}
if (key_exists($column, static::$columnRemap)) {
$newColumn = static::$columnRemap[$column];
if ($newColumn !== null) {
$resultColumns[$newColumn] = $column;
}
} else {
$resultColumns[$column] = $column;
}
}
foreach (static::$customViewColumns as $column => $reqShowLevel) {
if (!$showFullColumn && $reqShowLevel > $showLevel) {
continue;
}
$resultColumns[$column] = $column;
}
$generalList = [];
foreach ($rawGeneralList as $rawGeneral) {
$item = [];
foreach ($resultColumns as $column) {
$reqShowLevel = static::$viewColumns[$column];
if ($rawGeneral['nation'] != $nationID && $reqShowLevel == self::OUR_NATION) {
$item[] = null;
continue;
}
if (key_exists($column, $specialViewFilter)) {
$value = $specialViewFilter[$column]($rawGeneral);
} else {
$value = $rawGeneral[$column];
}
$item[] = $value;
}
$generalList[] = $item;
}
return [
'column' => array_keys($resultColumns),
'list' => $generalList,
];
}
private function calcShowLevel(int $cityID, int $currentCityID, int $nationID, Set $cityList, bool $isSpyPresent): int
{
$db = DB::db();
if ($cityList->contains($currentCityID)) {
return self::OUR_NATION;
}
if ($cityID == $currentCityID) {
return self::ON_CITY;
}
if ($isSpyPresent) {
return self::ON_CITY;
}
$existsGeneralID = $db->queryFirstField(
'SELECT no FROM general WHERE city = %i AND nation = %i LIMIT 1',
$cityID,
$nationID
);
if ($existsGeneralID) {
return self::ON_CITY;
}
$cityConstObj = CityConst::byID($cityID);
$nearCityIDList = array_keys($cityConstObj->path);
foreach ($nearCityIDList as $nearCityID) {
if ($cityList->contains($nearCityID)) {
return self::NEAR_CITY;
}
}
return self::FAR_CITY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
increaseRefresh("도시정보", 1);
$db = DB::db();
$gameStor = \sammo\KVStorage::getStorage($db, 'game_env');
$lastExecuted = $gameStor->getValue('turntime');
$me = $db->queryFirstRow('SELECT con, turntime, belong, city, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID());
if (key_exists('cityID', $this->args)) {
$cityID = (int)$this->args['cityID'];
} else {
$cityID = $me['city'];
}
$con = checkLimit($me['con']);
if ($con >= 2) {
return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.';
}
$nationID = $me['nation'];
$currentCityID = $me['city'];
//TODO: 조건 조사
$cityList = new Set($db->queryFirstColumn('SELECT city FROM city WHERE nation=%i', $nationID));
$spyList = JSON::decode($db->queryFirstField('SELECT spy FROM nation WHERE nation=%i', $nationID));
$showLevel = $this->calcShowLevel($cityID, $currentCityID, $nationID, $cityList, key_exists($cityID, $spyList));
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city=%i', $cityID);
$filteredCity = $this->filterCity($rawCity, $showLevel);
$result = [
'result' => true,
'lastExcuted' => $lastExecuted,
'cityInfo' => $filteredCity,
'spyList' => $spyList,
'nationCityList' => $cityList->toArray(),
'myGeneralID' => $session->generalID,
'currentCityID' => $currentCityID,
'showLevel' => $showLevel,
'cityGeneralList' => $this->getGeneralList($cityID, $nationID, $showLevel)
];
return $result;
}
}
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Json;
use sammo\KVStorage;
use sammo\TimeUtil;
@@ -23,7 +24,7 @@ class GetReservedCommand extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use function sammo\pushGeneralCommand;
@@ -31,7 +32,7 @@ class PushCommand extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$amount = $this->args['amount'];
if($amount == 0){
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use function sammo\repeatGeneralCommand;
@@ -31,7 +32,7 @@ class RepeatCommand extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$amount = $this->args['amount'];
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\GameConst;
use sammo\Util;
use sammo\Validator;
@@ -36,7 +37,7 @@ class ReserveBulkCommand extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$briefList = [];
foreach ($this->args as $idx => $turn) {
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Command;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\GameConst;
use sammo\Util;
use sammo\Validator;
@@ -33,7 +34,7 @@ class ReserveCommand extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$action = $this->args['action'];
$turnList = $this->args['turnList'];
@@ -4,6 +4,7 @@ namespace sammo\API\General;
use sammo\Command\General\che_거병;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\Session;
@@ -30,7 +31,7 @@ class BuildNationCandidate extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\General;
use sammo\DB;
use sammo\DummyGeneral;
use sammo\Enums\APIRecoveryType;
use sammo\GameConst;
use sammo\Session;
use sammo\General;
@@ -26,7 +27,7 @@ class DieOnPrestart extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
//로그인 검사
$userID = $session->userID;
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\General;
use Ds\Set;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Validator;
use sammo\Session;
@@ -33,7 +34,7 @@ class DropItem extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$generalID = $session->generalID;
$me = General::createGeneralObjFromDB($generalID);
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace sammo\API\General;
use sammo\Enums\APIRecoveryType;
use sammo\General;
use sammo\Session;
use function sammo\getCommandTable;
//getCommandTable 호출을 대신하는 API
class GetCommandTable extends \sammo\BaseAPI{
public function validateArgs(): ?string{
return null;
}
public function getRequiredSessionMode(): int{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$generalID = $session->generalID;
$me = General::createGeneralObjFromDB($generalID);
$commandTable = getCommandTable($me);
return [
'result'=>true,
'commandTable' => $commandTable,
];
}
}
+591
View File
@@ -0,0 +1,591 @@
<?php
namespace sammo\API\General;
use DateTimeInterface;
use MeekroDB;
use sammo\CityConst;
use sammo\DB;
use sammo\DTO\VoteInfo;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\CityColumn;
use sammo\Enums\GeneralColumn;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
use sammo\LastTurn;
use sammo\Validator;
use sammo\Session;
use sammo\TimeUtil;
use sammo\Util;
use function sammo\buildNationCommandClass;
use function sammo\checkLimit;
use function sammo\getTournamentTermText;
use function sammo\buildNationTypeClass;
use function sammo\calcLeadershipBonus;
use function sammo\checkSecretPermission;
use function sammo\getBillByLevel;
use function sammo\getDed;
use function sammo\getHonor;
use function sammo\getNationStaticInfo;
use function sammo\getOfficerLevelText;
use function sammo\increaseRefresh;
/**
* 통째로 메인페이지의 주요 정보를 반환하는 날로먹는 API
*/
class GetFrontInfo extends \sammo\BaseAPI
{
const ROW_LIMIT = 15;
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('lengthMin', 'lastNationNoticeDate', 19)
->rule('integer', 'lastGeneralRecordID')
->rule('integer', 'lastWorldHistoryID');
if (!$v->validate()) {
return $v->errorStr();
}
$this->args['lastGeneralRecordID'] = (int)($this->args['lastGeneralRecordID'] ?? 0);
$this->args['lastWorldHistoryID'] = (int)($this->args['lastWorldHistoryID'] ?? 0);
return null;
}
private function getGlobalRecord(int $lastRecordID): array
{
$db = DB::db();
$globalRecord = $db->queryAllLists(
'SELECT id, `text` FROM general_record WHERE `general_id` = 0 AND log_type = %s AND id >= %i ORDER BY `id` DESC LIMIT %i',
'history',
$lastRecordID,
static::ROW_LIMIT + 1,
);
return $globalRecord;
}
private function getGeneralRecord(int $generalID, int $lastRecordID): array
{
$db = DB::db();
$generalRecord = $db->queryAllLists(
'SELECT id, `text` FROM general_record WHERE `general_id` = %i AND log_type = %s AND id >= %i ORDER BY `id` DESC LIMIT %i',
$generalID,
'action',
$lastRecordID,
static::ROW_LIMIT + 1,
);
return $generalRecord;
}
private function getHistory(int $lastHistoryID): array
{
$db = DB::db();
$history = $db->queryAllLists(
'SELECT id, `text` FROM world_history WHERE nation_id = 0 AND id >= %i ORDER BY `id` DESC LIMIT %i',
$lastHistoryID,
static::ROW_LIMIT + 1,
);
return $history;
}
private function generateRecentRecord(int $generalID){
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['isunited', 'opentime', 'refresh']);
$lastHistoryID = $this->args['lastWorldHistoryID'];
$lastRecordID = $this->args['lastGeneralRecordID'];
$history = $this->getHistory($lastHistoryID);
$globalRecord = $this->getGlobalRecord($lastRecordID);
$generalRecord = $this->getGeneralRecord($generalID, $lastRecordID);
$flushHistory = false;
$flushGlobalRecord = false;
$flushGeneralRecord = false;
if (!$history) {
$flushHistory = false;
} else if (Util::array_last($history)[0] <= $lastHistoryID) {
$flushHistory = false;
array_pop($history);
} else if (count($history) > static::ROW_LIMIT) {
array_pop($history);
}
if (!$globalRecord) {
$flushGlobalRecord = false;
} else if (Util::array_last($globalRecord)[0] == $lastRecordID) {
$flushGlobalRecord = false;
array_pop($globalRecord);
} else if (count($globalRecord) > static::ROW_LIMIT) {
array_pop($globalRecord);
}
if (!$generalRecord) {
$flushGeneralRecord = false;
} else if (Util::array_last($generalRecord)[0] == $lastRecordID) {
$flushGeneralRecord = false;
array_pop($generalRecord);
} else if (count($generalRecord) > static::ROW_LIMIT) {
array_pop($generalRecord);
}
return [
'history' => $history,
'global' => $globalRecord,
'general' => $generalRecord,
'flushHistory' => $flushHistory ? 1 : 0,
'flushGlobal' => $flushGlobalRecord ? 1 : 0,
'flushGeneral' => $flushGeneralRecord ? 1 : 0,
];
}
private function generateGlobalInfo(MeekroDB $db): array
{
$gameStor = KVStorage::getStorage($db, 'game_env');
[
$scenarioText, $extendedGeneral, $isFiction, $npcMode,
$joinMode, $autorunUser, $turnterm, $lastExecuted,
$lastVoteID, $develCost, $noticeMsg,
$onlineNations, $onlineUserCnt,
$year, $month, $startYear,
$generalCntLimit,
$apiLimit,
$serverCnt,
] = $gameStor->getValuesAsArray([
'scenario_text', 'extended_general', 'fiction', 'npcmode',
'join_mode', 'autorun_user', 'turnterm', 'turntime',
'lastVote', 'develcost', 'msg',
'online_nation', 'online_user_cnt',
'year', 'month', 'startyear',
'maxgeneral',
'conlimit',
'server_cnt',
]);
$lastVote = null;
if ($lastVoteID) {
$voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
$lastVote = null;
}
}
$auctionCount = $db->queryFirstField('SELECT count(*) FROM ng_auction WHERE finished = 0');
$isTournamentActive = $gameStor->tournament > 0;
$isTournamentApplicationOpen = $gameStor->tournament == 1;
$isBettingActive = $gameStor->tournament == 6;
$tournamentType = $gameStor->tnmt_type;
$tournamentState = $gameStor->tournament;
$tournamentTime = $gameStor->tnmt_time;
$isLocked = boolval($db->queryFirstField('SELECT plock FROM plock WHERE `type`="GAME" LIMIT 1'));
$globalGenCount = $db->queryAllLists('SELECT npc, count(no) FROM general GROUP BY npc');
return [
'scenarioText' => $scenarioText,
'extendedGeneral' => $extendedGeneral,
'isFiction' => $isFiction,
'npcMode' => $npcMode,
'joinMode' => $joinMode,
'startyear' => $startYear,
'year' => $year,
'month' => $month,
'autorunUser' => $autorunUser,
'turnterm' => $turnterm,
'lastExecuted' => $lastExecuted,
'lastVoteID' => $lastVoteID,
'develCost' => $develCost,
'noticeMsg' => $noticeMsg,
'onlineNations' => $onlineNations,
'onlineUserCnt' => $onlineUserCnt,
'apiLimit' => $apiLimit,
'auctionCount' => $auctionCount,
'isTournamentActive' => $isTournamentActive,
'isTournamentApplicationOpen' => $isTournamentApplicationOpen,
'isBettingActive' => $isBettingActive,
'isLocked' => $isLocked,
'tournamentType' => $tournamentType,
'tournamentState' => $tournamentState,
'tournamentTime' => $tournamentTime,
'genCount' => $globalGenCount,
'generalCntLimit' => $generalCntLimit,
'serverCnt' => $serverCnt,
'lastVote' => $lastVote === null ? null : $lastVote->toArray(),
];
}
public function generateNationInfo(MeekroDB $db, General $general, array $rawNation): array
{
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getAll(true);
$lastNationNoticeDate = $this->args['lastNationNoticeDate'] ?? '2022-08-19 00:00:00';
$nationID = $general->getNationID();
//XXX: 매번 더하는가?
$nationPopulation = $db->queryFirstRow(
'SELECT COUNT(*) as cityCnt, CAST(SUM(pop) AS INTEGER) as `now`, CAST(SUM(pop_max) AS INTEGER) as `max` from city where nation=%i',
$nationID
);
if($nationPopulation['cityCnt'] == 0){
$nationPopulation = [
'cityCnt' => 0,
'now' => 0,
'max' => 0
];
}
//XXX: 매번 더하는가?
$nationCrew = $db->queryFirstRow(
'SELECT COUNT(*) as generalCnt, CAST(SUM(crew) AS INTEGER) as `now`,CAST(SUM(leadership)*100 AS INTEGER) as `max` from general where nation=%i AND npc != 5',
$nationID
);
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
[$nationNotice, $onlineGen] = $nationStor->getValuesAsArray(['nationNotice', 'online_genenerals']);
if (!$nationNotice || ($nationNotice['date'] ?? '') <= $lastNationNoticeDate) {
$nationNotice = null;
}
$topChiefs = Util::convertArrayToDict($db->query(
'SELECT officer_level, no, name, npc FROM general WHERE nation = %i AND officer_level >= 11',
$nationID
), 'officer_level');
$impossibleStrategicCommandLists = [];
$strategicCommandLists = GameConst::$availableChiefCommand['전략'];
$yearMonth = Util::joinYearMonth($admin['year'], $admin['month']);
foreach ($strategicCommandLists as $command) {
$cmd = buildNationCommandClass($command, $general, $admin, new LastTurn());
$nextAvailableTurn = $cmd->getNextAvailableTurn();
if ($nextAvailableTurn > $yearMonth) {
$impossibleStrategicCommandLists[] = [$cmd->getName(), $nextAvailableTurn - $yearMonth];
}
}
$nationClass = buildNationTypeClass($rawNation['type']);
return [
'id' => $nationID,
'full' => true,
'name' => $rawNation['name'],
'population' => $nationPopulation,
'crew' => $nationCrew,
'type' => [
'raw' => $rawNation['type'],
'name' => $nationClass->getName(),
'pros' => $nationClass::$pros,
'cons' => $nationClass::$cons,
],
'color' => $rawNation['color'],
'level' => $rawNation['level'],
'capital' => $rawNation['capital'],
'gold' => $rawNation['gold'],
'rice' => $rawNation['rice'],
'tech' => $rawNation['tech'],
'gennum' => $rawNation['gennum'],
'power' => $rawNation['power'],
'bill' => $rawNation['bill'],
'taxRate' => $rawNation['rate'],
'onlineGen' => $onlineGen,
'notice' => $nationNotice,
'topChiefs' => $topChiefs,
'diplomaticLimit' => $rawNation['surlimit'],
'strategicCmdLimit' => $rawNation['strategic_cmd_limit'],
'impossibleStrategicCommand' => $impossibleStrategicCommandLists,
'prohibitScout' => $rawNation['scout'],
'prohibitWar' => $rawNation['war'],
];
}
public function generateDummyNationInfo(MeekroDB $db, General $general, array $rawNation): array
{
$staticInfo = getNationStaticInfo(0);
return [
'id' => 0,
'full' => false,
'name' => $staticInfo['name'],
'population' => [
'cityCnt' => 0,
'now' => 0,
'max' => 0,
],
'crew' => [
'generalCnt' => 0,
'now' => 0,
'max' => 0,
],
'type' => [
'raw' => 'None',
'name' => '-',
'pros' => '',
'cons' => '',
],
'color' => $staticInfo['color'],
'level' => $staticInfo['level'],
'capital' => $staticInfo['capital'],
'gold' => $staticInfo['gold'],
'rice' => $staticInfo['rice'],
'tech' => $staticInfo['tech'],
'gennum' => $staticInfo['gennum'],
'power' => $staticInfo['power'],
'onlineGen' => '', //TODO 접속자
'notice' => '',
'topChiefs' => [],
'impossibleStrategicCommand' => [],
];
}
public function generateGeneralInfo(MeekroDB $db, General $general, array $rawNation): array
{
$permission = checkSecretPermission($general->getRaw());
$result = [
'no' => $general->getID(), // number;
'name' => $general->getName(), // string;
'nation' => $general->getNationID(), // number;
'npc' => $general->getNPCType(), // number;
'injury' => $general->getVar(GeneralColumn::injury), // number;
'leadership' => $general->getVar(GeneralColumn::leadership), // number;
'strength' => $general->getVar('strength'), // number;
'intel' => $general->getVar('intel'), // number;
'explevel' => $general->getVar('explevel'), // number;
'dedlevel' => $general->getVar('dedlevel'), // number;
'gold' => $general->getVar('gold'), // number;
'rice' => $general->getVar('rice'), // number;
'killturn' => $general->getVar(GeneralColumn::killturn), // number;
'picture' => $general->getVar(GeneralColumn::picture), // string;
'imgsvr' => $general->getVar(GeneralColumn::imgsvr), // 0 | 1;
'age' => $general->getVar(GeneralColumn::age), // number;
'specialDomestic' => $general->getVar(GeneralColumn::special), // GameObjClassKey;
'specialWar' => $general->getVar(GeneralColumn::special2), // GameObjClassKey;
'personal' => $general->getVar(GeneralColumn::personal), // GameObjClassKey;
'belong' => $general->getVar(GeneralColumn::belong), // number;
'connect' => $general->getVar(GeneralColumn::connect), // number;
'officerLevel' => $general->getVar(GeneralColumn::officer_level), // number;
'officerLevelText' => getOfficerLevelText($general->getVar(GeneralColumn::officer_level), $rawNation['level']), // string;
'lbonus' => calcLeadershipBonus($general->getVar(GeneralColumn::officer_level), $rawNation['level']), // number;
'ownerName' => $general->getVar(GeneralColumn::owner_name), // string | null;
'honorText' => getHonor($general->getVar(GeneralColumn::experience)), // string;
'dedLevelText' => getDed($general->getVar(GeneralColumn::dedication)), // string;
'bill' => getBillByLevel($general->getVar(GeneralColumn::dedlevel)), // number;
'reservedCommand' => null, // TurnObj[] | null;
'autorun_limit' => $general->getAuxVar('autorun_limit') ?? 0, // number;
'city' => $general->getVar(GeneralColumn::city), // number;
'troop' => $general->getVar(GeneralColumn::troop), // number;
//P0 End
'con' => $general->getVar(GeneralColumn::con), // number;
'specage' => $general->getVar(GeneralColumn::specage), // number;
'specage2' => $general->getVar(GeneralColumn::specage2), // number;
'leadership_exp' => $general->getVar(GeneralColumn::leadership_exp), // number;
'strength_exp' => $general->getVar(GeneralColumn::strength_exp), // number;
'intel_exp' => $general->getVar(GeneralColumn::intel_exp), // number;
'dex1' => $general->getVar(GeneralColumn::dex1), // number;
'dex2' => $general->getVar(GeneralColumn::dex2), // number;
'dex3' => $general->getVar(GeneralColumn::dex3), // number;
'dex4' => $general->getVar(GeneralColumn::dex4), // number;
'dex5' => $general->getVar(GeneralColumn::dex5), // number;
'experience' => $general->getVar(GeneralColumn::experience), // number;
'dedication' => $general->getVar(GeneralColumn::dedication), // number;
'officer_level' => $general->getVar(GeneralColumn::officer_level), // number;
'officer_city' => $general->getVar(GeneralColumn::officer_city), // number;
'defence_train' => $general->getVar(GeneralColumn::defence_train), // number;
'crewtype' => $general->getVar(GeneralColumn::crewtype), // GameObjClassKey;
'crew' => $general->getVar(GeneralColumn::crew), // number;
'train' => $general->getVar(GeneralColumn::train), // number;
'atmos' => $general->getVar(GeneralColumn::atmos), // number;
'turntime' => $general->getVar(GeneralColumn::turntime), // string;
'recent_war' => $general->getVar(GeneralColumn::recent_war), // string;
'horse' => $general->getVar(GeneralColumn::horse), // GameObjClassKey;
'weapon' => $general->getVar(GeneralColumn::weapon), // GameObjClassKey;
'book' => $general->getVar(GeneralColumn::book), // GameObjClassKey;
'item' => $general->getVar(GeneralColumn::item), // GameObjClassKey;
'warnum' => $general->getRankVar(RankColumn::warnum), // number;
'killnum' => $general->getRankVar(RankColumn::killnum), // number;
'deathnum' => $general->getRankVar(RankColumn::deathnum), // number;
'killcrew' => $general->getRankVar(RankColumn::killcrew), // number;
'deathcrew' => $general->getRankVar(RankColumn::deathcrew), // number;
'firenum' => $general->getRankVar(RankColumn::firenum), // number;
//P1 End
'permission' => $permission,
];
$nationID = $general->getNationID();
$troopID = $general->getVar(GeneralColumn::troop);
if (!$troopID) {
return $result;
}
$troopName = $db->queryFirstField(
'SELECT `name` FROM troop WHERE nation = %i AND troop_leader = %i',
$nationID,
$troopID
);
if (!$troopName) {
return $result;
}
$troopCityID = $db->queryFirstField(
'SELECT city FROM general WHERE nation = %i AND `no` = %i',
$nationID,
$troopID
);
if (!$troopCityID) {
return $result;
}
$troopReservedCommand = $db->query(
'SELECT action, arg, brief FROM general_turn WHERE general_id = %i AND turn_idx < 5 ORDER BY turn_idx asc',
$troopID
);
if (!$troopReservedCommand) {
return $result;
}
$result['troopInfo'] = [
'leader' => [
'city' => $troopCityID,
'reservedCommand' => $troopReservedCommand,
],
'name' => $troopName,
];
return $result;
}
public function generateCityInfo(MeekroDB $db, General $general, array $rawNation): array
{
$rawCity = $general->getRawCity() ?? [];
$cityID = $rawCity[CityColumn::city->value];
$nationID = $rawCity[CityColumn::nation->value];
if ($nationID == $general->getNationID()) {
$nationName = $rawNation['name'];
$nationColor = $rawNation['color'];
} else {
$staticNation = getNationStaticInfo($nationID);
$nationName = $staticNation['name'];
$nationColor = $staticNation['color'];
}
$rawOfficerList = $db->query('SELECT officer_level, name, npc FROM general WHERE officer_city = %i AND officer_level IN (4,3,2)', $cityID);
$officerList = [4 => null, 3 => null, 2 => null];
foreach ($rawOfficerList as $officer) {
$officerLevel = $officer['officer_level'];
$officerList[$officerLevel] = $officer;
}
$result = [
'id' => $rawCity[CityColumn::city->value],
'name' => $rawCity[CityColumn::name->value],
'nationInfo' => [
'id' => $nationID,
'name' => $nationName,
'color' => $nationColor,
],
'level' => $rawCity[CityColumn::level->value],
'trust' => $rawCity[CityColumn::trust->value],
'pop' => [$rawCity[CityColumn::pop->value], $rawCity[CityColumn::pop_max->value]],
'agri' => [$rawCity[CityColumn::agri->value], $rawCity[CityColumn::agri_max->value]],
'comm' => [$rawCity[CityColumn::comm->value], $rawCity[CityColumn::comm_max->value]],
'secu' => [$rawCity[CityColumn::secu->value], $rawCity[CityColumn::secu_max->value]],
'def' => [$rawCity[CityColumn::def->value], $rawCity[CityColumn::def_max->value]],
'wall' => [$rawCity[CityColumn::wall->value], $rawCity[CityColumn::wall_max->value]],
'trade' => $rawCity[CityColumn::trade->value],
'officerList' => $officerList,
];
return $result;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$generalID = $session->generalID;
//NOTE: 이 경우 staticNation 정보를 조회한다.
$general = General::createGeneralObjFromDB($generalID);
$nationID = $general->getNationID();
$cityID = $general->getCityID();
$con = checkLimit($general->getVar('con'));
if ($con >= 2) {
return [
'result' => false,
'reason' => '접속 제한중입니다.',
'recovery' => APIRecoveryType::GameQuota,
'recovery_arg' => $general->getVar('turntime'),
];
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheAll(true);
increaseRefresh("General/GetFrontInfo", 1);
$rawCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $cityID);
$general->setRawCity($rawCity);
if ($nationID == 0) {
$rawNation = getNationStaticInfo(0);
} else {
$rawNation = $db->queryFirstRow('SELECT * FROM nation WHERE nation = %i', $nationID);
}
$globalInfo = $this->generateGlobalInfo($db);
$nationInfo = $nationID != 0 ?
$this->generateNationInfo($db, $general, $rawNation) :
$this->generateDummyNationInfo($db, $general, $rawNation);
$generalInfo = $this->generateGeneralInfo($db, $general, $rawNation);
$cityInfo = $this->generateCityInfo($db, $general, $rawNation);
//TODO: 마지막 투표, 토너먼트, 베팅을 했는지 정보를 별도로 가져와야 함. aux?
$auxInfo = [];
if ($globalInfo['lastVote']) {
$myLastVoteID = $db->queryFirstField('SELECT vote_id FROM vote WHERE general_id = %i ORDER BY vote_id DESC LIMIT 1', $generalID);
if($myLastVoteID) {
$auxInfo['myLastVote'] = $myLastVoteID;
}
}
return [
'result' => true,
'recentRecord' => $this->generateRecentRecord($generalID),
'global' => $globalInfo,
'nation' => $nationInfo,
'general' => $generalInfo,
'city' => $cityInfo,
'aux' => $auxInfo,
];
}
}
+2 -1
View File
@@ -7,6 +7,7 @@ use sammo\ActionLogger;
use sammo\Auction;
use sammo\CityConst;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\GameUnitConst;
@@ -120,7 +121,7 @@ class Join extends \sammo\BaseAPI
return $targetBonusPointCnt;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Global;
use sammo\Session;
use sammo\DB;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\TurnExecutionHelper;
use sammo\UniqueConst;
@@ -20,7 +21,7 @@ class ExecuteEngine extends \sammo\BaseAPI
return static::NO_SESSION;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$reqServerID = $this->args['serverID'] ?? null;
if($reqServerID && $reqServerID !== UniqueConst::$serverID){
+2 -1
View File
@@ -3,6 +3,7 @@
namespace sammo\API\Global;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Json;
use sammo\KVStorage;
use sammo\RootDB;
@@ -33,7 +34,7 @@ class GeneralList extends \sammo\BaseAPI
return static::REQ_LOGIN;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use Nette\Caching\Cache;
use sammo\APICacheResult;
use sammo\Enums\APIRecoveryType;
use sammo\GameConst;
use sammo\MapRequest;
use sammo\TimeUtil;
@@ -44,7 +45,7 @@ class GetCachedMap extends \sammo\BaseAPI
return static::NO_SESSION;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
if (!class_exists('\\sammo\\UniqueConst')) {
return '서버 초기화되지 않음';
+6 -4
View File
@@ -9,6 +9,7 @@ use Nette\Caching\Cache;
use RuntimeException;
use sammo\APICacheResult;
use sammo\CityConst;
use sammo\Enums\APIRecoveryType;
use sammo\GameConst;
use sammo\GameUnitConst;
use sammo\Json;
@@ -20,7 +21,7 @@ use function sammo\prepareDir;
class GetConst extends \sammo\BaseAPI
{
/** 반환하는 StaticValues 타입이 달라지면 +1 */
const CONST_API_VERSION = 2;
const CONST_API_VERSION = 3;
const CACHE_KEY = 'JSConst';
private ?string $cacheKey = null;
@@ -85,10 +86,10 @@ class GetConst extends \sammo\BaseAPI
if ($lastModified !== null) {
$versionHash = "lt{$lastModified}";
} else {
$versionHash = VersionGit::getHash();
$versionHash = VersionGit::getVersion();
}
} else {
$versionHash = VersionGit::getHash();
$versionHash = VersionGit::getVersion();
}
$apiVersion = static::CONST_API_VERSION;
@@ -276,10 +277,11 @@ class GetConst extends \sammo\BaseAPI
],
'iActionInfo' => $iActionInfo,
'iActionKeyMap' => $iActionKeyMap,
'version' => VersionGit::getVersion(),
];
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$cacheDir = $this->rootPath . '/data/file_cache';
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use function sammo\getCurrentHistory;
@@ -19,7 +20,7 @@ class GetCurrentHistory extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$history = getCurrentHistory();
+2 -1
View File
@@ -3,6 +3,7 @@
namespace sammo\API\Global;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Json;
use sammo\KVStorage;
use sammo\Session;
@@ -22,7 +23,7 @@ class GetDiplomacy extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace sammo\API\Global;
use LDTO\DTO;
use sammo\APICacheResult;
use sammo\BaseAPI;
use sammo\Enums\APIRecoveryType;
use sammo\GlobalMenu;
use sammo\Session;
class GetGlobalMenu extends BaseAPI
{
public function getRequiredSessionMode(): int
{
return self::NO_SESSION;
}
function validateArgs(): ?string
{
return null;
}
function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
if ($reqEtag !== null) {
$version = GlobalMenu::version;
if ($reqEtag == "v{$version}") {
return null;
}
}
return [
'result' => true,
'menu' => array_map(function (DTO $dto) {
return $dto->toArray();
}, GlobalMenu::getMenu()),
];
}
public function tryCache(): ?APICacheResult
{
$version = GlobalMenu::version;
return new APICacheResult(
null,
"v{$version}",
60 * 60 * 6,
true
);
}
}
+2 -1
View File
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\APICacheResult;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Json;
use sammo\UniqueConst;
use sammo\Util;
@@ -127,7 +128,7 @@ class GetHistory extends \sammo\BaseAPI
return $cachedHash;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$checkCache = $this->checkCached($reqEtag);
if ($checkCache) {
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\MapRequest;
use sammo\Validator;
@@ -27,7 +28,7 @@ class GetMap extends \sammo\BaseAPI
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
return getWorldMap(new MapRequest([
'neutralView' => !!($this->args['neutralView'] ?? false),
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use function sammo\getAllNationStaticInfo;
use function sammo\getNationStaticInfo;
@@ -21,7 +22,7 @@ class GetNationList extends \sammo\BaseAPI
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
+38 -35
View File
@@ -5,24 +5,27 @@ namespace sammo\API\Global;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\KVStorage;
use sammo\Util;
use sammo\Validator;
class GetRecentRecord extends \sammo\BaseAPI
{
static bool $allowExternalAPI = false;
const ROW_LIMIT = 15;
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v->rule('int', 'lastGeneralRecordID')
->rule('int', 'lastWorldHistoryID');
$v->rule('integer', 'lastGeneralRecordID')
->rule('integer', 'lastWorldHistoryID');
if (!$v->validate()) {
return $v->errorStr();
}
$this->args['lastGeneralRecordID'] = (int)($this->args['lastGeneralRecordID']??0);
$this->args['lastWorldHistoryID'] = (int)($this->args['lastWorldHistoryID']??0);
$this->args['lastGeneralRecordID'] = (int)($this->args['lastGeneralRecordID'] ?? 0);
$this->args['lastWorldHistoryID'] = (int)($this->args['lastWorldHistoryID'] ?? 0);
return null;
}
@@ -70,10 +73,13 @@ class GetRecentRecord extends \sammo\BaseAPI
return $history;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['isunited', 'opentime', 'refresh']);
$lastHistoryID = $this->args['lastWorldHistoryID'];
$lastRecordID = $this->args['lastGeneralRecordID'];
@@ -81,38 +87,35 @@ class GetRecentRecord extends \sammo\BaseAPI
$globalRecord = $this->getGlobalRecord($lastRecordID);
$generalRecord = $this->getGeneralRecord($session->generalID, $lastRecordID);
$flushHistory = true;
$flushGlobalRecord = true;
$flushGeneralRecord = true;
$flushHistory = false;
$flushGlobalRecord = false;
$flushGeneralRecord = false;
if($history){
if(Util::array_last($history)[0] == $lastHistoryID){
$flushHistory = false;
array_pop($history);
}
else if(count($history) > static::ROW_LIMIT){
array_pop($history);
}
if (!$history) {
$flushHistory = false;
} else if (Util::array_last($history)[0] <= $lastHistoryID) {
$flushHistory = false;
array_pop($history);
} else if (count($history) > static::ROW_LIMIT) {
array_pop($history);
}
if($globalRecord){
if(Util::array_last($globalRecord)[0] == $lastRecordID){
$flushGlobalRecord = false;
array_pop($globalRecord);
}
else if(count($globalRecord) > static::ROW_LIMIT){
array_pop($globalRecord);
}
if (!$globalRecord) {
$flushGlobalRecord = false;
} else if (Util::array_last($globalRecord)[0] == $lastRecordID) {
$flushGlobalRecord = false;
array_pop($globalRecord);
} else if (count($globalRecord) > static::ROW_LIMIT) {
array_pop($globalRecord);
}
if($generalRecord){
if(Util::array_last($generalRecord)[0] == $lastRecordID){
$flushGeneralRecord = false;
array_pop($generalRecord);
}
else if(count($generalRecord) > static::ROW_LIMIT){
array_pop($generalRecord);
}
if (!$generalRecord) {
$flushGeneralRecord = false;
} else if (Util::array_last($generalRecord)[0] == $lastRecordID) {
$flushGeneralRecord = false;
array_pop($generalRecord);
} else if (count($generalRecord) > static::ROW_LIMIT) {
array_pop($generalRecord);
}
return [
@@ -120,9 +123,9 @@ class GetRecentRecord extends \sammo\BaseAPI
'history' => $history,
'global' => $globalRecord,
'general' => $generalRecord,
'flushHistory' => $flushHistory?1:0,
'flushGlobal' => $flushGlobalRecord?1:0,
'flushGeneral' => $flushGeneralRecord?1:0,
'flushHistory' => $flushHistory ? 1 : 0,
'flushGlobal' => $flushGlobalRecord ? 1 : 0,
'flushGeneral' => $flushGeneralRecord ? 1 : 0,
];
}
}
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
@@ -40,7 +41,7 @@ class BuyHiddenBuff extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$generalID = $session->generalID;
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
@@ -25,7 +26,7 @@ class BuyRandomUnique extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$generalID = $session->generalID;
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\InheritAction;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Session;
use sammo\Validator;
use sammo\Util;
@@ -25,7 +26,7 @@ class GetMoreLog extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$lastID = $this->args['lastID'];
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
@@ -25,7 +26,7 @@ class ResetSpecialWar extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$generalID = $session->generalID;
@@ -6,6 +6,7 @@ use DateTimeImmutable;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
@@ -30,7 +31,7 @@ class ResetTurnTime extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$generalID = $session->generalID;
@@ -5,6 +5,7 @@ namespace sammo\API\InheritAction;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
@@ -36,7 +37,7 @@ class SetNextSpecialWar extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$generalID = $session->generalID;
@@ -6,6 +6,7 @@ use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\DiplomaticMessage;
use sammo\Enums\APIRecoveryType;
use sammo\KVStorage;
use sammo\Message;
use sammo\Validator;
@@ -31,7 +32,7 @@ class DecideMessageResponse extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$msgID = $this->args['msgID'];
$msgResponse = $this->args['response'];
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Message;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use sammo\Message;
use sammo\Validator;
@@ -27,7 +28,7 @@ class DeleteMessage extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$msgID = $this->args['msgID'];
+2 -1
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Message;
use sammo\Session;
use DateTimeInterface;
use sammo\Enums\APIRecoveryType;
use function sammo\getMailboxList;
@@ -18,7 +19,7 @@ class GetContactList extends \sammo\BaseAPI{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
if(!$session->generalID){
return [
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Message;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\MessageType;
use sammo\Json;
use sammo\Message;
@@ -65,7 +66,7 @@ class GetOldMessage extends \sammo\BaseAPI
}
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$this->delayFrequentCall($session);
$session->setReadOnly();
+14 -5
View File
@@ -5,8 +5,11 @@ namespace sammo\API\Message;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType;
use sammo\Json;
use sammo\KVStorage;
use sammo\Message;
use sammo\TimeUtil;
use sammo\Util;
@@ -61,7 +64,7 @@ class GetRecentMessage extends \sammo\BaseAPI
}
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$this->delayFrequentCall($session);
$session->setReadOnly();
@@ -82,7 +85,6 @@ class GetRecentMessage extends \sammo\BaseAPI
$result = [];
$result['result'] = true;
$result['keepRecent'] = false;
$nextSequence = $reqSequence;
$minSequence = $reqSequence;
$lastType = null;
@@ -138,14 +140,21 @@ class GetRecentMessage extends \sammo\BaseAPI
if ($lastType !== null) {
array_pop($result[$lastType]);
$result['keepRecent'] = true;
} else if ($reqSequence <= 0) {
$result['keepRecent'] = true;
}
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
[$latestReadDiplomacyMsg, $latestReadPrivateMsg] = $generalStor->getValuesAsArray([
GeneralStorKey::latestReadDiplomacyMsg,
GeneralStorKey::latestReadPrivateMsg
]);
$result['sequence'] = $nextSequence;
$result['nationID'] = $nationID;
$result['generalName'] = $generalName;
$result['latestRead'] = [
'diplomacy' => $latestReadDiplomacyMsg ?? 0,
'private' => $latestReadPrivateMsg ?? 0,
];
return $result;
}
@@ -0,0 +1,52 @@
<?php
namespace sammo\API\Message;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType;
use sammo\KVStorage;
use sammo\Session;
use sammo\Validator;
class ReadLatestMessage extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
//type이 개인 메시지 혹은 외교 메시지여야함
$v = new Validator($this->args);
$v->rule('required', ['type', 'msgID'])
->rule('in', 'type', [MessageType::private->value, MessageType::diplomacy->value])
->rule('int', 'msgID');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
$generalID = $session->generalID;
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
$type = MessageType::from($this->args['type']);
$msgID = $this->args['msgID'];
$storKey = GeneralStorKey::latestReadPrivateMsg;
if($type == MessageType::diplomacy){
$storKey = GeneralStorKey::latestReadDiplomacyMsg;
}
$oldValue = $generalStor->getValue($storKey);
if($oldValue === null || $oldValue < $msgID){
$generalStor->setValue($storKey, $msgID);
}
return null;
}
}
+6 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Message;
use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\MessageType;
use sammo\Message;
use sammo\MessageTarget;
@@ -145,7 +146,7 @@ class SendMessage extends \sammo\BaseAPI
return $msg;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;
$mailbox = $this->args['mailbox'];
@@ -185,6 +186,7 @@ class SendMessage extends \sammo\BaseAPI
if ($mailbox === Message::MAILBOX_PUBLIC) {
$msgID = $this->genPublicMessage($src, $text)->send();
return [
'msgType' => 'public',
'msgID' => $msgID
];
}
@@ -201,6 +203,7 @@ class SendMessage extends \sammo\BaseAPI
if ($destNationID === $nationID) {
$msgID = $this->genNationalMessage($src, $text)->send();
return [
'msgType' => 'national',
'msgID' => $msgID
];
}
@@ -211,6 +214,7 @@ class SendMessage extends \sammo\BaseAPI
}
$msgID = $msgObjOrError->send();
return [
'msgType' => 'diplomacy',
'msgID' => $msgID
];
}
@@ -231,6 +235,7 @@ class SendMessage extends \sammo\BaseAPI
$msgID = $msgObjOrError->send();
return [
'msgType' => 'private',
'msgID' => $msgID
];
}
+2 -1
View File
@@ -5,6 +5,7 @@ namespace sammo\API\Misc;
use sammo\Session;
use DateTimeInterface;
use sammo\AppConf;
use sammo\Enums\APIRecoveryType;
use sammo\KVStorage;
use sammo\RootDB;
use sammo\TimeUtil;
@@ -31,7 +32,7 @@ class UploadImage extends \sammo\BaseAPI
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$imageData = base64_decode($this->args['imageData'], true);
if ($imageData === false) {
+4 -3
View File
@@ -4,6 +4,7 @@ namespace sammo\API\Nation;
use ArrayObject;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\General;
use sammo\Session;
use sammo\Util;
@@ -133,7 +134,7 @@ class GeneralList extends \sammo\BaseAPI
return 1;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
increaseRefresh("세력장수", 1);
@@ -188,14 +189,14 @@ class GeneralList extends \sammo\BaseAPI
foreach($troops as $troop){
$reservedCommandTargetGeneralIDList[$troop['id']] = $troop['id'];
}
if($reservedCommandTargetGeneralIDList){
$rawTurnList = $db->query(
'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc',
array_values($reservedCommandTargetGeneralIDList)
);
foreach ($rawTurnList as $rawTurn) {
[
'general_id' => $generalID,
+2 -1
View File
@@ -3,6 +3,7 @@
namespace sammo\API\Nation;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Session;
use sammo\Validator;
@@ -99,7 +100,7 @@ class GetGeneralLog extends \sammo\BaseAPI
return $this->args['generalID'];
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$userID = $session->userID;

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