fix: complete logical clock wall-time isolation
This commit is contained in:
@@ -10,7 +10,6 @@ use sammo\GameConst;
|
||||
use sammo\GameClock;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Util;
|
||||
|
||||
use function sammo\cutTurn;
|
||||
@@ -33,6 +32,7 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
|
||||
$commandList = [];
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$clock = GameClock::fromStorage($gameStor);
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$invalidTurnList = 0;
|
||||
@@ -85,11 +85,12 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
return [
|
||||
'result' => true,
|
||||
'turnTimeTick' => Util::toInt($turnTime),
|
||||
'turnTime' => GameClock::fromStorage($gameStor)->formatTick(Util::toInt($turnTime)),
|
||||
'turnTime' => $clock->formatTick(Util::toInt($turnTime)),
|
||||
'turnTerm' => $turnTerm,
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'date' => GameClock::fromStorage($gameStor)->formatTick(GameClock::fromStorage($gameStor)->nowTick(), true),
|
||||
'date' => $clock->formatTick($clock->nowTick(), true),
|
||||
'clockMode' => $clock->getMode(),
|
||||
'turn' => $commandList,
|
||||
'autorun_limit' => $generalAux['autorun_limit'] ?? null,
|
||||
];
|
||||
|
||||
@@ -21,7 +21,6 @@ use sammo\LastTurn;
|
||||
use sammo\Validator;
|
||||
|
||||
use sammo\Session;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Util;
|
||||
|
||||
use function sammo\buildNationCommandClass;
|
||||
@@ -185,8 +184,9 @@ class GetFrontInfo extends \sammo\BaseAPI
|
||||
$lastVote = null;
|
||||
if ($lastVoteID) {
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
$lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
|
||||
if ($lastVote->endDate && $lastVote->endDate < TimeUtil::now()) {
|
||||
$rawLastVote = VoteInfo::normalizeGameStorage($voteStor->getValue("vote_{$lastVoteID}"), $clock);
|
||||
$lastVote = VoteInfo::fromGameStorage($rawLastVote, $clock);
|
||||
if ($rawLastVote['endTick'] !== null && $rawLastVote['endTick'] < $clock->nowTick()) {
|
||||
$lastVote = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ use sammo\Enums\RankColumn;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\UserLogger;
|
||||
|
||||
class BuyRandomUnique extends \sammo\BaseAPI
|
||||
@@ -56,7 +55,7 @@ class BuyRandomUnique extends \sammo\BaseAPI
|
||||
$userLogger->push("{$reqAmount} 포인트로 랜덤 유니크 구입", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$general->setAuxVar('inheritRandomUnique', TimeUtil::now());
|
||||
$general->setAuxVar('inheritRandomUnique', true);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $reqAmount, null]);
|
||||
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $reqAmount);
|
||||
$general->applyDB($db);
|
||||
|
||||
@@ -116,7 +116,7 @@ class CheckOwner extends \sammo\BaseAPI
|
||||
$src,
|
||||
$dest,
|
||||
"{$destGeneralName}의 소유자는 {$destGeneralOwnerName} 입니다.",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
@@ -142,7 +142,7 @@ class CheckOwner extends \sammo\BaseAPI
|
||||
$src,
|
||||
$dest,
|
||||
"소유자명이 누군가에 의해 확인되었습니다.",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ class SendMessage extends \sammo\BaseAPI
|
||||
|
||||
private function genPublicMessage(MessageTarget $src, string $text): Message
|
||||
{
|
||||
$now = new \DateTime();
|
||||
$now = Message::gameNow();
|
||||
$unlimited = new \DateTime('9999-12-31');
|
||||
|
||||
$msg = new Message(
|
||||
@@ -62,7 +62,7 @@ class SendMessage extends \sammo\BaseAPI
|
||||
|
||||
private function genNationalMessage(MessageTarget $src, string $text): Message
|
||||
{
|
||||
$now = new \DateTime();
|
||||
$now = Message::gameNow();
|
||||
$unlimited = new \DateTime('9999-12-31');
|
||||
|
||||
$dest = new MessageTarget(0, '', $src->nationID, $src->nationName, $src->color);
|
||||
@@ -82,7 +82,7 @@ class SendMessage extends \sammo\BaseAPI
|
||||
|
||||
private function genDiplomacyMessage(MessageTarget $src, int $destNationID, string $text): Message|string
|
||||
{
|
||||
$now = new \DateTime();
|
||||
$now = Message::gameNow();
|
||||
$unlimited = new \DateTime('9999-12-31');
|
||||
|
||||
$destNation = getNationStaticInfo($destNationID);
|
||||
@@ -107,7 +107,7 @@ class SendMessage extends \sammo\BaseAPI
|
||||
|
||||
private function genPrivateMessage(MessageTarget $src, int $destGeneralID, int $permission, string $text): Message|string
|
||||
{
|
||||
$now = new \DateTime();
|
||||
$now = Message::gameNow();
|
||||
$unlimited = new \DateTime('9999-12-31');
|
||||
|
||||
$db = DB::db();
|
||||
|
||||
@@ -6,8 +6,8 @@ use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\GameClock;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Validator;
|
||||
use sammo\WebUtil;
|
||||
|
||||
@@ -51,8 +51,9 @@ class SetNotice extends \sammo\BaseAPI
|
||||
$nationID = $me['nation'];
|
||||
|
||||
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
|
||||
$gameNow = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))->formatNow();
|
||||
$nationStor->nationNotice = [
|
||||
'date'=>TimeUtil::now(),
|
||||
'date'=>$gameNow,
|
||||
'msg'=>WebUtil::htmlPurify($msg),
|
||||
'author'=>$me['name'],
|
||||
'authorID'=>$me['no'],
|
||||
|
||||
@@ -12,7 +12,6 @@ use sammo\GameClock;
|
||||
use sammo\General;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Util;
|
||||
|
||||
use function sammo\checkLimit;
|
||||
@@ -40,6 +39,7 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
increaseRefresh("사령부", 1);
|
||||
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$clock = GameClock::fromStorage($gameStor);
|
||||
$userID = $session->userID;
|
||||
|
||||
$me = $db->queryFirstRow(
|
||||
@@ -158,7 +158,8 @@ class GetReservedCommand extends \sammo\BaseAPI
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'turnTerm' => $turnTerm,
|
||||
'date' => TimeUtil::now(true),
|
||||
'date' => $clock->formatTick($clock->nowTick(), true),
|
||||
'clockMode' => $clock->getMode(),
|
||||
'chiefList' => $nationChiefList,
|
||||
'troopList' => $troopList,
|
||||
'isChief' => ($me['officer_level'] > 4),
|
||||
|
||||
@@ -10,8 +10,9 @@ use sammo\Enums\GeneralLiteQueryMode;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\General;
|
||||
use sammo\GeneralLite;
|
||||
use sammo\GameClock;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Session;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Validator;
|
||||
|
||||
class AddComment extends \sammo\BaseAPI
|
||||
@@ -47,7 +48,8 @@ class AddComment extends \sammo\BaseAPI
|
||||
$generalName = $general->getName();
|
||||
$nationID = $general->getNationID();
|
||||
$nationName = $general->getStaticNation()['name'];
|
||||
$date = TimeUtil::now();
|
||||
$db = DB::db();
|
||||
$date = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))->formatNow();
|
||||
|
||||
|
||||
$comment = new VoteComment(
|
||||
@@ -61,7 +63,6 @@ class AddComment extends \sammo\BaseAPI
|
||||
date: $date
|
||||
);
|
||||
|
||||
$db = DB::db();
|
||||
$db->insert('vote_comment', $comment->toArray());
|
||||
|
||||
return null;
|
||||
|
||||
@@ -8,6 +8,7 @@ use sammo\DB;
|
||||
use sammo\DTO\VoteComment;
|
||||
use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\GameClock;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Validator;
|
||||
@@ -35,13 +36,16 @@ class GetVoteDetail extends \sammo\BaseAPI
|
||||
{
|
||||
$voteID = $this->args['voteID'];
|
||||
$db = DB::db();
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
$rawVote = $voteStor->getValue("vote_{$voteID}");
|
||||
if (!$rawVote) {
|
||||
return '설문조사가 없습니다.';
|
||||
}
|
||||
$voteInfo = VoteInfo::fromArray($rawVote);
|
||||
$rawVote = VoteInfo::normalizeGameStorage($rawVote, $clock);
|
||||
$voteInfo = VoteInfo::fromGameStorage($rawVote, $clock);
|
||||
$isOpen = $rawVote['endTick'] === null || $rawVote['endTick'] >= $clock->nowTick();
|
||||
|
||||
|
||||
$votes = array_map(fn ($arr) => [Json::decode($arr[0]), $arr[1]], $db->queryAllLists(
|
||||
@@ -70,6 +74,7 @@ class GetVoteDetail extends \sammo\BaseAPI
|
||||
'comments' => $comments,
|
||||
'myVote' => $myVote,
|
||||
'userCnt' => $userCnt,
|
||||
'isOpen' => $isOpen,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\GameClock;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Session;
|
||||
|
||||
@@ -25,16 +26,17 @@ class GetVoteList extends \sammo\BaseAPI
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||
{
|
||||
$db = DB::db();
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
|
||||
$votes = [];
|
||||
foreach($voteStor->getAll() as $voteKey => $rawVote){
|
||||
if(!str_starts_with($voteKey, 'vote_')){
|
||||
if(preg_match('/^vote_(\d+)$/D', $voteKey, $matches) !== 1){
|
||||
continue;
|
||||
}
|
||||
$voteID = (int)substr($voteKey, 5);
|
||||
$votes[$voteID] = VoteInfo::fromArray($rawVote);
|
||||
$voteID = (int)$matches[1];
|
||||
$votes[$voteID] = VoteInfo::fromGameStorage($rawVote, $clock);
|
||||
}
|
||||
|
||||
return [
|
||||
|
||||
@@ -9,7 +9,7 @@ use sammo\Enums\APIRecoveryType;
|
||||
use sammo\KVStorage;
|
||||
use sammo\RootDB;
|
||||
use sammo\Session;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\GameClock;
|
||||
use sammo\Util;
|
||||
use sammo\Validator;
|
||||
|
||||
@@ -37,7 +37,7 @@ class NewVote extends \sammo\BaseAPI
|
||||
return null;
|
||||
}
|
||||
|
||||
function closeOldVote(int $voteID, KVStorage $voteStor)
|
||||
function closeOldVote(int $voteID, KVStorage $voteStor, GameClock $clock)
|
||||
{
|
||||
$db = DB::db();
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
@@ -45,13 +45,14 @@ class NewVote extends \sammo\BaseAPI
|
||||
if (!$rawLastVoteInfo) {
|
||||
return;
|
||||
}
|
||||
$lastVoteInfo = VoteInfo::fromArray($rawLastVoteInfo);
|
||||
if ($lastVoteInfo->endDate) {
|
||||
$rawLastVoteInfo = VoteInfo::normalizeGameStorage($rawLastVoteInfo, $clock);
|
||||
if ($rawLastVoteInfo['endTick'] !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lastVoteInfo->endDate = TimeUtil::now();
|
||||
$voteStor->setValue("vote_{$voteID}", $lastVoteInfo->toArray());
|
||||
$rawLastVoteInfo['endTick'] = $clock->nowTick();
|
||||
$rawLastVoteInfo['endDate'] = $clock->formatTick($rawLastVoteInfo['endTick']);
|
||||
$voteStor->setValue("vote_{$voteID}", $rawLastVoteInfo);
|
||||
}
|
||||
|
||||
function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
|
||||
@@ -71,7 +72,11 @@ class NewVote extends \sammo\BaseAPI
|
||||
$multipleOptions = 0;
|
||||
}
|
||||
|
||||
$now = TimeUtil::now();
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$clock = GameClock::fromStorage($gameStor);
|
||||
$nowTick = $clock->nowTick();
|
||||
$now = $clock->formatTick($nowTick);
|
||||
/** @var ?string */
|
||||
$endDate = $this->args['endDate'] ?? null;
|
||||
/** @var string[] */
|
||||
@@ -83,9 +88,9 @@ class NewVote extends \sammo\BaseAPI
|
||||
|
||||
if($endDate !== null){
|
||||
try{
|
||||
$oNow = new \DateTimeImmutable($now);
|
||||
$oEndDate = new \DateTimeImmutable($endDate);
|
||||
if($oEndDate < $oNow){
|
||||
$endTick = $clock->dateTimeToTick($oEndDate);
|
||||
if($endTick < $nowTick){
|
||||
return '종료일이 이미 지났습니다.';
|
||||
}
|
||||
}
|
||||
@@ -96,17 +101,13 @@ class NewVote extends \sammo\BaseAPI
|
||||
|
||||
$userName = $session->userName;
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
|
||||
$lastVote = $gameStor->getValue('lastVote') ?? 0;
|
||||
$voteID = $lastVote + 1;
|
||||
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
|
||||
if (!($this->args['keepOldVote'] ?? false)) {
|
||||
$this->closeOldVote($lastVote, $voteStor);
|
||||
$this->closeOldVote($lastVote, $voteStor, $clock);
|
||||
}
|
||||
|
||||
$multipleOptions = Util::valueFit($multipleOptions, 0, count($options));
|
||||
@@ -122,7 +123,10 @@ class NewVote extends \sammo\BaseAPI
|
||||
options: $options,
|
||||
);
|
||||
|
||||
$voteStor->setValue("vote_{$voteID}", $voteInfo->toArray());
|
||||
$voteStor->setValue("vote_{$voteID}", $voteInfo->toArray() + [
|
||||
'startTick' => $nowTick,
|
||||
'endTick' => $endDate === null ? null : $clock->dateTimeToTick(new \DateTimeImmutable($endDate)),
|
||||
]);
|
||||
$gameStor->setValue('lastVote', $voteID);
|
||||
|
||||
$db->update('general', [
|
||||
|
||||
@@ -8,6 +8,7 @@ use sammo\DTO\VoteInfo;
|
||||
use sammo\Enums\APIRecoveryType;
|
||||
use sammo\Enums\GeneralQueryMode;
|
||||
use sammo\General;
|
||||
use sammo\GameClock;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\LiteHashDRBG;
|
||||
@@ -54,15 +55,17 @@ class Vote extends \sammo\BaseAPI
|
||||
return '선택한 항목이 없습니다.';
|
||||
}
|
||||
$db = DB::db();
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||
$voteStor = KVStorage::getStorage($db, 'vote');
|
||||
|
||||
$rawVoteInfo = $voteStor->getValue("vote_{$voteID}");
|
||||
if (!$rawVoteInfo) {
|
||||
return '설문조사가 없습니다.';
|
||||
}
|
||||
$voteInfo = VoteInfo::fromArray($rawVoteInfo);
|
||||
$rawVoteInfo = VoteInfo::normalizeGameStorage($rawVoteInfo, $clock);
|
||||
$voteInfo = VoteInfo::fromGameStorage($rawVoteInfo, $clock);
|
||||
|
||||
if ($voteInfo->endDate && $voteInfo->endDate < new \DateTimeImmutable()) {
|
||||
if ($rawVoteInfo['endTick'] !== null && $rawVoteInfo['endTick'] < $clock->nowTick()) {
|
||||
return '설문조사가 종료되었습니다.';
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ class che_몰수 extends Command\NationCommand
|
||||
$src,
|
||||
$src,
|
||||
$text,
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
|
||||
@@ -198,8 +198,9 @@ class che_불가침제의 extends Command\NationCommand
|
||||
$destNation['color']
|
||||
);
|
||||
|
||||
$now = new \DateTime($date);
|
||||
$validUntil = new \DateTime($date);
|
||||
$clock = \sammo\GameClock::fromStorage(\sammo\KVStorage::getStorage($db, 'game_env'));
|
||||
$now = \DateTime::createFromImmutable($clock->tickToDateTime($general->getTurnTick()));
|
||||
$validUntil = clone $now;
|
||||
$validMinutes = max(30, $env['turnterm'] * 3);
|
||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||
|
||||
|
||||
@@ -147,8 +147,9 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
$destNation['color']
|
||||
);
|
||||
|
||||
$now = new \DateTime($date);
|
||||
$validUntil = new \DateTime($date);
|
||||
$clock = \sammo\GameClock::fromStorage(\sammo\KVStorage::getStorage($db, 'game_env'));
|
||||
$now = \DateTime::createFromImmutable($clock->tickToDateTime($general->getTurnTick()));
|
||||
$validUntil = clone $now;
|
||||
$validMinutes = max(30, $env['turnterm']*3);
|
||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||
|
||||
@@ -217,4 +218,4 @@ class che_불가침파기제의 extends Command\NationCommand{
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,8 +145,9 @@ class che_종전제의 extends Command\NationCommand{
|
||||
$destNation['color']
|
||||
);
|
||||
|
||||
$now = new \DateTime($date);
|
||||
$validUntil = new \DateTime($date);
|
||||
$clock = \sammo\GameClock::fromStorage(\sammo\KVStorage::getStorage($db, 'game_env'));
|
||||
$now = \DateTime::createFromImmutable($clock->tickToDateTime($general->getTurnTick()));
|
||||
$validUntil = clone $now;
|
||||
$validMinutes = max(30, $env['turnterm']*3);
|
||||
$validUntil->add(new \DateInterval("PT{$validMinutes}M"));
|
||||
|
||||
@@ -203,4 +204,4 @@ class che_종전제의 extends Command\NationCommand{
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,41 @@
|
||||
|
||||
namespace sammo\DTO;
|
||||
|
||||
use sammo\GameClock;
|
||||
use sammo\Util;
|
||||
|
||||
class VoteInfo extends \LDTO\DTO
|
||||
{
|
||||
/**
|
||||
* 기존 문자열만 가진 vote도 읽되, 저장 경계에서는 반드시 tick을 함께 둡니다.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function normalizeGameStorage(array $raw, GameClock $clock): array
|
||||
{
|
||||
if (!array_key_exists('startTick', $raw)) {
|
||||
$raw['startTick'] = $clock->dateTimeToTick(new \DateTimeImmutable((string)$raw['startDate']));
|
||||
}
|
||||
if (!array_key_exists('endTick', $raw)) {
|
||||
$raw['endTick'] = ($raw['endDate'] ?? null) === null
|
||||
? null
|
||||
: $clock->dateTimeToTick(new \DateTimeImmutable((string)$raw['endDate']));
|
||||
}
|
||||
|
||||
$raw['startTick'] = Util::toInt($raw['startTick']);
|
||||
$raw['endTick'] = $raw['endTick'] === null ? null : Util::toInt($raw['endTick']);
|
||||
$raw['startDate'] = $clock->formatTick($raw['startTick']);
|
||||
$raw['endDate'] = $raw['endTick'] === null ? null : $clock->formatTick($raw['endTick']);
|
||||
return $raw;
|
||||
}
|
||||
|
||||
public static function fromGameStorage(array $raw, GameClock $clock): self
|
||||
{
|
||||
$raw = self::normalizeGameStorage($raw, $clock);
|
||||
unset($raw['startTick'], $raw['endTick']);
|
||||
return self::fromArray($raw);
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
public int $id,
|
||||
public string $title,
|
||||
|
||||
@@ -215,7 +215,7 @@ class DiplomaticMessage extends Message{
|
||||
$this->dest,
|
||||
$this->src,
|
||||
"【외교】{$year}년 {$month}월: {$this->src->nationName}{$josaYi} {$this->dest->nationName}에게 제안한 {$this->diplomacyDetail}",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[
|
||||
'delete'=>$this->id,
|
||||
@@ -231,7 +231,7 @@ class DiplomaticMessage extends Message{
|
||||
$this->dest,
|
||||
$this->src,
|
||||
"【외교】{$year}년 {$month}월: {$this->src->nationName}{$josaYi} {$this->dest->nationName}에게 제안한 {$this->diplomacyDetail}",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[
|
||||
'delete'=>$this->id,
|
||||
|
||||
@@ -123,7 +123,7 @@ class OpenNationBetting extends \sammo\Event\Action
|
||||
}
|
||||
|
||||
$logger->flush();
|
||||
$now = new DateTime();
|
||||
$now = Message::gameNow();
|
||||
$text = "새로운 {$name} 내기가 열렸습니다. 천통국 베팅란을 확인해주세요.";
|
||||
|
||||
$src = new MessageTarget(0, '', 0, 'System', '#000000');
|
||||
|
||||
@@ -3727,7 +3727,7 @@ class GeneralAI
|
||||
$src,
|
||||
$src,
|
||||
$general->getVar('npcmsg'),
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
|
||||
+24
-5
@@ -26,6 +26,12 @@ class Message
|
||||
) {
|
||||
}
|
||||
|
||||
public static function gameNow(): \DateTime
|
||||
{
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
||||
return \DateTime::createFromImmutable($clock->nowDateTime());
|
||||
}
|
||||
|
||||
public function setSentInfo(int $mailbox, int $messageID) : self
|
||||
{
|
||||
if(!Message::isValidMailBox($mailbox)){
|
||||
@@ -78,6 +84,15 @@ class Message
|
||||
}
|
||||
|
||||
public function toArray():array{
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
||||
$messageTick = $clock->dateTimeToTick($this->date);
|
||||
$deleteUntilTick = GameClock::addTicks($messageTick, $clock->ticksFromMinutes(5));
|
||||
$deleteRemainingTicks = max(0, $deleteUntilTick - $clock->nowTick());
|
||||
$deleteRemainingTicks = min($deleteRemainingTicks, $clock->ticksFromSeconds(2_147_483));
|
||||
$deleteRemainingMilliseconds = intdiv(
|
||||
$deleteRemainingTicks * 1000,
|
||||
$clock->ticksPerSecond(),
|
||||
);
|
||||
if($this->msgType === MessageType::public){
|
||||
$src = $this->src->toArray();
|
||||
$dest = null;
|
||||
@@ -98,7 +113,9 @@ class Message
|
||||
'dest'=>$dest,
|
||||
'text'=>$this->msg,
|
||||
'option'=>$this->msgOption,
|
||||
'time'=>$this->date->format('Y-m-d H:i:s')
|
||||
'time'=>$this->date->format('Y-m-d H:i:s'),
|
||||
'deleteRemainingMilliseconds'=>$deleteRemainingMilliseconds,
|
||||
'clockMode'=>$clock->getMode(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -446,7 +463,7 @@ class Message
|
||||
$src,
|
||||
$dest,
|
||||
$msg,
|
||||
new \DateTime(),
|
||||
self::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
@@ -480,6 +497,8 @@ class Message
|
||||
}
|
||||
|
||||
public function invalidate(?array $newMsgOption=null, bool $hideMsg=true){
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage(DB::db(), 'game_env'));
|
||||
$validUntilTick = $clock->dateTimeToTick($this->validUntil);
|
||||
if($newMsgOption !== null){
|
||||
$this->msgOption = $newMsgOption;
|
||||
}
|
||||
@@ -487,7 +506,8 @@ class Message
|
||||
$this->msgOption['invalid'] = true;
|
||||
|
||||
if($hideMsg){
|
||||
$this->validUntil = new \DateTime('2000-12-31');
|
||||
$validUntilTick = GameClock::addTicks($clock->nowTick(), -1);
|
||||
$this->validUntil = \DateTime::createFromImmutable($clock->tickToDateTime($validUntilTick));
|
||||
}
|
||||
else{
|
||||
if(key_exists('receiverMessageID', $this->msgOption)){
|
||||
@@ -505,8 +525,7 @@ class Message
|
||||
'text' => $this->msg,
|
||||
'option' => $this->msgOption
|
||||
]),
|
||||
'valid_until'=>GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'))
|
||||
->dateTimeToTick($this->validUntil),
|
||||
'valid_until'=>$validUntilTick,
|
||||
], 'id=%i', $this->id);
|
||||
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ class RaiseInvaderMessage extends Message
|
||||
$srcTarget = MessageTarget::buildSystemTarget();
|
||||
$destTarget = MessageTarget::buildQuick($destGeneralID);
|
||||
if ($date === null) {
|
||||
$date = new \DateTime();
|
||||
$date = Message::gameNow();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,7 +108,7 @@ class ScoutMessage extends Message
|
||||
$this->src,
|
||||
$this->dest,
|
||||
"{$this->src->nationName}{$josaRo} 등용 제의 수락",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[
|
||||
'delete' => $this->id
|
||||
@@ -156,7 +156,7 @@ class ScoutMessage extends Message
|
||||
$this->src,
|
||||
$this->dest,
|
||||
"{$this->src->nationName}{$josaRo} 등용 제의 거부",
|
||||
new \DateTime(),
|
||||
Message::gameNow(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[
|
||||
'delete' => $this->id
|
||||
@@ -205,9 +205,9 @@ class ScoutMessage extends Message
|
||||
$db = DB::db();
|
||||
$srcGeneral = $db->queryFirstRow('SELECT `name`, nation FROM general WHERE `no`=%i', $srcGeneralID);
|
||||
$destGeneral = $db->queryFirstRow('SELECT `name`, nation, `officer_level` FROM general WHERE `no`=%i', $destGeneralID);
|
||||
if ($date === null) {
|
||||
$date = new \DateTime();
|
||||
}
|
||||
if ($date === null) {
|
||||
$date = Message::gameNow();
|
||||
}
|
||||
|
||||
if ($destGeneral['officer_level'] == 12) {
|
||||
if ($reason !== null) {
|
||||
|
||||
@@ -6,15 +6,20 @@ use sammo\Enums\EventTarget;
|
||||
use sammo\Enums\InheritanceKey;
|
||||
use \Symfony\Component\Lock;
|
||||
|
||||
class TurnExecutionHelper
|
||||
{
|
||||
class TurnExecutionHelper
|
||||
{
|
||||
/** @var General*/
|
||||
protected $generalObj;
|
||||
|
||||
public function __construct(General $general)
|
||||
public function __construct(General $general)
|
||||
{
|
||||
$this->generalObj = $general;
|
||||
}
|
||||
}
|
||||
|
||||
public static function monotonicCompletionTick(int $completedTick, int $candidateTick): int
|
||||
{
|
||||
return max($completedTick, $candidateTick);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
@@ -450,9 +455,12 @@ class TurnExecutionHelper
|
||||
updateTraffic();
|
||||
|
||||
if ($executionOver) {
|
||||
if ($currentTurn !== null) {
|
||||
$executed = true;
|
||||
$gameStor->turntime = $currentTurn;
|
||||
if ($currentTurn !== null) {
|
||||
$executed = true;
|
||||
$gameStor->turntime = self::monotonicCompletionTick(
|
||||
Util::toInt($gameStor->turntime),
|
||||
$currentTurn,
|
||||
);
|
||||
}
|
||||
unlock();
|
||||
return $gameStor->turntime;
|
||||
@@ -497,10 +505,16 @@ class TurnExecutionHelper
|
||||
$gameStor->month
|
||||
);
|
||||
|
||||
if ($currentTurn !== null) {
|
||||
$executed = true;
|
||||
$gameStor->turntime = $currentTurn;
|
||||
}
|
||||
if ($currentTurn !== null) {
|
||||
$executed = true;
|
||||
// A general's sub-tick can be just before the monthly boundary that
|
||||
// was completed above. Never move the global completion cursor back
|
||||
// behind an already-applied monthly event.
|
||||
$gameStor->turntime = self::monotonicCompletionTick(
|
||||
Util::toInt($gameStor->turntime),
|
||||
$currentTurn,
|
||||
);
|
||||
}
|
||||
|
||||
//토너먼트 처리
|
||||
processTournament();
|
||||
|
||||
@@ -55,7 +55,8 @@ class UserLogger
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$date = TimeUtil::now();
|
||||
$clock = GameClock::fromStorage(KVStorage::getStorage($db, 'game_env'));
|
||||
$date = $clock->formatTick($clock->nowTick());
|
||||
$serverID = UniqueConst::$serverID;
|
||||
$request = array_map(function ($textAndType) use ($date, $serverID) {
|
||||
[$text, $type] = $textAndType;
|
||||
|
||||
Reference in New Issue
Block a user