From a88982940bdd96f7411973a35ac15472e8d48fe4 Mon Sep 17 00:00:00 2001 From: hide_d Date: Sat, 14 Apr 2018 15:37:52 +0900 Subject: [PATCH] =?UTF-8?q?=EB=93=B1=EC=9A=A9=EC=9E=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=9D=84=20=EC=9C=84=ED=95=9C=20ScoutMessage=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/DiplomacticMessage.php | 79 +++++++- hwe/sammo/Message.php | 17 +- hwe/sammo/MessageTarget.php | 8 +- hwe/sammo/ScoutMessage.php | 298 +++++++++++++++++++++++++++++-- 4 files changed, 380 insertions(+), 22 deletions(-) diff --git a/hwe/sammo/DiplomacticMessage.php b/hwe/sammo/DiplomacticMessage.php index 0a0efca5..417eae22 100644 --- a/hwe/sammo/DiplomacticMessage.php +++ b/hwe/sammo/DiplomacticMessage.php @@ -3,6 +3,20 @@ namespace sammo; class DiplomacticMessage extends Message{ + const ACCEPTED = 1; + const DECLINED = -1; + const INVALID = 0; + + const TYPE_SURRENDER = 'surrender'; //항복 + const TYPE_ALLY = 'ally'; //불가침 + const TYPE_MERGE = 'merge'; //통합 + const TYPE_CEASE = 'cease'; //종전 + const TYPE_CANCEL = 'cancel'; //불가침 파기 + + + protected $diplomaticType = ''; + protected $validDiplomacy = true; + public function __construct( string $msgType, MessageTarget $src, @@ -16,13 +30,72 @@ class DiplomacticMessage extends Message{ if ($msgType !== self::MSGTYPE_DIPLOMACY){ throw new \InvalidArgumentException('DiplomaticMessage msgType'); } + + $this->diplomaticType = Util::array_get($msgOption['action']); + if(array_search($this->diplomaticType, [ + self::TYPE_SURRENDER, + self::TYPE_ALLY, + self::TYPE_MERGE, + self::TYPE_CEASE, + self::TYPE_CANCEL + ]) === false) + { + throw new \InvalidArgumentException('Invalid Diplomatic ActionType'); + } + parent::__construct(...func_get_args()); - //TODO: 누가, 누구에게 보낸 건지 파싱 + + if(Util::array_get($msgOption['used'])){ + $this->validDiplomacy = false; + } + + if($this->$validUntil < (new \DateTime())){ + $this->validDiplomacy = false; + } } - public function send(){ - parent::send(); + /** + * @return int 수행 결과 반환, ACCEPTED(등용장 소모), DECLINED(등용장 소모), INVALID 중 반환 + */ + public function agreeMessage(int $receiverID, string &$reason=null):int{ + //NOTE: 올바른 유저가 agreeMessage() 호출을 한건지는 외부에서 체크 필요(Session->userID 등) + + if(!$this->validScout){ + if($reason !== null){ + $reason = '이미 사용한 외교서신입니다'; + } + return self::INVALID; + } + if($this->mailbox !== $this->dest->nationID + static::MAILBOX_NATIONAL){ + if($reason !== null){ + $reason = '송신자가 외교서신을 수락할 수 없습니다'; + } + return self::INVALID; + } + + //거절하지 않았어야함. + //수뇌여야함 + //방랑군이 아니어야함 + //상대도 방랑군이 아니어야함 + + //불가침시 : 교전중이 아니어야함, 선포중이 아니어야함. 합병중이 아니어얗. + //불가침 파기시 : 불가침 중이어야함. + //종전시 : 교전중이거나 선포중이어야함. + //합병시 : 양국 다 외교제한이 지나지 않았어야함. 국력, 장수수가 적절해야함. 인접한 국가여야함. 서로 교전중이어선 안됨. + // 송신자가 선포, 전쟁중이어선 안됨. 송신자가 C국과 불가침인데 수신자가 C국과 전쟁중이면 안됨 + //항복시 : 양국 다 외교제한이 지나지 않았어야함. 국력, 장수수가 적절해야함. 인접한 국가여야함. 서로 교전중이어선 안됨. + // 송신자가 선포, 전쟁중이어선 안됨. 송신자가 C국과 불가침인데 수신자가 C국과 전쟁중이면 안됨 + + + $db = DB::db(); + $general = $db->queryFirstRow('SELECT nation, `no`, city, `level` FROM general WHERE `no`=%i', $receiverID); + + + } + + public function declineMessage(string &$reason=null):int{ + } } \ No newline at end of file diff --git a/hwe/sammo/Message.php b/hwe/sammo/Message.php index 466766aa..0c2b9f61 100644 --- a/hwe/sammo/Message.php +++ b/hwe/sammo/Message.php @@ -245,7 +245,7 @@ class Message if($this->sendCnt > 0){ throw new \RuntimeException('이미 전송한 메일입니다.'); } - if($this->msgType === self::MSGTYPE_PRIVATE){ + if($this->msgType === self::MSGTYPE_PRIVATE && $this->src->generalID !== $this->dest->generalID){ return $this->sendRaw($this->src->generalID); } if($this->msgType === self::MSGTYPE_NATIONAL && $this->src->nationID !== $this->dest->nationID){ @@ -295,4 +295,19 @@ class Message return $receiveID; } + + public function invalidate(array $newMsgOption=null){ + if($newMsgOption !== null){ + $this->msgOption = $newMsgOption; + } + + $this->validUntil = new \DateTime('2000-12-31'); + + $db = DB::db(); + $db->update('message', [ + 'msgOption'=>Json::encode($this->msgOption), + 'validUntil'=>$this->validUntil->format('Y-m-d H:i:s'), + ]); + + } } diff --git a/hwe/sammo/MessageTarget.php b/hwe/sammo/MessageTarget.php index b8860c34..baa350be 100644 --- a/hwe/sammo/MessageTarget.php +++ b/hwe/sammo/MessageTarget.php @@ -7,12 +7,14 @@ class MessageTarget { /** @var int */ public $nationID; + /** @var string */ + public $generalName; /** @var string */ public $nationName; /** @var string */ public $color; - public function __construct(int $generalID, int $nationID, string $nationName, string $color){ + public function __construct(int $generalID, string $generalName, int $nationID, string $nationName, string $color){ if($mailbox > Message::MAILBOX_NATIONAL){ @@ -23,6 +25,7 @@ class MessageTarget { } $this->generalID = $generalID; + $this->generalName = $generalName; $this->nationID = $nationID; $this->nationName = $nationName; $this->color = $color; @@ -36,12 +39,13 @@ class MessageTarget { $arr['nation_id'] = 0; } - return new MessageTarget($arr['id'], $arr['nation_id'], $arr['nation'], $arr['color']); + return new MessageTarget($arr['id'], $arr['name'], $arr['nation_id'], $arr['nation'], $arr['color']); } public function toArray() : array{ return [ 'id'=>$this->generalID, + 'name'=>$this->generalName, 'nation_id'=>$this->nationID, 'nation'=>$this->nationName, 'color'=>$this->color diff --git a/hwe/sammo/ScoutMessage.php b/hwe/sammo/ScoutMessage.php index 35c94ca5..a403160e 100644 --- a/hwe/sammo/ScoutMessage.php +++ b/hwe/sammo/ScoutMessage.php @@ -31,31 +31,295 @@ class ScoutMessage extends Message{ if(Util::array_get($msgOption['used'])){ $this->validScout = false; } + + if($this->validUntil <= new DateTime()){ + $this->validScout = false; + } + } + + protected function checkAgreeValidation(int $startYear, int $year, array $general, array $scoutNation){ + if($year < $startYear + 3){ + return [self::INVALID, '초반제한 중입니다.']; + } + + if(!$this->validScout){ + return [self::INVALID, '유효하지 않은 등용장입니다.']; + } + if($this->mailbox !== $this->dest->generalID){ + return [self::INVALID, '송신자가 등용장을 수락할 수 없습니다.']; + } + + if($this->mailbox !== $receiverID){ + return [self::INVALID, '올바른 수신자가 아닙니다.']; + } + + if(!$scoutNation){ + return [self::DECLINED, '이미 멸망한 국가입니다.']; + } + + if(!$scoutNation['scout']){ + return [self::INVALID, '현재 임관금지 중인 국가입니다.']; + } + + if($scoutNation['level'] == 0){ + return [self::DECLINED, '방랑군에는 임관할 수 없습니다.']; + } + + if($scoutNation['nation'] == $general['nation']){ + return [self::DECLINED, '이미 같은 국가입니다.']; + } + + if($general['level'] == 12){ + return [self::DECLINED, '군주는 등용장을 수락할 수 없습니다.']; + } + + if(strpos($general['nations'], ",{$scoutNation['nation']},") >= 0){ + return [self::DECLINED, '이미 임관했었던 국가입니다.']; + } + + return [self::ACCEPTED, '']; } /** * @return int 수행 결과 반환, ACCEPTED(등용장 소모), DECLINED(등용장 소모), INVALID 중 반환 */ - public function agreeMessage(string &$reason=null):int{ + public function agreeMessage(int $receiverID):int{ //NOTE: 올바른 유저가 agreeMessage() 호출을 한건지는 외부에서 체크 필요(Session->userID 등) - if(!$this->validScout){ - if($reason !== null){ - $reason = '이미 사용한 등용장입니다'; - } - return self::INVALID; + if(!$this->id){ + throw \RuntimeException('전송되지 않은 메시지에 수락 진행 중'); } - if($this->mailbox !== $this->dest->generalID){ - if($reason !== null){ - $reason = '송신자가 등용장을 수락할 수 없습니다'; - } - return self::INVALID; - } - $db = DB::db(); - $general = $db->queryFirstRow('SELECT nation, `no`, city, nations FROM general WHERE `no`=%i', $this->dest->generalID); + list( + $startYear, + $year, + $month, + $killturn + ) = $db->queryFirstList('SELECT startyear, year, month, killturn FROM game LIMIt 1'); + $scoutNation = $db->queryFirstRow( + 'SELECT nation, `name`, `level`, capital, scout FROM nation WHERE nation=%i', + $this->src->nationID + ); + $general = $db->queryFirstRow( + 'SELECT `no`, `name`, nation, nations, city, `level`, troop, npc, gold, rice FROM general WHERE `no`=%i', + $receiverID + ); + list($result, $reason) = $this->checkAgreeValidation($startYear, $year, $general, $scoutNation); + + if($result !== self::ACCEPTED){ + pushGenLog($general, ["●{$reason} 등용 수락 불가."]); + if($result === self::DECLINED){ + $this->_declineMessage(); + } + return $result; + } + + $scoutNationGeneralCnt = $db->queryFirstField( + 'SELECT COUNT(`no`) FROM general WHERE nation = %i', + $scoutNation['nation'] + ); + + $originalNationGeneralCnt = $db->queryFirstField( + 'SELECT COUNT(`no`) FROM general WHERE nation = %i', + $general['nation'] + ); + + $isTroopLeader = false; + if($general['troop']){ + $troopLeader = $db->queryFirstField('SELECT `no` FROM troop WHERE troop = %i', $general['troop']); + if($troopLeader == $receiverID){ + $isTroopLeader = true; + } + } + + $scoutNationGeneralCnt+=1; + if($scoutNationGeneralCnt < 10){ + $scoutNationGeneralCnt = 10;//XXX: 상수! + } + + + + $originalNationGeneralCnt-=1; + if($originalNationGeneralCnt < 10){ + $originalNationGeneralCnt = 10;//XXX: 상수! + } + + //TODO: Logging 시스템 들어엎자. + $senderLog = []; + $receiverLog = []; + $generalPublicLog = []; + + $senderLog[] = "{$general['name']} 등용에 성공했습니다."; + $receiverLog[] = "{$scoutNation['name']}(으)로 망명하여 수도로 이동합니다."; + $generalPublicLog[] = "●{$month}월:{$general['name']}(이)가 {$scoutNation['name']}(으)로 망명하였습니다."; + + // 국가 변경, 도시 변경, 일반으로, 수도로 + $setValues = [ + 'belong'=>1, + 'level'=>1, + 'nation'=>$scoutNation['nation'], + 'city'=>$scoutNation['capital'], + 'nations'=>$db->sqleval('CONCAT(nations, %s)', "{$scoutNation['nation']},"), + 'troop'=>0, + ]; + + $setSenderValues = [ + 'experience'=>$db->sqleval('experience + %i', 100),//XXX: 상수. + 'dedication'=>$db->sqleval('dedication + %i', 100) + ]; + + $setOriginalNationValues = [ + 'totaltech'=>$db->sqleval('tech * %i', $originalNationGeneralCnt), + 'gennum'=>$originalNationGeneralCnt + ]; + + $setScoutNationValues = [ + 'totaltech'=>$db->sqleval('tech * %i', $scoutNationGeneralCnt), + 'gennum'=>$scoutNationGeneralCnt + ]; + + $setOriginalCityValues = [ + + ]; + + // 재야가 아니면 명성N*10% 공헌N*10%감소 + if($general['nation'] != 0){ + // 1000 1000 남기고 환수 + if($general['gold'] > 1000){//XXX: 상수. + $setValues['gold'] = 1000; + $setOriginalNationValues['gold'] = $db->sqleval('gold + %i', $general['gold'] - 1000); + } + + if($general['rice'] > 1000){//XXX: 상수. + $setValues['rice'] = 1000; + $setOriginalNationValues['rice'] = $db->sqleval('rice + %i', $general['rice'] - 1000); + } + + //관직 해제 + if(5 <= $general['level'] && $general['level'] <= 11){ + $setOriginalNationValues["l{$general['level']}set"] = 0; + } + else if($general['level'] == 4){ + $setOriginalCityValues['gen1'] = 0; + } + else if($general['level'] == 3){ + $setOriginalCityValues['gen2'] = 0; + } + else if($general['level'] == 2){ + $setOriginalCityValues['gen3'] = 0; + } + + $setValues['betray'] = $db->sqleval('betray + 1'); + $setValues['experience'] = $db->sqleval('experience * (1 - 0.1 * betray)'); + $setValues['dedication'] = $db->sqleval('dedication * (1 - 0.1 * betray)'); + } + else{ + //재야이면 100 100 증가 + $setValues['experience'] = $db->sqleval('experience + %i', 100);//XXX: 상수 + $setValues['dedication'] = $db->sqleval('experience + %i', 100); + } + + if($me['npc'] < 2){ + $setValues['killturn'] = $killturn; + } + + $db->update('general', $setValues, 'no=%i', $receiverID); + $db->update('general', $setSenderValues, 'no=%i', $this->src->generalID); + $db->update('nation', $setOriginalNationValues, 'nation=%i', $general['nation']); + $db->update('nation', $setScoutNationValues, 'nation=%i', $scoutNation['nation']); + if($setOriginalCityValues){ + $db->update('city', $setOriginalCityValues, 'city=%i', $general['city']); + } + + if($isTroopLeader){ + // 모두 탈퇴 + $db->update('general', [ + 'troop'=>0, + ], 'troop=%i', $general['troop']); + // 부대 삭제 + $db->delete('troop', 'troop=%i', $general['troop']); + } + + pushGenLog($general, $receiverLog); + pushGenLog(['no'=>$this->src->generalID], $senderLog); + pushGeneralPublicRecord($generalPublicLog, $year, $month); + + $now = new \DateTime(); + + //메시지 비 활성화 + $this->msgOption['used'] = true; + $this->invalidate(); + $this->validScout = false; + + $newMsg = new Message( + self::MSGTYPE_PRIVATE, + $this->dest, + $this->dest, + "{$scoutNation['name']}(으)로 등용 제의 수락", + $now, + new \DateTime('9999-12-31'), + Json::encode([ + 'related'=>$this->id + ]) + ); + $newMsg->send(); + + return self::ACCEPTED; + } + + protected function _declineMessage(){ + $this->msgOption['used'] = true; + $this->invalidate(); + $this->validScout = false; + + $newMsg = new Message( + self::MSGTYPE_PRIVATE, + $this->dest, + $this->dest, + "{$scoutNation['name']}(으)로 등용 제의 거부", + $now, + new \DateTime('9999-12-31'), + Json::encode([ + 'related'=>$this->id + ]) + ); + $newMsg->send(); + + return self::ACCEPTED; + } + + protected function checkDeclineValidation(int $receiverID){ + if(!$this->validScout){ + return [self::INVALID, '유효하지 않은 등용장입니다.']; + } + if($this->mailbox !== $this->dest->generalID){ + return [self::INVALID, '송신자가 등용장을 거부할 수 없습니다.']; + } + + if($this->mailbox !== $receiverID){ + return [self::INVALID, '올바른 수신자가 아닙니다.']; + } + } + + public function declineMessage(int $receiverID):int{ + if(!$this->id){ + throw \RuntimeException('전송되지 않은 메시지에 거절 진행 중'); + } + + list($result, $reason) = $this->checkDeclineValidation($receiverID); + + if($result === self::INVALID){ + pushGenLog($general, ["●{$reason} 등용 수락 불가."]); + return $result; + } + + $this->_declineMessage(); + pushGenLog(['no'=>$receiverID], "{$this->src->nationName}(으)로 망명을 거부했습니다."); + pushGenLog(['no'=>$this->src->generalID], "{$this->dest->generalName}(이)가 등용을 거부했습니다."); + + return self::DECLINED; } public static function buildScoutMessage(int $srcGeneralID, int $destGeneralID, &$reason = null, \DateTime $date = null): Message{ @@ -67,8 +331,8 @@ class ScoutMessage extends Message{ } $db = DB::db(); - $srcGeneral = $db->queryFirstRow('SELECT nation FROM nation WHERE `no`=%i', $srcGeneralID); - $destGeneral = $db->queryFirstRow('SELECT nation, `level` FROM nation WHERE `no`=%i', $destGeneralID); + $srcGeneral = $db->queryFirstRow('SELECT `name`, nation FROM nation WHERE `no`=%i', $srcGeneralID); + $destGeneral = $db->queryFirstRow('SELECT `name`, nation, `level` FROM nation WHERE `no`=%i', $destGeneralID); if($date === null){ $date = new DateTime(); } @@ -99,6 +363,7 @@ class ScoutMessage extends Message{ $src = new MessageTarget( $srcGeneralID, + $srcGeneral['name'], $srcGeneral['nation'], $srcNationInfo['name'], $srcNationInfo['color'] @@ -106,6 +371,7 @@ class ScoutMessage extends Message{ $dest = new MessageTarget( $destGeneralID, + $destGeneral['name'], $destGeneral['nation'], Util::array_get($srcNationInfo['name'], ''), Util::array_get($srcNationInfo['color'], '')