Merge branch 'devel' into inherit_buff

This commit is contained in:
2021-09-12 14:56:33 +09:00
11 changed files with 1001 additions and 326 deletions
+90
View File
@@ -0,0 +1,90 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
try {
$input = json_decode(file_get_contents('php://input'));
} catch (\Exception $e) {
Json::dieWithReason($e->getMessage());
}
if (!key_exists('path', $input)) {
Json::dieWithReason('path가 지정되지 않았습니다.');
}
if (key_exists('args', $input) && !is_array($input['args'])) {
Json::dieWithReason('args가 array가 아닙니다.' . gettype($input['args']));
}
try {
$obj = buildAPIExecutorClass($input['path'], $input['args'] ?? []);
$api =
$validateResult = $obj->validateArgs();
if ($validateResult !== null) {
Json::dieWithReason($validateResult);
}
$sessionMode = $obj->getRequiredSessionMode();
if ($sessionMode === BaseAPI::NO_SESSION) {
$session = null;
} else {
if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) {
$session = Session::requireGameLogin();
} else if ($sessionMode & BaseAPI::REQ_LOGIN) {
$session = Session::requireLogin();
} else {
Json::dieWithReason("올바르지 않은 SessionMode: {$sessionMode}");
}
if ($sessionMode & BaseAPI::REQ_READ_ONLY) {
$session->setReadOnly();
}
}
$modifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
? new \DateTimeImmutable($_SERVER['HTTP_IF_MODIFIED_SINCE'], new \DateTimeZone("UTC"))
: null;
$reqEtags = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : null;
$result = $obj->launch($session, $modifiedSince, $reqEtags);
if (is_string($result)) {
Json::dieWithReason($result);
}
$cacheResult = $obj->tryCache();
if ($cacheResult !== null) {
/** @var \DateTimeInterface $lastModified */
[$lastModified, $etag] = $cacheResult;
if ($lastModified !== null) {
header("Last-Modified: " . gmdate("D, d M Y H:i:s", TimeUtil::DateTimeToSeconds($lastModified, true)) . " GMT");
}
if ($etag !== null) {
header("Etag: $etag");
}
if ($modifiedSince !== null && $lastModified !== null && TimeUtil::DateIntervalToSeconds($modifiedSince->diff($lastModified)) == 0) {
header("HTTP/1.1 304 Not Modified");
die();
}
if ($reqEtags !== null && $reqEtags === $etag) {
header("HTTP/1.1 304 Not Modified");
die();
}
}
if ($result === null) {
Json::die([
'result' => true,
'reason' => 'success'
], $cacheResult === null ? Json::NO_CACHE : 0);
}
Json::die($result, $cacheResult === null ? Json::NO_CACHE : 0);
} catch (\Exception $e) {
Json::dieWithReason($e->getMessage());
} catch (mixed $e) {
Json::dieWithReason($e);
}
+2 -2
View File
@@ -2345,7 +2345,7 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
$randSecond = Util::randRangeInt(0, 60 * $term - 1); $randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수 $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s'); return $baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
} }
function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null) function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
@@ -2360,5 +2360,5 @@ function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
$randSecond = Util::randRangeInt(0, 60 * $term - 1); $randSecond = Util::randRangeInt(0, 60 * $term - 1);
$randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수 $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s'); return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
} }
+25
View File
@@ -357,6 +357,31 @@ function buildNationCommandClass(?string $type, General $generalObj, array $env,
return new $class($generalObj, $env, $lastTurn, $arg); return new $class($generalObj, $env, $lastTurn, $arg);
} }
function getAPIExecutorClass($path){
static $basePath = __NAMESPACE__.'\\API\\';
if(is_string($path)){
}
else if(is_array($path)){
$path = join('\\', $path);
}
else{
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = ($basePath.$path);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass(string $type, array $args):\sammo\BaseAPI{
$class = getAPIExecutorClass($type);
return new $class($args);
}
function getWarUnitTriggerClass(string $type){ function getWarUnitTriggerClass(string $type){
static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\'; static $basePath = __NAMESPACE__.'\\WarUnitTrigger\\';
$classPath = ($basePath.$type); $classPath = ($basePath.$type);
+13 -3
View File
@@ -1150,15 +1150,24 @@ function checkEmperior()
LogHistory(); LogHistory();
} }
function resetInheritanceUser(int $userID, bool $isRebirth=false){ function resetInheritanceUser(int $userID, bool $isRebirth=false):float{
$rebirthDegraded = [ $rebirthDegraded = [
'dex'=>0.5, 'dex'=>0.5,
]; ];
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}"); $inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$totalPoint = 0; $totalPoint = 0;
foreach($inheritStor->getAll() as $key=>[$value,]){ $allPoints = $inheritStor->getAll();
if(key_exists($key, $rebirthDegraded)){ if(count($allPoints) == 0){
//비었으므로 리셋 안함
return 0;
}
if(count($allPoints) == 1 && key_exists('previous', $allPoints)){
//이미 리셋되었으므로 리셋 안함
return $allPoints['previous'];
}
foreach($allPoints as $key=>[$value,]){
if($isRebirth && key_exists($key, $rebirthDegraded)){
$value *= $rebirthDegraded[$key]; $value *= $rebirthDegraded[$key];
} }
$totalPoint += $value; $totalPoint += $value;
@@ -1166,6 +1175,7 @@ function resetInheritanceUser(int $userID, bool $isRebirth=false){
$totalPoint = Util::toInt($totalPoint); $totalPoint = Util::toInt($totalPoint);
$inheritStor->resetValues(); $inheritStor->resetValues();
$inheritStor->setValue('previous', [$totalPoint, null]); $inheritStor->setValue('previous', [$totalPoint, null]);
return $totalPoint;
} }
function updateMaxDomesticCritical(General $general, $score){ function updateMaxDomesticCritical(General $general, $score){
+114 -45
View File
@@ -1,9 +1,17 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
function dieMsg(string $msg)
{
$jmsg = Json::encode($msg);
echo "<html><head><style>html,body{background:black;}</style><script>alert({$jmsg});history.go(-1);</script></head><body></body></html>";
exit(1);
}
$v = new Validator($_POST); $v = new Validator($_POST);
$v $v
->rule('required', [ ->rule('required', [
@@ -28,12 +36,15 @@ $v
'strength', 'strength',
'intel' 'intel'
], GameConst::$defaultStatMax) ], GameConst::$defaultStatMax)
->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random'])); ->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random']))
->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar)
->rule('integer', 'inheritTurntime')
->rule('min', 'inheritTurntime', 0)
->rule('in', 'inheritCity', array_keys(CityConst::all()))
->rule('integerArray', 'inheritBonusStat');
if (!$v->validate()) { if (!$v->validate()) {
MessageBox($v->errorStr()); dieMsg($v->errorStr());
echo "<script>history.go(-1);</script>";
exit(1);
} }
$session = Session::requireLogin()->setReadOnly(); $session = Session::requireLogin()->setReadOnly();
@@ -52,6 +63,11 @@ $leadership = Util::getPost('leadership', 'int', 50);
$strength = Util::getPost('strength', 'int', 50); $strength = Util::getPost('strength', 'int', 50);
$intel = Util::getPost('intel', 'int', 50); $intel = Util::getPost('intel', 'int', 50);
$inheritSpecial = Util::getPost('inheritSpecial');
$inheritTurntime = Util::getPost('inheritTurntime', 'int');
$inheritCity = Util::getPost('inheritCity', 'int');
$inheritBonusStat = Util::getPost('inheritBonusStat', 'array_int');
$join = Util::getPost('join'); //쓸모 없음 $join = Util::getPost('join'); //쓸모 없음
$rootDB = RootDB::db(); $rootDB = RootDB::db();
@@ -59,9 +75,7 @@ $rootDB = RootDB::db();
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID); $member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID);
if (!$member) { if (!$member) {
MessageBox("잘못된 접근입니다!!!"); dieMsg("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
} }
$db = DB::db(); $db = DB::db();
@@ -74,62 +88,95 @@ $oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i',
$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name); $oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name);
if ($oldGeneral) { if ($oldGeneral) {
echo("<script> dieMsg("이미 등록하셨습니다!");
window.alert('이미 등록하셨습니다!')
history.go(-1)
</script>");
exit;
} }
if ($oldName) { if ($oldName) {
echo("<script> dieMsg("이미 있는 장수입니다. 다른 이름으로 등록해 주세요!");
window.alert('이미 있는 장수입니다. 다른 이름으로 등록해 주세요!')
history.go(-1)
</script>");
exit;
} }
if ($gameStor->maxgeneral <= $gencount) { if ($gameStor->maxgeneral <= $gencount) {
echo("<script> dieMsg("더이상 등록할 수 없습니다!");
window.alert('더이상 등록할 수 없습니다!')
history.go(-1)
</script>");
exit;
} }
if ($name == '') { if ($name == '') {
echo("<script> dieMsg("이름이 짧습니다. 다시 가입해주세요!");
window.alert('이름이 짧습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
} }
if (mb_strwidth($name) > 18) { if (mb_strwidth($name) > 18) {
echo("<script> dieMsg("이름이 유효하지 않습니다. 다시 가입해주세요!");
window.alert('이름이 유효하지 않습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
} }
if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) { if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) {
echo("<script> dieMsg("능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!");
window.alert('능력치가 ".GameConst::$defaultStatTotal."을 넘어섰습니다. 다시 가입해주세요!')
history.go(-1)
</script>");
exit;
} }
$genius = Util::randBool(0.01); if ($inheritBonusStat) {
if (count($inheritBonusStat) != 3) {
dieMsg("보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!");
}
$sum = array_sum($inheritBonusStat);
if ($sum < 3 || $sum > 5) {
dieMsg("보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!");
}
foreach ($inheritBonusStat as $stat) {
if ($stat < 0) {
dieMsg("보너스 능력치가 음수입니다. 다시 가입해주세요!");
}
}
}
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']);
$inheritTotalPoint = resetInheritanceUser($userID);
$inheritRequiredPoint = 0;
if ($inheritCity !== null) {
$inheritRequiredPoint += GameConst::$inheritBornCityPoint;
}
if ($inheritBonusStat !== null) {
$inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat;
}
if ($inheritSpecial !== null) {
$inheritRequiredPoint += GameConst::$inheritBornSpecialPoint;
}
if ($inheritTurntime !== null) {
$inheritRequiredPoint += GameConst::$inheritBornTurntimePoint;
}
if ($inheritTotalPoint < $inheritRequiredPoint) {
dieMsg("유산 포인트가 부족합니다. 다시 가입해주세요!");
}
if ($inheritSpecial !== null && $gameStor->genius == 0) {
dieMsg("이미 천재가 모두 나타났습니다. 다시 가입해주세요!");
}
if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) {
dieMsg("도시가 잘못 지정되었습니다. 다시 가입해주세요!");
}
if ($inheritSpecial) {
$genius = true;
} else {
// 현재 1% // 현재 1%
$genius = Util::randBool(0.01);
}
if ($genius && $gameStor->genius > 0) { if ($genius && $gameStor->genius > 0) {
$gameStor->genius = $gameStor->genius - 1; $gameStor->genius = $gameStor->genius - 1;
} else { } else {
$genius = false; $genius = false;
} }
if ($inheritCity !== null) {
$city = $inheritCity;
} else {
// 공백지에서만 태어나게 // 공백지에서만 태어나게
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1"); $city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1");
if (!$city) { if (!$city) {
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1"); $city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1");
} }
}
if ($inheritBonusStat) {
[$pleadership, $pstrength, $pintel] = $inheritBonusStat;
} else {
$pleadership = 0; $pleadership = 0;
$pstrength = 0; $pstrength = 0;
$pintel = 0; $pintel = 0;
@@ -146,18 +193,21 @@ foreach(Util::range(Util::randRangeInt(3, 5)) as $statIdx){
break; break;
} }
} }
}
$leadership = $leadership + $pleadership; $leadership = $leadership + $pleadership;
$strength = $strength + $pstrength; $strength = $strength + $pstrength;
$intel = $intel + $pintel; $intel = $intel + $pintel;
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']);
$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0); $relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0);
$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1)); $age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1));
// 아직 남았고 천재등록상태이면 특기 부여 // 아직 남았고 천재등록상태이면 특기 부여
if ($genius) { if ($genius) {
$specage2 = $age; $specage2 = $age;
if ($inheritSpecial) {
$special2 = $inheritSpecial;
} else {
$special2 = SpecialityHelper::pickSpecialWar([ $special2 = SpecialityHelper::pickSpecialWar([
'leadership' => $leadership, 'leadership' => $leadership,
'strength' => $strength, 'strength' => $strength,
@@ -168,6 +218,7 @@ if ($genius) {
'dex4' => 0, 'dex4' => 0,
'dex5' => 0 'dex5' => 0
]); ]);
}
} else { } else {
$specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age; $specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age;
$special2 = GameConst::$defaultSpecialWar; $special2 = GameConst::$defaultSpecialWar;
@@ -183,8 +234,7 @@ if ($admin['scenario'] >= 1000) {
if ($relYear < 3) { if ($relYear < 3) {
$experience = 0; $experience = 0;
} } else {
else{
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4'); $expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2); $targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField( $experience = $db->queryFirstField(
@@ -194,9 +244,17 @@ else{
$experience *= 0.8; $experience *= 0.8;
} }
if ($inheritTurntime === null) {
$inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60);
$inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
$turntime = cutTurn($admin['turntime'], $admin['turnterm']);
$turntime = TimeUtil::nowAddSeconds($inheritTurntime, true);
} else {
$turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
}
$now = date('Y-m-d H:i:s');
$now = TimeUtil::now(true);
if ($now >= $turntime) { if ($now >= $turntime) {
$turntime = addTurn($turntime, $admin['turnterm']); $turntime = addTurn($turntime, $admin['turnterm']);
} }
@@ -266,8 +324,6 @@ foreach(Util::range(GameConst::$maxTurn) as $turnIdx){
} }
$db->insert('general_turn', $turnRows); $db->insert('general_turn', $turnRows);
resetInheritanceUser($userID);
$rank_data = []; $rank_data = [];
foreach (array_keys(General::RANK_COLUMN) as $rankColumn) { foreach (array_keys(General::RANK_COLUMN) as $rankColumn) {
$rank_data[] = [ $rank_data[] = [
@@ -333,9 +389,22 @@ $rootDB->insert('member_log', [
]); ]);
?> ?>
<html>
<head>
<style>
html,
body {
background: black;
}
</style>
<script> <script>
window.alert('정상적으로 회원 가입되었습니다. 장수명 : <?= $name ?> \n위키와 팁/강좌 게시판을 꼭 읽어보세요!'); window.alert('정상적으로 회원 가입되었습니다. 장수명 : <?= $name ?> \n위키와 팁/강좌 게시판을 꼭 읽어보세요!');
location.replace('./');
</script> </script>
<script>location.replace('./');</script> </head>
<body>
</body>
</html>
+426
View File
@@ -0,0 +1,426 @@
<?php
namespace sammo\API\General;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\GameConst;
use sammo\GameUnitConst;
use sammo\General;
use sammo\JosaUtil;
use sammo\Json;
use sammo\KVStorage;
use sammo\RootDB;
use sammo\Session;
use sammo\SpecialityHelper;
use sammo\StringUtil;
use sammo\TimeUtil;
use sammo\Util;
use sammo\Validator;
use sammo\WebUtil;
use function sammo\addTurn;
use function sammo\cutTurn;
use function sammo\getGeneralSpecialWarName;
use function sammo\getRandTurn;
use function sammo\pushAdminLog;
use function sammo\resetInheritanceUser;
class Join extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
$v = new Validator($this->args);
$v
->rule('required', [
'name',
'leadership',
'strength',
'intel',
'pic',
'character',
])
->rule('integer', [
'leadership',
'strength',
'intel',
'inheritTurntime',
])
->rule('boolean', [
'pic'
])
->rule('stringWidthBetween', 'name', 1, 18)
->rule('min', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMin)
->rule('max', [
'leadership',
'strength',
'intel'
], GameConst::$defaultStatMax)
->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random']))
->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar)
->rule('min', 'inheritTurntime', 0)
->rule('in', 'inheritCity', array_keys(CityConst::all()))
->rule('integerArray', 'inheritBonusStat');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_LOGIN | static::REQ_READ_ONLY;
}
public function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag)
{
if($session === null){
throw "invalid session";
}
$userID = $session->userID;
$name = $this->args['name'];
$name = htmlspecialchars($name);
$name = StringUtil::removeSpecialCharacter($name);
$name = WebUtil::htmlPurify($name);
$name = StringUtil::textStrip($name);
$pic = $this->args['pic'];
$character = $this->args['character'];
$leadership = $this->args['leadership'];
$strength = $this->args['strength'];
$intel = $this->args['intel'];
$inheritSpecial = $this->args['inheritSpecial']??null;
$inheritTurntime =$this->args['inheritTurntime']??null;
$inheritCity = $this->args['inheritCity']??null;
$inheritBonusStat = $this->args['inheritBonusStat']??null;
$rootDB = RootDB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID);
if (!$member) {
return "잘못된 접근입니다!!!";
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'turnterm', 'turntime', 'genius', 'npcmode']);
########## 동일 정보 존재여부 확인. ##########
$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);
if ($oldGeneral) {
return "이미 등록하셨습니다!";
}
if ($oldName) {
return "이미 있는 장수입니다. 다른 이름으로 등록해 주세요!";
}
if ($gameStor->maxgeneral <= $gencount) {
return "더이상 등록할 수 없습니다!";
}
if ($name == '') {
return "이름이 짧습니다. 다시 가입해주세요!";
}
if (mb_strwidth($name) > 18) {
return "이름이 유효하지 않습니다. 다시 가입해주세요!";
}
if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) {
return "능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!";
}
if ($inheritBonusStat) {
if (count($inheritBonusStat) != 3) {
return "보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!";
}
$sum = array_sum($inheritBonusStat);
if ($sum < 3 || $sum > 5) {
return "보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!";
}
foreach ($inheritBonusStat as $stat) {
if ($stat < 0) {
return "보너스 능력치가 음수입니다. 다시 가입해주세요!";
}
}
}
$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']);
$inheritTotalPoint = resetInheritanceUser($userID);
$inheritRequiredPoint = 0;
if ($inheritCity !== null) {
$inheritRequiredPoint += GameConst::$inheritBornCityPoint;
}
if ($inheritBonusStat !== null) {
$inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat;
}
if ($inheritSpecial !== null) {
$inheritRequiredPoint += GameConst::$inheritBornSpecialPoint;
}
if ($inheritTurntime !== null) {
$inheritRequiredPoint += GameConst::$inheritBornTurntimePoint;
}
if ($inheritTotalPoint < $inheritRequiredPoint) {
return "유산 포인트가 부족합니다. 다시 가입해주세요!";
}
if ($inheritSpecial !== null && $gameStor->genius == 0) {
return "이미 천재가 모두 나타났습니다. 다시 가입해주세요!";
}
if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) {
return "도시가 잘못 지정되었습니다. 다시 가입해주세요!";
}
if ($inheritSpecial) {
$genius = true;
} else {
// 현재 1%
$genius = Util::randBool(0.01);
}
if ($genius && $gameStor->genius > 0) {
$gameStor->genius = $gameStor->genius - 1;
} else {
$genius = false;
}
if ($inheritCity !== null) {
$city = $inheritCity;
} else {
// 공백지에서만 태어나게
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1");
if (!$city) {
$city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1");
}
}
if ($inheritBonusStat) {
[$pleadership, $pstrength, $pintel] = $inheritBonusStat;
} else {
$pleadership = 0;
$pstrength = 0;
$pintel = 0;
foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) {
switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) {
case 0:
$pleadership++;
break;
case 1:
$pstrength++;
break;
case 2:
$pintel++;
break;
}
}
}
$leadership = $leadership + $pleadership;
$strength = $strength + $pstrength;
$intel = $intel + $pintel;
$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0);
$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1));
// 아직 남았고 천재등록상태이면 특기 부여
if ($genius) {
$specage2 = $age;
if ($inheritSpecial) {
$special2 = $inheritSpecial;
} else {
$special2 = SpecialityHelper::pickSpecialWar([
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
'dex1' => 0,
'dex2' => 0,
'dex3' => 0,
'dex4' => 0,
'dex5' => 0
]);
}
} else {
$specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age;
$special2 = GameConst::$defaultSpecialWar;
}
//내특
$specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 12 - $relYear / 2), 3) + $age;
$special = GameConst::$defaultSpecialDomestic;
if ($admin['scenario'] >= 1000) {
$specage2 = $age + 3;
$specage = $age + 3;
}
if ($relYear < 3) {
$experience = 0;
} else {
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField(
'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1',
$targetGenOrder - 1
);
$experience *= 0.8;
}
if ($inheritTurntime === null) {
$inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60);
$inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
$turntime = cutTurn($admin['turntime'], $admin['turnterm']);
$turntime = TimeUtil::nowAddSeconds($inheritTurntime, true);
} else {
$turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
}
$now = TimeUtil::now(true);
if ($now >= $turntime) {
$turntime = addTurn($turntime, $admin['turnterm']);
}
//특회 전콘
if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) {
$face = $member['picture'];
$imgsvr = $member['imgsvr'];
} else {
$face = "default.jpg";
$imgsvr = 0;
}
//성격 랜덤시
if (!in_array($character, GameConst::$availablePersonality)) {
$character = Util::choiceRandom(GameConst::$availablePersonality);
}
//상성 랜덤
$affinity = rand() % 150 + 1;
########## 회원정보 테이블에 입력값을 등록한다. ##########
$db->insert('general', [
'owner' => $userID,
'name' => $name,
'owner_name' => $member['name'],
'picture' => $face,
'imgsvr' => $imgsvr,
'nation' => 0,
'city' => $city,
'troop' => 0,
'affinity' => $affinity,
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
'experience' => $experience,
'dedication' => 0,
'gold' => GameConst::$defaultGold,
'rice' => GameConst::$defaultRice,
'crew' => 0,
'train' => 0,
'atmos' => 0,
'officer_level' => 0,
'turntime' => $turntime,
'killturn' => 6,
'lastconnect' => $now,
'lastrefresh' => $now,
'crewtype' => GameUnitConst::DEFAULT_CREWTYPE,
'makelimit' => 0,
'age' => $age,
'startage' => $age,
'personal' => $character,
'specage' => $specage,
'special' => $special,
'specage2' => $specage2,
'special2' => $special2
]);
$generalID = $db->insertId();
$turnRows = [];
foreach (Util::range(GameConst::$maxTurn) as $turnIdx) {
$turnRows[] = [
'general_id' => $generalID,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
$db->insert('general_turn', $turnRows);
$rank_data = [];
foreach (array_keys(General::RANK_COLUMN) as $rankColumn) {
$rank_data[] = [
'general_id' => $generalID,
'nation_id' => 0,
'type' => $rankColumn,
'value' => 0
];
}
$db->insert('rank_data', $rank_data);
$db->insert('betting', [
'general_id' => $generalID,
]);
$cityname = CityConst::byID($city)->name;
$me = [
'no' => $generalID
];
$log = [];
$mylog = [];
$logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month);
$josaRa = JosaUtil::pick($name, '라');
$speicalText = getGeneralSpecialWarName($special2);
if ($genius) {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 기재가 천하에 이름을 알립니다.");
$logger->pushGlobalActionLog("<C>{$speicalText}</> 특기를 가진 <C>천재</>의 등장으로 온 천하가 떠들썩합니다.");
$logger->pushGlobalHistoryLog("<L><b>【천재】</b></><G><b>{$cityname}</b></>에 천재가 등장했습니다.");
} else {
$logger->pushGlobalActionLog("<G><b>{$cityname}</b></>에서 <Y>{$name}</>{$josaRa}는 호걸이 천하에 이름을 알립니다.");
}
$logger->pushGeneralHistoryLog("<Y>{$name}</>, <G>{$cityname}</>에서 큰 뜻을 품다.");
$logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("처음 하시는 경우에는 <D>도움말</>을 참고하시고,", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("통솔 <C>$pleadership</> 무력 <C>$pstrength</> 지력 <C>$pintel</> 의 보너스를 받으셨습니다.", ActionLogger::PLAIN);
$logger->pushGeneralActionLog("연령은 <C>$age</>세로 시작합니다.", ActionLogger::PLAIN);
if ($genius) {
$logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 <C>{$speicalText}</> 특기를 가지게 됩니다!", ActionLogger::PLAIN);
$logger->pushGeneralHistoryLog("<C>{$speicalText}</> 특기를 가진 천재로 탄생.");
}
$logger->flush();
pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}" . getenv("REMOTE_ADDR")]);
$rootDB->insert('member_log', [
'member_no' => $userID,
'date' => TimeUtil::now(),
'action_type' => 'make_general',
'action' => Json::encode([
'server' => DB::prefix(),
'type' => 'general',
'generalID' => $generalID,
'generalName' => $name
])
]);
return null;
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace sammo;
abstract class BaseAPI
{
const NO_SESSION = 0;
const REQ_LOGIN = 1;
const REQ_GAME_LOGIN = 2;
const REQ_READ_ONLY = 4;
protected array $args;
public function __construct(array $args)
{
$this->args = $args;
}
abstract public function getRequiredSessionMode(): int;
abstract function validateArgs(): ?string;
/** @return null|string|array */
abstract function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag);
public function tryCache():?string{
return null;
}
}
+6
View File
@@ -1,4 +1,5 @@
<?php <?php
namespace sammo; namespace sammo;
class GameConstBase class GameConstBase
@@ -189,6 +190,11 @@ class GameConstBase
'che_은둔', 'None' 'che_은둔', 'None'
]; ];
public static $inheritBornSpecialPoint = 12000;
public static $inheritBornTurntimePoint = 3000;
public static $inheritBornCityPoint = 1000;
public static $inheritBornMaxBonusStat = 1000;
public static $allItems = [ public static $allItems = [
'horse' => [ 'horse' => [
'che_명마_01_노기' => 0, 'che_명마_02_조랑' => 0, 'che_명마_03_노새' => 0, 'che_명마_01_노기' => 0, 'che_명마_02_조랑' => 0, 'che_명마_03_노새' => 0,
+39 -31
View File
@@ -1,7 +1,9 @@
<?php <?php
namespace sammo; namespace sammo;
use \Symfony\Component\Lock; use \Symfony\Component\Lock;
class TurnExecutionHelper class TurnExecutionHelper
{ {
/** @var General*/ /** @var General*/
@@ -17,16 +19,19 @@ class TurnExecutionHelper
$this->applyDB(); $this->applyDB();
} }
public function applyDB(){ public function applyDB()
{
$db = DB::db(); $db = DB::db();
$this->generalObj->applyDB($db); $this->generalObj->applyDB($db);
} }
public function getGeneral():General{ public function getGeneral(): General
{
return $this->generalObj; return $this->generalObj;
} }
public function preprocessCommand(array $env){ public function preprocessCommand(array $env)
{
$general = $this->getGeneral(); $general = $this->getGeneral();
$caller = $general->getPreTurnExecuteTriggerList($general); $caller = $general->getPreTurnExecuteTriggerList($general);
$caller->merge(new GeneralTriggerCaller( $caller->merge(new GeneralTriggerCaller(
@@ -37,7 +42,8 @@ class TurnExecutionHelper
$caller->fire($env); $caller->fire($env);
} }
public function processBlocked():bool{ public function processBlocked(): bool
{
$general = $this->getGeneral(); $general = $this->getGeneral();
$blocked = $general->getVar('block'); $blocked = $general->getVar('block');
@@ -50,12 +56,10 @@ class TurnExecutionHelper
if ($blocked == 2) { if ($blocked == 2) {
$general->increaseVarWithLimit('killturn', -1, 0); $general->increaseVarWithLimit('killturn', -1, 0);
$logger->pushGeneralActionLog("현재 멀티, 또는 비매너로 인한<R>블럭</> 대상자입니다. <1>$date</>"); $logger->pushGeneralActionLog("현재 멀티, 또는 비매너로 인한<R>블럭</> 대상자입니다. <1>$date</>");
} } else if ($blocked == 3) {
else if($blocked == 3){
$general->increaseVarWithLimit('killturn', -1, 0); $general->increaseVarWithLimit('killturn', -1, 0);
$logger->pushGeneralActionLog("현재 악성유저로 분류되어 <R>블럭</> 대상자입니다. <1>$date</>"); $logger->pushGeneralActionLog("현재 악성유저로 분류되어 <R>블럭</> 대상자입니다. <1>$date</>");
} } else {
else{
//Hmm? //Hmm?
return false; return false;
} }
@@ -63,7 +67,8 @@ class TurnExecutionHelper
return true; return true;
} }
public function processNationCommand(Command\NationCommand $commandObj):LastTurn{ public function processNationCommand(Command\NationCommand $commandObj): LastTurn
{
$general = $this->getGeneral(); $general = $this->getGeneral();
while (true) { while (true) {
@@ -101,7 +106,8 @@ class TurnExecutionHelper
return $commandObj->getResultTurn(); return $commandObj->getResultTurn();
} }
public function processCommand(Command\GeneralCommand $commandObj, bool $autorunMode){ public function processCommand(Command\GeneralCommand $commandObj, bool $autorunMode)
{
$general = $this->getGeneral(); $general = $this->getGeneral();
@@ -146,24 +152,21 @@ class TurnExecutionHelper
if ($general->getNPCType() >= 2) { if ($general->getNPCType() >= 2) {
$general->increaseVarWithLimit('killturn', -1); $general->increaseVarWithLimit('killturn', -1);
} } else if ($general->getVar('killturn') > $killTurn) {
else if($general->getVar('killturn') > $killTurn){
$general->increaseVarWithLimit('killturn', -1); $general->increaseVarWithLimit('killturn', -1);
} } else if ($autorunMode) {
else if($autorunMode){
$general->increaseVarWithLimit('killturn', -1); $general->increaseVarWithLimit('killturn', -1);
} } else if ($commandClassName == '휴식') {
else if($commandClassName == '휴식'){
$general->increaseVarWithLimit('killturn', -1); $general->increaseVarWithLimit('killturn', -1);
} } else {
else{
$general->setVar('killturn', $killTurn); $general->setVar('killturn', $killTurn);
} }
return $commandObj->getResultTurn(); return $commandObj->getResultTurn();
} }
function updateTurnTime(){ function updateTurnTime()
{
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
@@ -189,8 +192,7 @@ class TurnExecutionHelper
$general->setVar('owner', 0); $general->setVar('owner', 0);
$general->setVar('defence_train', 80); $general->setVar('defence_train', 80);
$general->setVar('owner_name', null); $general->setVar('owner_name', null);
} } else {
else{
$general->applyDB($db); $general->applyDB($db);
storeOldGeneral($generalID, $gameStor->year, $gameStor->month); storeOldGeneral($generalID, $gameStor->year, $gameStor->month);
$general->kill($db); $general->kill($db);
@@ -210,11 +212,11 @@ class TurnExecutionHelper
$turntime = addTurn($general->getTurnTime(), $gameStor->turnterm); $turntime = addTurn($general->getTurnTime(), $gameStor->turnterm);
$general->setVar('turntime', $turntime); $general->setVar('turntime', $turntime);
} }
static public function executeGeneralCommandUntil(string $date, \DateTimeInterface $limitActionTime, int $year, int $month){ static public function executeGeneralCommandUntil(string $date, \DateTimeInterface $limitActionTime, int $year, int $month)
{
$db = DB::db(); $db = DB::db();
$generalsTodo = $db->query( $generalsTodo = $db->query(
'SELECT no,name,turntime,killturn,block,npc,deadyear FROM general WHERE turntime < %s ORDER BY turntime ASC, `no` ASC', 'SELECT no,name,turntime,killturn,block,npc,deadyear FROM general WHERE turntime < %s ORDER BY turntime ASC, `no` ASC',
@@ -260,7 +262,6 @@ class TurnExecutionHelper
$general->increaseInheritancePoint('lived_month', 1); $general->increaseInheritancePoint('lived_month', 1);
$turnObj->preprocessCommand($env); $turnObj->preprocessCommand($env);
$generalCommandObj = $general->getReservedTurn(0, $env);
if ($general->getNPCType() >= 2 || ($autorun_user['limit_minutes'] ?? false)) { if ($general->getNPCType() >= 2 || ($autorun_user['limit_minutes'] ?? false)) {
$ai = new GeneralAI($turnObj->getGeneral()); $ai = new GeneralAI($turnObj->getGeneral());
@@ -278,8 +279,11 @@ class TurnExecutionHelper
$nationCommandObj $nationCommandObj
); );
$nationStor->setValue($lastNationTurnKey, $resultNationTurn->toRaw()); $nationStor->setValue($lastNationTurnKey, $resultNationTurn->toRaw());
$general->setRawCity(null);
} }
$generalCommandObj = $general->getReservedTurn(0, $env);
if ($ai) { if ($ai) {
$newGeneralCommandObj = $ai->chooseGeneralTurn($generalCommandObj); // npc AI 처리 $newGeneralCommandObj = $ai->chooseGeneralTurn($generalCommandObj); // npc AI 처리
if ($generalCommandObj !== $newGeneralCommandObj) { if ($generalCommandObj !== $newGeneralCommandObj) {
@@ -300,14 +304,13 @@ class TurnExecutionHelper
$turnObj->updateTurnTime(); $turnObj->updateTurnTime();
$turnObj->applyDB(); $turnObj->applyDB();
} }
return [false, $currentTurn]; return [false, $currentTurn];
} }
static public function executeAllCommand(){ static public function executeAllCommand()
{
//if(!timeover()) { return; } //if(!timeover()) { return; }
$db = DB::db(); $db = DB::db();
@@ -344,8 +347,7 @@ class TurnExecutionHelper
$maxActionTime = Util::toInt(ini_get('max_execution_time')); $maxActionTime = Util::toInt(ini_get('max_execution_time'));
if ($maxActionTime == 0) { if ($maxActionTime == 0) {
$maxActionTime = 60; $maxActionTime = 60;
} } else {
else {
$maxActionTime = max($maxActionTime * 2 / 3, $maxActionTime - 10); $maxActionTime = max($maxActionTime * 2 / 3, $maxActionTime - 10);
} }
@@ -356,7 +358,10 @@ class TurnExecutionHelper
while ($nextTurn <= $date) { while ($nextTurn <= $date) {
[$executionOver, $currentTurn] = static::executeGeneralCommandUntil( [$executionOver, $currentTurn] = static::executeGeneralCommandUntil(
$nextTurn, $limitActionTime, $gameStor->year, $gameStor->month $nextTurn,
$limitActionTime,
$gameStor->year,
$gameStor->month
); );
// 트래픽 업데이트 // 트래픽 업데이트
@@ -440,7 +445,10 @@ class TurnExecutionHelper
// 현재시간의 월턴시간 이후 분단위 장수 처리 // 현재시간의 월턴시간 이후 분단위 장수 처리
[$executionOver, $currentTurn] = static::executeGeneralCommandUntil( [$executionOver, $currentTurn] = static::executeGeneralCommandUntil(
$date, $limitActionTime, $gameStor->year, $gameStor->month $date,
$limitActionTime,
$gameStor->year,
$gameStor->month
); );
if ($currentTurn !== null) { if ($currentTurn !== null) {
+8
View File
@@ -53,4 +53,12 @@ class Json
} }
die(Json::encode($value, $flag)); die(Json::encode($value, $flag));
} }
/** @return never */
public static function dieWithReason(string $reason){
static::die([
'result'=>false,
'reason'=>$reason
]);
}
} }
+17 -10
View File
@@ -1,6 +1,9 @@
<?php <?php
namespace sammo; namespace sammo;
use phpDocumentor\Reflection\Types\Boolean;
class TimeUtil class TimeUtil
{ {
@@ -131,7 +134,8 @@ class TimeUtil
return $obj->format('Y-m-d H:i:s.u'); return $obj->format('Y-m-d H:i:s.u');
} }
public static function secondsToDateTime(float $fullSeconds, bool $isDateTimeImmutable=false): \DateTimeInterface{ public static function secondsToDateTime(float $fullSeconds, bool $isDateTimeImmutable = false, bool $isUTC = false): \DateTimeInterface
{
$seconds = floor($fullSeconds); $seconds = floor($fullSeconds);
$fraction = $fullSeconds - $seconds; $fraction = $fullSeconds - $seconds;
@@ -140,32 +144,34 @@ class TimeUtil
$interval->f = $fraction; $interval->f = $fraction;
if ($isDateTimeImmutable) { if ($isDateTimeImmutable) {
$dateTime = new \DateTimeImmutable("@0"); $dateTime = new \DateTimeImmutable("@0", $isUTC ? new \DateTimeZone("UTC") : null);
return $dateTime->add($interval); return $dateTime->add($interval);
} }
$dateTime = new \DateTime("@0"); $dateTime = new \DateTime("@0", $isUTC ? new \DateTimeZone("UTC") : null);
$dateTime->add($interval); $dateTime->add($interval);
return $dateTime; return $dateTime;
} }
public static function secondsToDateInterval(float $fullSeconds): \DateInterval{ public static function secondsToDateInterval(float $fullSeconds): \DateInterval
{
$d0 = new \DateTime("@0"); $d0 = new \DateTime("@0");
return $d0->diff(static::secondsToDateTime($fullSeconds, true)); return $d0->diff(static::secondsToDateTime($fullSeconds, true));
} }
public static function DateTimeToSeconds(\DateTimeInterface $dateTime): float{ public static function DateTimeToSeconds(\DateTimeInterface $dateTime, bool $isUTC = false): float
$d0 = new \DateTimeImmutable("@0"); {
$d0 = new \DateTimeImmutable("@0", $isUTC ? new \DateTimeZone("UTC") : null);
return static::DateIntervalToSeconds($d0->diff($dateTime)); return static::DateIntervalToSeconds($d0->diff($dateTime));
} }
public static function DateIntervalToSeconds(\DateInterval $interval): float{ public static function DateIntervalToSeconds(\DateInterval $interval): float
{
if ($interval->days !== FALSE) { if ($interval->days !== FALSE) {
$days = $interval->days; $days = $interval->days;
} } else {
else{
if ($interval->y != 0) { if ($interval->y != 0) {
throw new \InvalidArgumentException('Year argument conversion is not supported'); throw new \InvalidArgumentException('Year argument conversion is not supported');
} }
@@ -186,7 +192,8 @@ class TimeUtil
* $baseYear, $baseMonth 부터 $afterMonth 개월 이내인지. $afterMonth 포함. * $baseYear, $baseMonth 부터 $afterMonth 개월 이내인지. $afterMonth 포함.
* *
*/ */
public static function IsRangeMonth(int $baseYear, int $baseMonth, int $afterMonth, int $askYear, int $askMonth):bool{ public static function IsRangeMonth(int $baseYear, int $baseMonth, int $afterMonth, int $askYear, int $askMonth): bool
{
if ($baseMonth < 1 || $baseMonth > 12) { if ($baseMonth < 1 || $baseMonth > 12) {
throw new \InvalidArgumentException('개월이 올바르지 않음'); throw new \InvalidArgumentException('개월이 올바르지 않음');
} }