Compare commits

...
44 Commits
Author SHA1 Message Date
Hide_D f2a785f2fc imagePull 기능 추가, 인스톨러 완성 2019-09-23 00:28:15 +09:00
Hide_D 6fafcfae4e 훈사 분리 2019-09-21 23:27:43 +09:00
Hide_D 33e075f669 훈사를 분리 2019-09-21 21:29:20 +09:00
Hide_D e5fc467c4e 버그 수정 2019-09-21 21:04:17 +09:00
Hide_D b7a5de49c6 표기 일부 변경 2019-09-21 18:09:37 +09:00
Hide_D 3f145abd6f 모훈사 기준을 징병 6회로 변경 2019-09-21 17:39:13 +09:00
Hide_D 4612834870 워프 기준, 쌀 삼팜 기준 변경 2019-09-21 14:41:23 +09:00
Hide_D 83c5609fad 징병 버그 수정 2 2019-09-21 11:42:10 +09:00
Hide_D d142056098 징병 안되는 버그 수정 2019-09-21 11:39:51 +09:00
Hide_D 4d8ecf4191 진짜로 삭턴 버그 수정 2019-09-21 02:44:00 +09:00
Hide_D af6c3f466d 삭턴 버그 수정 2019-09-21 02:38:06 +09:00
Hide_D 033a2d8674 삭턴 버그 수정 2019-09-21 02:35:15 +09:00
Hide_D 9079788b2b 삭턴 기준 변경 2019-09-21 02:33:39 +09:00
Hide_D 44ddb2e480 git fetch에도 -q 2019-09-21 02:28:49 +09:00
Hide_D 295ba84071 자동 행동 세부를 툴팁으로 2019-09-21 02:27:05 +09:00
Hide_D 8773250aab 초기 병종이 보병일 때 고정되는 버그 수정 2019-09-21 02:14:25 +09:00
Hide_D c5a4602fe1 옵션 표기 버그 수정 2019-09-21 02:11:54 +09:00
Hide_D 5f4c43baf6 Merge branch 'devel' into autorun 2019-09-21 02:07:26 +09:00
Hide_D 0ef3921e17 update 서버 변경 2019-09-21 02:06:49 +09:00
Hide_D efcf0f772e server checkout 추가2 2019-09-21 01:50:36 +09:00
Hide_D ccabe847bb 루트도 git tree-ish 지정 가능 2019-09-21 01:42:21 +09:00
Hide_D 45ed63ffe3 버그 수정 2019-09-21 01:38:29 +09:00
Hide_D 7bebbe3a16 징병, 모병 추가 2019-09-21 01:09:17 +09:00
Hide_D 53ba1db79f autorun_user 초기 세팅 2019-09-20 02:12:42 +09:00
Hide_D 76c306a122 npc AI를 '사전 턴' 수행 이후에 처리하도록 변경 2019-09-20 00:41:38 +09:00
Hide_D 89c2c163cb 서버 정보에 자동행동 표기 2019-09-20 00:35:13 +09:00
Hide_D 8826061266 autorun_user 인자 세팅 2019-09-20 00:05:40 +09:00
Hide_D e684877c94 리셋 화면에서 '휴식 턴 시 장수 턴' 추가 2019-09-19 02:21:51 +09:00
Hide_D 12c8152901 docker 메시지 수정 2019-09-19 01:16:21 +09:00
Hide_D 8ba20bf4d2 Docker를 이용한 설치 안내 2019-09-15 23:25:11 +09:00
Hide_D 0bc1ad09d1 년도 변경 2019-09-15 23:19:04 +09:00
Hide_D 231c79132a run_daemon 1분 유지 수정 2019-09-15 20:59:35 +09:00
Hide_D 089803c599 cron 수정 2019-09-15 20:53:23 +09:00
Hide_D 4ea373aff6 gitignore change 2019-09-15 20:08:57 +09:00
Hide_D 0d94b8c742 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2019-09-15 19:49:32 +09:00
Hide_D d444f19043 date_default_timezone_set 해제 2019-09-15 19:49:24 +09:00
Hide_D 87a0e73c96 인스톨러 버그 수정 2019-09-15 02:59:38 +09:00
Hide_D b5922095f0 인스톨러 임시 트윅 2019-09-15 02:50:10 +09:00
Hide_D 3fee29e9e9 setup_db에서 global_salt 추가 2019-09-15 00:55:57 +09:00
Hide_D 4e351b3be8 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2019-09-15 00:38:00 +09:00
Hide_D 3432b900df 설치 직후 기본 gitpath 변경 2019-09-15 00:37:46 +09:00
Hide_D fb7c67f317 빙의 안되는 버그 수정, 가입/빙의 시 락 2019-08-18 18:01:11 +09:00
Hide_D 28d5a5c39a 장수 생성시 빠르게 쿼리를 날려 중복 생성하는 것이 불가능하도록 2019-08-18 17:50:38 +09:00
Hide_D e2754511d9 부대탈퇴 시 propergation 처리 실수 수정 2019-08-18 00:46:39 +09:00
29 changed files with 649 additions and 123 deletions
+1 -7
View File
@@ -1,11 +1,4 @@
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# 체섭 ignore
*.log
@@ -48,3 +41,4 @@ test.php
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2018 Hide_D, 62che
Copyright (c) 2019 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
+11 -6
View File
@@ -11,16 +11,21 @@
* <code>php-fpm</code> 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다. (기본값: 지원)
* mysqlnd가 지원되어야합니다. (기본값: 지원)
* mysqli
* gd
* MariaDB 10.2.1 이상
* MySQL 5.6 이상도 가능하도록 할 예정입니다.
* 현재 MySQL은 지원하지 않습니다.
* <code>git</code>
* <code>curl</code>
Linux는 Ubuntu 16.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다.
Linux는 Ubuntu 16.04, 18.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다.
Docker를 이용한 설치는 계획중입니다.
## 설치
## Docker를 이용한 설치
https://storage.hided.net/gogs/devsam/docker 를 참고해 주세요.
## 수동 설치
본 게임은 <code>git</code>을 이용한 업그레이드 시스템을 구현하였으므로, <code>git</code>이 필요합니다.
또한 웹 서비스 데몬을 운영중인 사용자(일반적으로 <code>www-data</code>, <code>apache</code>)에게 디렉토리 권한이 주어져야합니다.
@@ -30,8 +35,8 @@ Docker를 이용한 설치는 계획중입니다.
웹 데몬 user가 <code>www-data</code>인 경우 다음과 같이 입력하여 최신 배포버전과 이미지 파일을 얻을 수 있습니다.
```
sudo -u www-data git clone ssh://git@storage.hided.net:2525/devsam/core.git
git clone ssh://git@storage.hided.net:2525/devsam/image.git
sudo -u www-data git clone https://storage.hided.net/gogs/devsam/core.git
git clone https://storage.hided.net/gogs/devsam/image.git
```
> 이미지는 git hook을 이용한 업데이트 기능을 제공하지만 아직 범용성 있는 설계가 되어있진 않습니다.
-1
View File
@@ -3,7 +3,6 @@ namespace sammo;
define('ROOT', realpath(__dir__.'/..'));
setlocale(LC_ALL, 'ko_KR.UTF-8');
date_default_timezone_set('Asia/Seoul');
mb_internal_encoding("UTF-8");
mb_http_output('UTF-8');
mb_regex_encoding('UTF-8');
+32
View File
@@ -98,6 +98,38 @@ require(__dir__.'/../vendor/autoload.php');
</div>
</div>
<div class="form-group row">
<label for="image_request_key" class="col-sm-4 col-form-label">이미지 갱신 키</label>
<div class="input-group col-sm-8">
<input type="text" class="form-control" name="image_request_key" id="image_request_key"
placeholder="이미지 서버의 hook/HashKey.php의 값과 동일하게"
value="" />
<div class="input-group-append">
<button id="btn_random_generate_key" class="btn btn-secondary" type="button">랜덤 생성</button>
</div>
</div>
</div>
<hr style="width:100%; border-top: 1px solid lightgray;">
<div class="form-group row">
<label for="kakao_rest_key" class="col-sm-4 col-form-label">카카오 API Rest Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_rest_key" id="kakao_rest_key"
placeholder="카카오톡 API의 Rest Key"
value="" />
</div>
</div>
<div class="form-group row">
<label for="kakao_admin_key" class="col-sm-4 col-form-label">카카오 API Admin Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_admin_key" id="kakao_admin_key"
placeholder="카카오톡 API의 Admin Key"
value="" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-4"></div>
<div class="col-sm-8">
+21 -2
View File
@@ -11,6 +11,11 @@ $dbName = Util::getReq('db_name');
$servHost = Util::getReq('serv_host');
$sharedIconPath = Util::getReq('shared_icon_path');
$gameImagePath = Util::getReq('game_image_path');
$imageRequestKey = Util::getReq('image_request_key');
$kakaoRESTKey = Util::getReq('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getReq('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([
@@ -186,6 +191,8 @@ $globalSalt = bin2hex(random_bytes(16));
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath.'/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath.'/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/ServConfig.orig.php',
@@ -193,11 +200,17 @@ $result = Util::generateFileUsingSimpleTemplate(
[
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
'gameImagePath'=>$gameImagePath,
'imageRequestPath'=>$imageRequestPath,
'imageRequestKey'=>$imageRequestKey
],
true
);
if($imageRequestKey){
@file_get_contents($imageKeyInstallPath.'?key='.$imageRequestKey);
}
if ($result !== true) {
Json::die([
'result'=>false,
@@ -263,10 +276,15 @@ $result = Util::generateFileUsingSimpleTemplate(
]
);
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost.'/');
Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/KakaoKey.orig.php',
ROOT.'/d_setting/KakaoKey.php',
[
'REST_API_KEY'=>$kakaoRESTKey,
'ADMIN_KEY'=>$kakaoAdminKey,
'REDIRECT_URI'=>$kakaoRedirectURI
],
true
);
@@ -280,5 +298,6 @@ if ($result !== true) {
Json::die([
'result'=>true,
'reason'=>'success'
'reason'=>'success',
'globalSalt'=>$globalSalt
]);
+9
View File
@@ -10,6 +10,8 @@ class ServConfig
public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_';
public static function getSharedIconPath(string $filepath='') : string
{
@@ -32,6 +34,13 @@ class ServConfig
return static::$gameImagePath;
}
public static function getImagePullURI() : string
{
$now = time();
$req_hash = Util::hashPassword(sprintf("%016x",$now), static::$imageRequestKey);
return static::$imageRequestPath."?req={$req_hash}&time={$now}";
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
+3 -1
View File
@@ -27,7 +27,7 @@ $userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime']);
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime','autorun_user']);
$connect=$db->get();
increaseRefresh("내정보", 1);
@@ -161,8 +161,10 @@ $('#die_immediately').click(function(){
<input type=<?=$submit?> name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br>
∞<font color=orange>설정저장은 이달중 <?=$me['myset']?>회 남았습니다.</font><br><br>
</form>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
휴 가 신 청<br>
<a href="c_vacation.php"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button></a><br><br>
<?php endif; ?>
<!--빙의 해제용 삭턴 조절<br>
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
+9 -3
View File
@@ -87,8 +87,14 @@ jQuery(function($){
$('#form1').submit(function(){
return false;
});
$('.submitBtn').click(function(){
$('#leaveTroop').click(function(e){
return confirm("정말 부대를 탈퇴하시겠습니까?");
})
$('.submitBtn').click(function(event){
if(event.isPropagationStopped()){
return false;
}
console.log('b');
var $this=$(this);
$.post({
@@ -140,7 +146,7 @@ $('.submitBtn').click(function(){
<?php elseif($me['troop'] == 0): ?>
<input type=submit class='submitBtn' value='부 대 가 입'>
<?php else: ?>
<input type=submit class='submitBtn' value='부 대 탈 퇴' onclick='return confirm("정말 부대를 탈퇴하시겠습니까?")'>
<input type=submit id="leaveTroop" class='submitBtn' value='부 대 탈 퇴'>
<?php endif;?>
</td></tr></tfoot>
<tbody>
+6
View File
@@ -10,6 +10,12 @@ $userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$autorun_user = $gameStor->autorun_user;
if($autorun_user['limit_minutes']??false){
//자동 턴인 경우에는 휴가 불가
header('location:b_myPage.php', true, 303);
}
$killturn = $gameStor->killturn;
$db->update('general', [
+12 -6
View File
@@ -1596,6 +1596,7 @@ function checkTurn() {
CheckOverhead();
//서버정보
$autorun_user = $gameStor->autorun_user;
// 최종 처리 월턴의 다음 월턴시간 구함
$prevTurn = cutTurn($gameStor->turntime, $gameStor->turnterm);
@@ -1614,12 +1615,15 @@ function checkTurn() {
//if(PROCESS_LOG) $processlog[0] = "[{$date}] 월턴 이전 갱신: name({$general['name']}), no({$general['no']}), turntime({$general['turntime']}), turn0({$general['turn0']})";
//if(PROCESS_LOG) pushProcessLog($processlog);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', processAI');
if($general['npc'] >= 2) { processAI($general['no']); } // npc AI 처리
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', PreprocessCommand');
PreprocessCommand($general['no']);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', processAI');
$reduce_turn = false;
if($general['npc'] >= 2 || ($autorun_user['limit_minutes']??false)) {
processAI($general['no'], $reduce_turn);
} // npc AI 처리
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', processCommand');
processCommand($general['no']);
processCommand($general['no'], $reduce_turn);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', updateCommand');
updateCommand($general['no']);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', updateTurntime');
@@ -1731,12 +1735,14 @@ function checkTurn() {
//if(PROCESS_LOG) $processlog[0] = "[{$date}] 월턴 이후 갱신: name({$general['name']}), no({$general['no']}), turntime({$general['turntime']}), turn0({$general['turn0']})";
//if(PROCESS_LOG) pushProcessLog($processlog);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', processAI');
if($general['npc'] >= 2) { processAI($general['no']); } // npc AI 처리
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', PreprocessCommand');
PreprocessCommand($general['no']);
$reduce_turn = false;
if($general['npc'] >= 2 || ($autorun_user['limit_minutes']??false)) {
processAI($general['no'], $reduce_turn);
}
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', processCommand');
processCommand($general['no']);
processCommand($general['no'], $reduce_turn);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', updateCommand');
updateCommand($general['no']);
//if(STEP_LOG) pushStepLog(date('Y-m-d H:i:s').', updateTurntime');
+3 -1
View File
@@ -483,7 +483,7 @@ function getCoreTurn($nation, $level) {
}
function processCommand($no) {
function processCommand($no, $reduceTurn) {
$session = Session::getInstance();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -561,6 +561,8 @@ function processCommand($no) {
$newKillturn = $general['killturn'] - 1;
} elseif($command[0] == 0) {
$newKillturn = $general['killturn'] - 1;
} elseif($reduceTurn == true){
$newKillturn = $general['killturn'] - 1;
} else {
$newKillturn = $killturn;
}
+196 -50
View File
@@ -1,6 +1,75 @@
<?php
namespace sammo;
class AIAllowedAction{
public $develop = true;
public $warp = true;
public $randomRecruit = true;
public $recruit = true;
public $recruit_high = false;
public $train = true;
public $atmos = true;
public $battle = true;
public $appointment = true;
public $changeWarCondition = true;
public $donation = true;
public $buySellRice = true;
public $staffAction = true;
function __construct($npc, $aiOptions){
if($npc >= 2){
return;
}
$this->develop = false;
$this->warp = false;
$this->randomRecruit = false;
$this->recruit = false;
$this->recruit_high = false;
$this->train = false;
$this->atmos = false;
$this->battle = false;
$this->appointment = false;
$this->changeWarCondition = false;
$this->donation = false;
$this->buySellRice = true;
$this->staffAction = false;
foreach($aiOptions as $key=>$value){
assert($value);
switch($key){
case 'develop':
$this->develop = true;
break;
case 'warp':
$this->warp = true;
break;
case 'recruit_high':
$this->recruit_high = true;
case 'recruit':
$this->recruit = true;
$this->changeWarCondition = true;
break;
case 'train':
$this->train = true;
$this->atmos = true;
$this->changeWarCondition = true;
break;
case 'battle':
$this->battle = true;
break;
}
}
}
}
function SetDevelop($genType, $no, $city, $tech) {
$db = DB::db();
$connect=$db->get();
@@ -83,7 +152,7 @@ function SetDevelop($genType, $no, $city, $tech) {
return;
}
function SetCrew($no, $nationID, $personal, $gold, $leader, $genType, $tech, $dex0, $dex10, $dex20, $dex30, $dex40) {
function SetCrew($no, $nationID, $personal, $gold, $leader, $genType, $tech, $dex0, $dex10, $dex20, $dex30, $dex40, $currentCrewType, AIAllowedAction $allowedAction) {
$db = DB::db();
$connect=$db->get();
@@ -160,7 +229,13 @@ function SetCrew($no, $nationID, $personal, $gold, $leader, $genType, $tech, $de
}
if($types){
$type = Util::choiceRandom($types);
if(!$allowedAction->randomRecruit && in_array($currentCrewType, $types) && $type != GameUnitConst::DEFAULT_CREWTYPE){
$type = $currentCrewType;
}
else{
$type = Util::choiceRandom($types);
}
}
else{
$type = GameUnitConst::DEFAULT_CREWTYPE;
@@ -175,19 +250,25 @@ function SetCrew($no, $nationID, $personal, $gold, $leader, $genType, $tech, $de
$crew = intdiv($gold, $cost);
if($leader < $crew) { $crew = $leader; }
$command = EncodeCommand(0, $type, $crew, 11);
if($allowedAction->recruit_high && $crew * $cost * 6 < $gold){
$command = EncodeCommand(0, $type, $crew, 12);
}
else{
$command = EncodeCommand(0, $type, $crew, 11);
}
$query = "update general set turn0='$command' where no='$no'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
return;
}
function processAI($no) {
function processAI($no, &$reduce_turn) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$admin = $gameStor->getValues(['startyear','year','month','turnterm','scenario','gold_rate','rice_rate']);
$admin = $gameStor->getValues(['startyear','year','month','turnterm','scenario','gold_rate','rice_rate','killturn','autorun_user']);
// 초반 여부
if($admin['startyear']+2 > $admin['year'] || ($admin['startyear']+2 == $admin['year'] && $admin['month'] < 5)) {
$isStart = 1;
@@ -195,7 +276,8 @@ function processAI($no) {
$isStart = 0;
}
$query = "select no,turn0,npcid,name,nation,nations,city,level,npcmsg,personal,leader,intel,power,gold,rice,crew,train,atmos,troop,npc,affinity,mode,injury,picture,imgsvr,killturn,makelimit,dex0,dex10,dex20,dex30,dex40 from general where no='$no'";
$query = "select no,turn0,npcid,name,nation,nations,city,level,npcmsg,personal,leader,intel,power,gold,rice,crew,crewtype,train,atmos,troop,npc,affinity,mode,injury,picture,imgsvr,killturn,makelimit,dex0,dex10,dex20,dex30,dex40 from general where no='$no'";
$result = MYDB_query($query, $connect) or Error("processAI01 ".MYDB_error($connect),"");
$general = MYDB_fetch_array($result);
@@ -240,15 +322,55 @@ function processAI($no) {
return;
}
$autorun_user = $admin['autorun_user'];
if($general['npc'] < 2){
$autorun_limit_minutes = $autorun_user['limit_minutes']??0;
if(!$autorun_limit_minutes){
return;
}
if($general['nation'] == 0){
return;
}
$blankTurnCnt = $admin['killturn']-$general['killturn'];
if($blankTurnCnt * $admin['turnterm'] > $autorun_limit_minutes){
return;
}
}
// 입력된 턴이 있으면 그것 실행
if(DecodeCommand($general['turn0'])[0] != 0) {
return;
}
$query = "select city,region,nation,level,path,rate,gen1,gen2,gen3,pop,supply,front from city where city='{$general['city']}'";
$reduce_turn = true;
$allowedAction = new AIAllowedAction($general['npc'], $autorun_user['options']??[]);
if($general['troop'] && $allowedAction->warp){
$troopLeader = $db->query(
'SELECT general.no,general.name,general.city,turn0,troop,general.nation, city.nation AS city_nation FROM general JOIN city ON city.city = general.city WHERE troop = %i', $general['troop']
);
if(DecodeCommand($troopLeader['turn0'])[0] != 26){
//valid
}
else if($troopLeader['nation'] == $troopLeader['city_nation']){
//valid
}
else{
$allowedAction->warp = false;
}
}
$query = "select city,region,nation,level,path,rate,gen1,gen2,gen3,pop,supply,front,trade from city where city='{$general['city']}'";
$result = MYDB_query($query, $connect) or Error("processAI02 ".MYDB_error($connect),"");
$city = MYDB_fetch_array($result);
if ($general['npc'] < 2 && $allowedAction->buySellRice) {
if($city['trade'] == 0){
$allowedAction->buySellRice = false;
}
}
$query = "select nation,level,tech,gold,rice,rate,type,color,name,war from nation where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error("processAI03 ".MYDB_error($connect),"");
$nation = MYDB_fetch_array($result)??[
@@ -327,17 +449,20 @@ function processAI($no) {
$tech = getTechCost($nation['tech']);
$resrc = $tech * 700;//XXX: 왜 700이지?
if($general['atmos'] >= 90 && $general['train'] >= 90) {
if($general['mode'] == 0) {
$query = "update general set mode=1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
}
} else {
if($general['mode'] == 1) {
$query = "update general set mode=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
if($allowedAction->changeWarCondition){
if($general['atmos'] >= 90 && $general['train'] >= 90) {
if($general['mode'] == 0) {
$query = "update general set mode=1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
}
} else {
if($general['mode'] == 1) {
$query = "update general set mode=0 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
}
}
}
//운영자메시지 출력 하루 6번..?
//특별 메세지 있는 경우 출력 하루 4번
@@ -369,7 +494,7 @@ function processAI($no) {
$rulerNation = $db->queryFirstField('SELECT nation FROM general WHERE `level`=12 AND npc=9 and nation not in %li ORDER BY RAND() limit 1', Json::decode($general['nations']));
if($ruler) {
if($rulerNation) {
$command = EncodeCommand(0, 0, $rulerNation, 25); //임관
} else {
$command = EncodeCommand(0, 0, 0, 42); //견문
@@ -377,7 +502,7 @@ function processAI($no) {
$query = "update general set turn0='$command' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
return;
} elseif($general['npc'] != 9 && $general['level'] == 0) {
} elseif($general['npc'] != 9 && $general['level'] == 0 && $allowedAction->appointment) {
switch(Util::choiceRandomUsingWeight([11.4, 40, 20, 28.6])) {
//임관 10%
case 0:
@@ -432,7 +557,7 @@ function processAI($no) {
$rulerCommand = 0;
//군주가 할일
if($general['level'] == 12) {
if($general['level'] == 12 && $allowedAction->staffAction) {
//오랑캐인데 공격 못하면 바로 방랑/해산
if($general['npc'] == 9 && $dipState == 0 && !$attackable) {
//방랑군이냐 아니냐
@@ -547,7 +672,7 @@ function processAI($no) {
}
//방랑군 아니고, 입력된 턴이 없을때 수뇌부가 할일
if($nation['level'] != 0 && $general['level'] >= 5 && $rulerCommand == 0) {
if($nation['level'] != 0 && $general['level'] >= 5 && $rulerCommand == 0 && $allowedAction->staffAction) {
$command = NPCStaffWork($general, $nation, $dipState);
if($command){
$db->update('nation', [
@@ -569,7 +694,7 @@ function processAI($no) {
} elseif($general['injury'] > 10) {
// 부상 2달 이상이면 요양
$command = EncodeCommand(0, 0, 0, 50); //요양
} elseif($nation['level'] == 0) {
} elseif($nation['level'] == 0 && $allowedAction->appointment) {
//방랑군일때
if($admin['startyear']+3 <= $admin['year']) {
$command = EncodeCommand(0, 0, 0, 45); //하야
@@ -591,7 +716,7 @@ function processAI($no) {
return;
}
if($general['leader'] < 40){
if($general['leader'] < 40 && $allowedAction->donation){
//무지장인데
if(
@@ -626,7 +751,7 @@ function processAI($no) {
}
//국가 병량이 없을때 바로 헌납
if($nation['rice'] < 2000 && $general['rice'] > 200) {
if($nation['rice'] < 2000 && $general['rice'] > 200 && $allowedAction->donation) {
$amount = intdiv($general['rice'] - 200, 100) + 1;
if($amount > 20) { $amount = 20; }
$command = EncodeCommand(0, 2, $amount, 44); //헌납
@@ -646,23 +771,23 @@ function processAI($no) {
$target = array();
// 평시거나 초반아니면서 공격가능 없으면서 병사 있으면 해제(25%)
if($dipState == 0 && $isStart == 0 && !$attackable && $general['crew'] > 0 && rand()% 100 < 25) {
if($allowedAction->recruit && $dipState == 0 && $isStart == 0 && !$attackable && $general['crew'] > 0 && rand()% 100 < 25) {
$command = EncodeCommand(0, 0, 0, 17); //소집해제
} elseif($dipState <= 1 || $isStart == 1) {
//평시이거나 선포있어도 초반이면
if($general['gold'] + $general['rice'] < 200) { $command = EncodeCommand(0, 0, 0, 9); } //금쌀없으면 조달9
elseif($general['rice'] > 100 && $city['rate'] < 95) { $command = EncodeCommand(0, 0, 0, 4); } //우선 선정
elseif($general['gold'] < 100) { //금없으면 쌀팜
elseif($general['rice'] > 100 && $city['rate'] < 95 && $allowedAction->develop) { $command = EncodeCommand(0, 0, 0, 4); } //우선 선정
elseif($general['gold'] < 100 && $allowedAction->buySellRice) { //금없으면 쌀팜
$amount = intdiv(($general['rice'] - $general['gold'])/2, 100); // 100단위
$command = EncodeCommand(0, 1, $amount, 49); //팜
} elseif($general['gold'] < 500 && $general['rice'] < 500) { $command = EncodeCommand(0, 0, 0, 1); } //금쌀되면 내정
elseif($general['rice'] < 100) { //쌀없으면 쌀삼
} elseif($general['gold'] < 500 && $general['rice'] < 500 && $allowedAction->develop) { $command = EncodeCommand(0, 0, 0, 1); } //금쌀되면 내정
elseif($general['rice'] < 100 && $allowedAction->buySellRice) { //쌀없으면 쌀삼
$amount = intdiv(($general['gold'] - $general['rice'])/2, 100); // 100단위
$command = EncodeCommand(0, 2, $amount, 49); //삼
} elseif($genType >= 2) { $command = EncodeCommand(0, 0, 0, 1); } //내정장일때 내정
} elseif($genType >= 2 && $allowedAction->develop) { $command = EncodeCommand(0, 0, 0, 1); } //내정장일때 내정
else {
//현도시가 전방이면 공격 가능성 체크
if($city['front'] > 0) {
if($city['front'] > 0 && $allowedAction->battle) {
//주변도시 체크
$paths = explode('|', $city['path']);
for($i=0; $i < count($paths); $i++) {
@@ -687,6 +812,11 @@ function processAI($no) {
$sel = rand() % 10;
if($selCity['dev'] > 95) { $sel = 9; }
elseif($selCity['dev'] < 70) { $sel = 0; }
if(!$allowedAction->warp){
$sel = 0;
}
switch($sel) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 그대로 내정 80 %
$command = EncodeCommand(0, 0, 0, 1);
@@ -729,22 +859,22 @@ function processAI($no) {
} else { // 공격인 경우
if($general['crew'] < 1000 && $general['gold'] >= $resrc && $general['rice'] >= $resrc) { //자원되고, 병사없을때
if($city['pop'] > 40000) { $command = EncodeCommand(0, 0, 0, 11); }
if($city['pop'] > 40000 && $allowedAction->recruit) { $command = EncodeCommand(0, 0, 0, 11); }
else { $command = EncodeCommand(0, 0, 0, 1); }
} elseif($general['rice'] < $resrc && $general['rice'] <= $general['gold']) {
} elseif($general['rice'] < $resrc && $general['rice'] <= $general['gold'] && $allowedAction->buySellRice) {
//금이 더 많으면 매매
$amount = intdiv(($general['gold'] - $general['rice']) / 2, 100); // 100단위
if($amount > 0) { $command = EncodeCommand(0, 2, $amount, 49); }//삼
else { $command = EncodeCommand(0, 0, 0, (rand()%2)*8 + 1); } // 내정, 조달
} elseif($general['gold'] < $resrc && $general['rice'] > $general['gold']) {
} elseif($general['gold'] < $resrc && $general['rice'] > $general['gold'] && $allowedAction->buySellRice) {
//쌀이 더 많으면 매매
$amount = intdiv(($general['rice'] - $general['gold']) / 2, 100); // 100단위
if($amount > 0) { $command = EncodeCommand(0, 1, $amount, 49); }//팜
else { $command = EncodeCommand(0, 0, 0, (rand()%2)*8 + 1); } // 내정, 조달
//자원, 병사 모두 충족
} elseif($general['crew'] >= 1000 && $general['train'] < 90) {
} elseif($general['crew'] >= 1000 && $general['train'] < 90 && $allowedAction->train) {
$command = EncodeCommand(0, 0, 0, 13); //훈련
} elseif($general['crew'] >= 1000 && $general['atmos'] < 90) {
} elseif($general['crew'] >= 1000 && $general['atmos'] < 90 && $allowedAction->atmos) {
$command = EncodeCommand(0, 0, 0, 14); //사기진작
} else {
//공격
@@ -764,18 +894,18 @@ function processAI($no) {
//전시일때
if($general['gold'] + $general['rice'] < $resrc*2) { $command = EncodeCommand(0, 0, 0, 9); } //금쌀없으면 조달
elseif($general['rice'] > $resrc && $city['rate'] < 95 && $city['front'] == 0) { $command = EncodeCommand(0, 0, 0, 4); } // 우선 선정
elseif($general['rice'] > $resrc && $city['rate'] < 50 && $city['front'] > 0) { $command = EncodeCommand(0, 0, 0, 4); } // 우선 선정
elseif($general['gold'] < $resrc || ($general['gold'] < $resrc *2 && $general['rice'] > $resrc * 6)) { // 금없으면 쌀팜
elseif($general['rice'] > $resrc && $city['rate'] < 95 && $city['front'] == 0 && $allowedAction->develop) { $command = EncodeCommand(0, 0, 0, 4); } // 우선 선정
elseif($general['rice'] > $resrc && $city['rate'] < 50 && $city['front'] > 0 && $allowedAction->develop) { $command = EncodeCommand(0, 0, 0, 4); } // 우선 선정
elseif(($general['gold'] < $resrc || ($general['gold'] < $resrc *2 && $general['rice'] > $resrc * 6)) && $allowedAction->buySellRice) { // 금없으면 쌀팜
$amount = intdiv(($general['rice'] - $general['gold'])/2, 100); // 100단위
if($amount > 0) { $command = EncodeCommand(0, 1, $amount, 49); }// 팜
else { $command = EncodeCommand(0, 0, 0, 9); } // 조달
} elseif($general['rice'] < $resrc || ($general['rice'] < $resrc *2 && $general['gold'] > $resrc * 6)) { // 쌀없으면 쌀삼
} elseif(($general['rice'] < $resrc || ($general['rice'] < $resrc *2 && $general['gold'] > $resrc * 6)) && $allowedAction->buySellRice) { // 쌀없으면 쌀삼
$amount = intdiv(($general['gold'] - $general['rice'])/2, 100); // 100단위
if($amount > 0) { $command = EncodeCommand(0, 2, $amount, 49); }// 팜
else { $command = EncodeCommand(0, 0, 0, 9); } // 조달
} elseif($genType >= 2) { $command = EncodeCommand(0, 0, 0, 1); } //내정장일때 내정
elseif($general['crew'] < 1000 && $general['gold'] >= $resrc && $general['rice'] >= $resrc) {
elseif($general['crew'] < 1000 && $general['gold'] >= $resrc && $general['rice'] >= $resrc && $allowedAction->recruit) {
$query = "select no from general where nation='{$general['nation']}'";
$result = MYDB_query($query, $connect) or Error("processAI16 ".MYDB_error($connect),"");
$genCount = MYDB_num_rows($result);
@@ -795,12 +925,12 @@ function processAI($no) {
// 전체 인구 대비 확률로 현지에서 징병
if($city['pop'] > 40000 && 100 + $ratio - $ratio2 > $ratio3) {
$command = EncodeCommand(0, 0, 0, 11); //인구 되면 징병
} else {
} else{
// 인구 안되면 4만 이상인 도시로 워프
$query = "select city from city where nation='{$general['nation']}' and pop>40000 and supply='1' order by rand() limit 0,1";
$result = MYDB_query($query, $connect) or Error("processAI16 ".MYDB_error($connect),"");
$cityCount = MYDB_num_rows($result);
if($cityCount > 0) {
if($cityCount > 0 && $allowedAction->warp) {
$selCity = MYDB_fetch_array($result);
//워프
$query = "update general set city='{$selCity['city']}' where no='{$general['no']}'";
@@ -810,17 +940,17 @@ function processAI($no) {
$query = "update general set turn0='$command' where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI23 ".MYDB_error($connect),"");
return;
} else {
} else if($allowedAction->develop){
$command = EncodeCommand(0, 0, 0, 7); //인구 안되면 정장
}
}
} elseif($general['crew'] >= 1000 && $general['train'] < 90) {
} elseif($general['crew'] >= 1000 && $general['train'] < 90 && $allowedAction->train) {
if($general['atmos'] >= 90 && $general['train'] >= 60 && $general['mode'] == 0) {
$query = "update general set mode=1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
}
$command = EncodeCommand(0, 0, 0, 13); //훈련
} elseif($general['crew'] >= 1000 && $general['atmos'] < 90) {
} elseif($general['crew'] >= 1000 && $general['atmos'] < 90 && $allowedAction->atmos) {
if($general['atmos'] >= 60 && $general['train'] >= 90 && $general['mode'] == 0) {
$query = "update general set mode=1 where no='{$general['no']}'";
MYDB_query($query, $connect) or Error("processAI05 ".MYDB_error($connect),"");
@@ -844,7 +974,7 @@ function processAI($no) {
if($dip['state'] == 0) $target[] = $targetCity['city'];
}
}
if(count($target) == 0) {
if(count($target) == 0 && $allowedAction->warp) {
//전방 도시 선택, 30% 확률로 태수 있는 전방으로 워프
if(rand()%100 < 30) {
$query = "select city from city where nation='{$general['nation']}' and supply='1' and front>0 order by gen1 desc,rand() limit 0,1";
@@ -879,20 +1009,36 @@ function processAI($no) {
} else {
$command = EncodeCommand(0, 0, 0, (rand()%2)*8 + 1); //공격 가능도시가 없고 워프도 안되면 내정, 조달
}
} elseif($nation['war'] == 1) {
} elseif($nation['war'] == 1 || !$allowedAction->battle) {
//전금이면 내정, 조달
$command = EncodeCommand(0, 0, 0, (rand()%2)*8 + 1); //내정, 조달
} else { $command = EncodeCommand(0, 0, $target[rand()%count($target)], 16); } //있으면 공격
} else if($target){ $command = EncodeCommand(0, 0, $target[rand()%count($target)], 16); } //있으면 공격
}
}
}
switch($command) {
case EncodeCommand(0, 0, 0, 1): //내정
SetDevelop($genType, $general['no'], $general['city'], $nation['tech']);
if($allowedAction->develop){
SetDevelop($genType, $general['no'], $general['city'], $nation['tech']);
}
else{
$db->update('general', [
'turn0'=>EncodeCommand(0, 0, 0, 29)
], 'no=%i', $general['no']);
}
return;
case EncodeCommand(0, 0, 0, 11): //징병
SetCrew($general['no'], $general['nation'], $general['personal'], $general['gold'], $general['leader'], $genType, $nation['tech'], $general['dex0'], $general['dex10'], $general['dex20'], $general['dex30'], $general['dex40']);
if ($allowedAction->recruit) {
SetCrew($general['no'], $general['nation'], $general['personal'], $general['gold'], $general['leader'], $genType, $nation['tech'], $general['dex0'], $general['dex10'], $general['dex20'], $general['dex30'], $general['dex40'], $general['crewtype'], $allowedAction);
}
else{
$db->update('general', [
'turn0'=>EncodeCommand(0, 0, 0, 29)
], 'no=%i', $general['no']);
}
return;
default:
$query = "update general set turn0='$command' where no='{$general['no']}'";
+95
View File
@@ -152,6 +152,101 @@ if($session->userGrade < 5 && !$allowReset){
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">휴식 턴 시 장수 턴</label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group-prepend btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="develop" name="autorun_develop" id="autorun_develop">내정
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="warp" name="autorun_warp" id="autorun_warp">순간이동
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="recruit" name="autorun_recruit" id="autorun_recruit">징병
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="recruit_high" name="autorun_recruit_high" id="autorun_recruit_high">모병
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="train" name="autorun_train" id="autorun_train">훈사
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="battle" name="autorun_battle" id="autorun_battle">출병
</label>
</div>
<div class="input-group-append">
<span class="input-group-text">유효 시간</span>
</div>
<select class="custom-select" name="autorun_user_minutes" id="autorun_user_minutes">
<option value="0" selected>꺼짐</option>
<option value="43200">항상</option>
<option value="10">10분</option>
<option value="20">20분</option>
<option value="30">30분</option>
<option value="60">1시간</option>
<option value="120">2시간</option>
<option value="180">3시간</option>
<option value="240">4시간</option>
<option value="360">6시간</option>
<option value="480">8시간</option>
<option value="600">10시간</option>
<option value="720">12시간</option>
<option value="1440">24시간</option>
<option value="2160">36시간</option>
<option value="2880">48시간</option>
<option value="3600">60시간</option>
<option value="4320">72시간</option>
</select>
</div>
</div>
</div>
<!--
<div class="form-group row">
<label class="col-sm-3 col-form-label">휴식 턴 시 사령 턴</label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group-prepend btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="autorun_chief_reward" id="autorun_chief_reward">포상/몰수
</label>
<label class="btn btn-secondary">
<input type="radio" name="autorun_chief_warp" id="autorun_chief_warp">발령
</label>
<label class="btn btn-secondary">
<input type="radio" name="autorun_chief_declaration" id="autorun_chief_declaration">선포
</label>
</div>
<div class="input-group-append">
<span class="input-group-text">유효 시간</span>
</div>
<select class="custom-select" name="autorun_chief_minutes" id="autorun_chief_minutes">
<option value="0" selected>꺼짐</option>
<option value="43200">항상</option>
<option value="10">10분</option>
<option value="20">20분</option>
<option value="30">30분</option>
<option value="60">1시간</option>
<option value="120">2시간</option>
<option value="180">3시간</option>
<option value="240">4시간</option>
<option value="360">6시간</option>
<option value="480">8시간</option>
<option value="600">10시간</option>
<option value="720">12시간</option>
<option value="1440">24시간</option>
<option value="2160">36시간</option>
<option value="2880">48시간</option>
<option value="3600">60시간</option>
<option value="4320">72시간</option>
</select>
</div>
</div>
</div>
-->
<div class="form-group row">
<label for="join_mode" class="col-sm-3 col-form-label">임관 모드</label>
<div class="col-sm-9">
+2 -1
View File
@@ -89,7 +89,8 @@ $result = ResetHelper::buildScenario(
$options['show_img_level'],
$options['tournament_trig'],
$options['join_mode'],
$options['starttime']
$options['starttime'],
$options['autorun_user']?:null
);
$result['affected']=1;
+30 -2
View File
@@ -57,7 +57,8 @@ $v->rule('required', [
'extend',
'join_mode',
'npcmode',
'show_img_level'
'show_img_level',
'autorun_user_minutes'
])->rule('integer', [
'turnterm',
'sync',
@@ -67,6 +68,7 @@ $v->rule('required', [
'npcmode',
'show_img_level',
'tournament_trig',
'autorun_user_minutes'
])->rule('in', 'join_mode', ['onlyRandom', 'full']);
if(!$v->validate()){
Json::die([
@@ -108,6 +110,30 @@ $npcmode = (int)$_POST['npcmode'];
$show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = (int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
$autorun_user_options = [];
foreach(Util::getReq('autorun_user', 'array_string', []) as $autorun_option){
$autorun_user_options[$autorun_option] = 1;
}
if($autorun_user_minutes > 0 && !$autorun_user_options){
Json::die([
'result'=>false,
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]);
}
if($autorun_user_minutes < 0){
Json::die([
'result'=>false,
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]);
}
$autorun_user = $autorun_user_minutes?[
'limit_minutes'=>$autorun_user_minutes,
'options'=>$autorun_user_options
]:null;
if($reserve_open){
$reserve_open = new \DateTime($reserve_open);
@@ -143,6 +169,7 @@ if($reserve_open){
'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode,
'starttime'=>$open_date,
'autorun_user'=>$autorun_user
];
@@ -175,5 +202,6 @@ Json::die(ResetHelper::buildScenario(
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::DatetimeNow()
TimeUtil::DatetimeNow(),
$autorun_user
));
+18 -7
View File
@@ -22,6 +22,13 @@ $rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
list(
$year,
$month,
$maxgeneral,
$npcmode
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']);
$userNick = RootDB::db()->queryFirstField('SELECT `NAME` FROM member WHERE `NO`=%i',$userID);
if(!$userNick){
Json::die([
@@ -30,6 +37,8 @@ if(!$userNick){
]);
}
$db->query("lock tables general write, select_npc_token write");
$pickResult = $db->queryFirstField('SELECT pick_result FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
if(!$pickResult){
Json::die([
@@ -38,7 +47,6 @@ if(!$pickResult){
]);
}
$pickResult = Json::decode($pickResult);
if(!key_exists($pick, $pickResult)){
Json::die([
@@ -50,14 +58,9 @@ $pickedNPC = $pickResult[$pick];
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
list(
$year,
$month,
$maxgeneral,
$npcmode
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']);
if(!$npcmode){
$db->query("unlock tables");
Json::die([
'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다'
@@ -65,12 +68,15 @@ if(!$npcmode){
}
if ($gencount >= $maxgeneral) {
$db->query("unlock tables");
Json::die([
'result'=>false,
'reason'=>'더 이상 등록 할 수 없습니다.'
]);
}
//등록 시작
$db->update('general', [
'name2'=>$userNick,
@@ -81,7 +87,10 @@ $db->update('general', [
'owner'=>$userID,
], 'owner <= 0 AND npc = 2 AND no = %i', $pick);
if(!$db->affectedRows()){
$db->query("unlock tables");
Json::die([
'result'=>false,
'reason'=>'장수 등록에 실패했습니다.'
@@ -90,6 +99,8 @@ if(!$db->affectedRows()){
$db->delete('select_npc_token', 'owner=%i or valid_until < %s', $userID, $now);
$db->query("unlock tables");
$josaYi = JosaUtil::pick($userNick, '이');
pushGeneralHistory($pickedNPC, "<C>●</>{$year}{$month}월:<Y>{$pickedNPC['name']}</>의 육체에 <Y>{$userNick}</>{$josaYi} 빙의되다.");
//pushGenLog($me, $mylog);
+49 -1
View File
@@ -16,6 +16,8 @@ if(!class_exists('\\sammo\\DB')){
]);
}
$templates = new \League\Plates\Engine(__dir__.'/templates');
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -38,6 +40,27 @@ if(file_exists(__dir__.'/.htaccess')){
$otherTextInfo[] = '랜덤 임관 전용';
}
if($options['autorun_user']['limit_minutes']??false){
$auto_info = [];
foreach($options['autorun_user']['options'] as $auto_option => $value){
assert($value);
switch($auto_option){
case 'develop': $auto_info['내정'] = '내정'; break;
case 'warp': $auto_info['순간이동'] = '순간이동'; break;
case 'recruit': $auto_info['징병'] = $auto_info['징병']??'징병'; break;
case 'recruit_high': $auto_info['징병'] = '모병'; break;
case 'train': $auto_info['훈사'] = '훈련/사기진작'; break;
case 'battle': $auto_info['출병'] = '출병'; break;
}
}
$auto_info = join(', ', array_values($auto_info));
$otherTextInfo[] = $templates->render('tooltip', [
'text'=>'자율행동',
'info'=>$auto_info,
'style'=>'text-decoration:underline'
]);
}
if(!$otherTextInfo){
$otherTextInfo = '표준';
}
@@ -64,7 +87,7 @@ if(file_exists(__dir__.'/.htaccess')){
//TODO: 천통시에도 예약 오픈 알림이 필요..?
$admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction']);
$admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction', 'autorun_user']);
$admin['maxUserCnt'] = $admin['maxgeneral'];
$admin['npcMode'] = $admin['npcmode'];
$admin['turnTerm'] = $admin['turnterm'];
@@ -94,12 +117,37 @@ if($admin['join_mode'] == 'onlyRandom'){
$otherTextInfo[] = '랜덤 임관 전용';
}
if($admin['autorun_user']['limit_minutes']??false){
$auto_info = [];
foreach($admin['autorun_user']['options'] as $auto_option => $value){
assert($value);
switch($auto_option){
case 'develop': $auto_info['내정'] = '내정'; break;
case 'warp': $auto_info['순간이동'] = '순간이동'; break;
case 'recruit': $auto_info['징병'] = $auto_info['징병']??'징병'; break;
case 'recruit_high': $auto_info['징병'] = '모병'; break;
case 'train': $auto_info['훈사'] = '훈련/사기진작'; break;
case 'battle': $auto_info['출병'] = '출병'; break;
}
}
$auto_info = join(', ', array_values($auto_info));
$otherTextInfo[] = $templates->render('tooltip', [
'text'=>'자율행동',
'info'=>$auto_info,
'style'=>'text-decoration:underline'
]);
}
if(!$otherTextInfo){
$otherTextInfo = '표준';
}
else{
$otherTextInfo = join(', ', $otherTextInfo);
}
$admin['otherTextInfo'] = $otherTextInfo;
$admin['defaultStatTotal'] = GameConst::$defaultStatTotal;
$me = [];
+10
View File
@@ -71,6 +71,8 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year','month','maxgeneral','scenario','show_img_level','turnterm','turntime','genius','npcmode']);
########## 동일 정보 존재여부 확인. ##########
$db->query("lock tables general write, city read, storage read");
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name);
@@ -80,6 +82,7 @@ if ($oldGeneral) {
window.alert('이미 등록하셨습니다!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
if ($oldName) {
@@ -87,6 +90,7 @@ if ($oldName) {
window.alert('이미 있는 장수입니다. 다른 이름으로 등록해 주세요!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
if ($gameStor->maxgeneral <= $gencount) {
@@ -94,6 +98,7 @@ if ($gameStor->maxgeneral <= $gencount) {
window.alert('더이상 등록할 수 없습니다!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
if (mb_strlen($name) < 1) {
@@ -101,6 +106,7 @@ if (mb_strlen($name) < 1) {
window.alert('이름이 짧습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
if (mb_strlen($name) > 9) {
@@ -108,6 +114,7 @@ if (mb_strlen($name) > 9) {
window.alert('이름이 유효하지 않습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
if ($leader + $power + $intel > GameConst::$defaultStatTotal) {
@@ -115,6 +122,7 @@ if ($leader + $power + $intel > GameConst::$defaultStatTotal) {
window.alert('능력치가 ".GameConst::$defaultStatTotal."을 넘어섰습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
$db->query("unlock tables");
exit;
}
@@ -247,6 +255,8 @@ $db->insert('general', [
]);
$generalID = $db->insertId();
$db->query("unlock tables");
$cityname = CityConst::byID($city)->name;
$me = [
+28
View File
@@ -105,6 +105,22 @@ function scenarioPreview(){
}
function formSetup(){
$.validator.addMethod("autorun_user", function(value,element){
var parent = $(element).parent('.input-group');
var checkCnt = parent.find('input:checked').length;
if(value <= 0){
if(checkCnt > 0){
return false;
}
return true;
}
if(checkCnt == 0){
return false;
}
return true;
}, "유효 시간과 옵션은 동시에 설정해야합니다.");
$('#game_form').validate({
rules:{
turnterm:"required",
@@ -116,6 +132,7 @@ function formSetup(){
show_img_level:"required",
tournament_trig:"required",
join_mode:'required',
autorun_user_minutes:{required: true, autorun_user: true, min:0}
},
errorElement: "div",
errorPlacement: function ( error, element ) {
@@ -140,6 +157,15 @@ function formSetup(){
if(!$("#game_form").valid()){
return;
}
var autorun_user_minutes = parseInt($('#autorun_user_minutes').val());
var autorun_user = [];
if(autorun_user_minutes > 0){
$('.autorun_user_chk:checked').each(function(){
autorun_user.push($(this).data('key'));
});
}
$.ajax({
cache:false,
type:'post',
@@ -157,6 +183,8 @@ function formSetup(){
reserve_open:$('#reserve_open').val(),
pre_reserve_open:$('#pre_reserve_open').val(),
join_mode:$('#join_mode input:radio:checked').val(),
autorun_user_minutes:autorun_user_minutes,
autorun_user:autorun_user
}
}).then(function(result){
var deferred = $.Deferred();
+4 -2
View File
@@ -144,7 +144,8 @@ class ResetHelper{
int $show_img_level,
int $tournament_trig,
string $join_mode,
string $turntime
string $turntime,
?array $autorun_user
):array{
//FIXME: 분리할 것
if(120 % $turnterm != 0){
@@ -253,7 +254,8 @@ class ResetHelper{
'extended_general'=>$extend,
'fiction'=>$fiction,
'tnmt_trig'=>$tournament_trig,
'prev_winner'=>$prevWinner
'prev_winner'=>$prevWinner,
'autorun_user'=>$autorun_user
];
foreach(RootDB::db()->query('SELECT `no`, `name`, `picture`, `imgsvr` FROM member WHERE grade >= 5') as $admin){
+6 -5
View File
@@ -1,5 +1,6 @@
<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><?=$text??''?>
<span class="tooltiptext">
<?=$info??''?>
</span>
</span>
<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"
><span <?=isset($style)?"style=\"$style\"":''?>><?=$text??''?></span
><span class="tooltiptext"
><?=$info??''
?></span
></span>
+1 -1
View File
@@ -76,7 +76,7 @@ foreach (AppConf::getList() as $setting) {
'korName' => $serverKorName,
'color' => $serverColor,
'isRoot' => $serverDir == $rootServer,
'lastGitPath' => ($serverGitPath[$serverDir][0])??'origin/master'
'lastGitPath' => ($serverGitPath[$serverDir][0])??($serverDir == $rootServer?'devel':'origin/devel')
];
$server[] = $state;
}
+1 -1
View File
@@ -196,7 +196,7 @@ function postOAuthResult(result){
</div>
</div>
<div id="bottom_box">
<div class="container"><a href="terms.2.html">개인정보처리방침</a> &amp; <a href="terms.1.html">이용약관</a><br>© 2018 • HideD
<div class="container"><a href="terms.2.html">개인정보처리방침</a> &amp; <a href="terms.1.html">이용약관</a><br>© 2019 • HideD
<br>크롬과 파이어폭스에 최적화되어있습니다.</div></div>
</div>
+58 -6
View File
@@ -58,12 +58,13 @@ if(!$allowUpdate){
]);
}
$src_target = $storage->$server;
if($src_target){
$src_target = $src_target[0];
}
if(!$allowFullUpdate || !$target){
$target = $storage->$server;
if($target){
$target = $target[0];
}
$target = $src_target;
}
else{
$target = $request['target'];
@@ -114,6 +115,26 @@ if(!file_exists($server)){
if($server == $baseServerName){
exec("git fetch -q 2>&1", $output);
if($output){
Json::die([
'result'=>false,
'reason'=>'git pull 작업 : '.join(', ', $output)
]);
}
if($target != $src_target){
$command = sprintf('git checkout %s -q 2>&1', $target);
exec($command, $output);
if($output){
Json::die([
'result'=>false,
'reason'=>join(', ', $output)
]);
}
}
exec("git pull -q 2>&1", $output);
if($output && $output[0] != 'Already up-to-date.'){
Json::die([
@@ -129,13 +150,44 @@ if($server == $baseServerName){
'verionGit'=>$version
], true
);
if(ServConfig::$imageRequestKey){
try {
$imagePullPath = ServConfig::getImagePullURI();
$pullResult = @file_get_contents($imagePullPath);
if($pullResult === false){
throw new \ErrorException('Invalid URI');
}
$pullResult = Json::decode($pullResult);
if($pullResult['result']){
$imgResult = true;
$imgDetail = $pullResult['version'];
}
else{
$imgResult = false;
$imgDetail = $pullResult['reason'];
}
}
catch(\Exception $e){
$imgResult = false;
$imgDetail = $e->getMessage();
}
}
else{
$imgResult = true;
$imgDetail = 'No key';
}
$storage->$server = [null, $version];
$storage->$server = [$target, $version];
Json::die([
'server'=>$server,
'result'=>true,
'version'=>$version
'version'=>$version,
'imgResult'=>$imgResult,
'imgDetail'=>$imgDetail,
]);
}
+15 -13
View File
@@ -38,22 +38,20 @@ function serverUpdate(caller){
return;
}
if(isRoot){
if(!confirm('서버 라이브러리, 루트 서버에 대해 git pull을 실행합니다.')){
return;
}
}
else if(!allowFullUpdate){
if (!confirm('다음 git tree-ish 주소로 업데이트를 시도합니다 : ' + target)) {
return;
}
}
else {
if(allowFullUpdate){
target = prompt('가져올 git tree-ish 명을 입력해주세요.', target)
if(!target){
return;
}
}
else if(isRoot){
if(!confirm('서버 라이브러리, 루트 서버에 대해 git pull을 실행합니다.')){
return;
}
}
else if (!confirm('다음 git tree-ish 주소로 업데이트를 시도합니다 : ' + target)) {
return;
}
$.ajax({
@@ -66,7 +64,11 @@ function serverUpdate(caller){
}
}).then(function(response) {
if(response.result) {
alert('{0} 서버가 {1} 버전으로 업데이트 되었습니다.'.format(response.server, response.version));
var aux = '';
if(isRoot){
aux = ' (이미지 서버 갱신:{0}, {1})'.format(response.imgResult, response.imgDetail);
}
alert('{0} 서버가 {1} 버전으로 업데이트 되었습니다.{2}'.format(response.server, response.version, aux));
location.reload();
} else {
alert(response.reason);
+2 -1
View File
@@ -99,6 +99,7 @@ function Entrance_drawServerList(serverInfos){
$serverHtml.append(
TemplateEngine(serverReservedTemplate, result.reserved)
);
initTooltip($serverHtml);
return;
}
@@ -149,7 +150,7 @@ function Entrance_drawServerList(serverInfos){
TemplateEngine(serverFullTemplate, {})
);
}
else if(game.npcMode == '가'){
else if(game.npcMode == '가'){
$serverHtml.append(
TemplateEngine(serverCreateAndSelectTemplate, {serverPath:serverPath})
).addClass('server_create_and_select');
+19 -2
View File
@@ -47,6 +47,16 @@ $(document).ready( function () {
$('#serv_host').val(
[location.protocol, '//', location.host, parentPathname].join('')
);
$('#btn_random_generate_key').click(function(){
var token = '';
while(token.length < 24){
token += (Math.random() + 1).toString(36).substring(7);
}
token = token.substr(0,24);
$('#image_request_key').val(token);
});
$('#db_form').validate({
rules:{
db_host:"required",
@@ -56,7 +66,11 @@ $(document).ready( function () {
db_name:"required",
serv_host:"required",
shared_icon_path:"required",
game_image_path:"required"
game_image_path:"required",
image_request_key:{
required:false,
minlength:16
}
},
errorElement: "div",
errorPlacement: function ( error, element ) {
@@ -94,7 +108,10 @@ $(document).ready( function () {
db_name:$('#db_name').val(),
serv_host:$('#serv_host').val(),
shared_icon_path:$('#shared_icon_path').val(),
game_image_path:$('#game_image_path').val()
game_image_path:$('#game_image_path').val(),
image_request_key:$('#image_request_key').val(),
kakao_rest_key:$('#kakao_rest_key').val(),
kakao_admin_key:$('#kakao_admin_key').val(),
}
}).then(function(result){
var deferred = $.Deferred();
+7 -3
View File
@@ -5,9 +5,11 @@ import time
import glob
import urllib.request
import concurrent.futures
from datetime import datetime
def run(webPath):
print(webPath)
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"), webPath)
obj = urllib.request.urlopen(webPath)
obj.read()
@@ -44,15 +46,17 @@ def main():
servList.append(webPath)
with concurrent.futures.ThreadPoolExecutor(max_workers=len(servList)) as executor:
with concurrent.futures.ThreadPoolExecutor(max_workers=max(1,len(servList))) as executor:
waiters=[]
for resetPath in autoResetList:
future = executor.submit(run, resetPath)
waiters.append(future)
for _ in range(4):
for idx in range(4):
for webPath in servList:
future = executor.submit(run, webPath)
waiters.append(future)
if idx == 3:
break
time.sleep(15)
for future in waiters:
future.done()