docs: NPC 명령 선택기 항목 제거, Server Action Queue 추가
- NPC 명령 선택은 기존처럼 동기 모드로 구현 - 로직을 최대한 기존과 유사하게 - Server Action Queue 추가 - 외부 이벤트 루프가 관리
This commit is contained in:
+7
-26
@@ -51,12 +51,13 @@ Collection은 다양하나, 게임 엔진에 필요한 값과 게임 엔진에
|
||||
게임 엔진은 내부적으로 세개의 처리 큐를 가집니다.
|
||||
|
||||
- 장수 처리 Queue: 턴마다 처리되는 장수 명령 처리 Queue입니다.
|
||||
- NPC Action Queue: NPC의 명령을 처리하는 Queue입니다.
|
||||
- NPC 명령 선택기의 입력 요청이 이곳에 쌓입니다.
|
||||
- 유저 Action Queue: 유저의 명령을 처리합니다.
|
||||
- 내부적으로는 Double Ended Queue로 구현한 일종의 Priority Queue입니다.
|
||||
- Server Action Queue: 서버 내 각종 외부 이벤트를 처리하는 Queue입니다.
|
||||
- 경매, 토너먼트, 관리자 처리등이 해당합니다.
|
||||
- User Action Queue: 유저의 명령을 처리합니다.
|
||||
- API 처리기를 통해 전달됩니다.
|
||||
|
||||
세개의 처리 큐는 장수 처리 Queue > NPC Action Queue > 유저 Action Queue 순의 우선순위를 가집니다.
|
||||
세개의 처리 큐는 장수 처리 Queue > Server Action Queue > User Action Queue 순의 우선순위를 가집니다.
|
||||
|
||||
#### DB 반영 시점
|
||||
|
||||
@@ -66,20 +67,6 @@ MongoDB에 데이터가 기록되는 시점은 Queue의 아이템 하나를 해
|
||||
게임 엔진 내에서 변경되는 내용은 메모리 내의 저장소에만 담아두고, 처리를 마치는 시점에 변경된 내용을 정리하여 한번에 쓰기 작업을 수행하여 Transaction을 모사합니다.
|
||||
|
||||
|
||||
### NPC 명령 선택기
|
||||
|
||||
NPC 명령 선택기는 NPC가 어떤 턴을 실행해야할지만을 연산하는 컴포넌트입니다.
|
||||
|
||||
NPC의 실행턴보다 일정 시간 이전에 적절한 턴이 무엇인지 계산하고, 게임 엔진으로 결과값을 전송합니다.
|
||||
|
||||
이때 명령의 규격은 일반 유저가 내리는 명령 규격과 유사한 형태를 갖습니다.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> 기존 삼모전 PHP에서는 명령 선택기가 게임 엔진과 동기적으로 구성되어있었습니다.
|
||||
|
||||
|
||||
|
||||
### API 처리기
|
||||
|
||||
API 처리기는 유저의 명령을 받아 1차적으로 처리합니다.
|
||||
@@ -100,6 +87,8 @@ API 처리기는 유저의 명령을 받아 1차적으로 처리합니다.
|
||||
|
||||
API 처리기와 연계되어(= 같은 스레드에서) 운용됩니다.
|
||||
|
||||
외부 이벤트 처리기가 게임 엔진에 요청하는 경우 `Server Action Queue`를 사용합니다.
|
||||
|
||||
## 기존 삼국지 모의전투 PHP와 비교하여 달라진 부분
|
||||
|
||||
### 게임 엔진
|
||||
@@ -110,14 +99,6 @@ PHP 버전에서 장수 처리 Queue는 `sammo::TurnExecutionHelper`에 해당
|
||||
|
||||
이러한 처리 방법은 장수 처리 Queue 하나만으로 운영되는 형태로 생각할 수 있습니다.
|
||||
|
||||
### NPC 명령 선택기
|
||||
|
||||
NPC의 실행 턴이 무엇이 될지는 엔진내에 NPC 턴 실행 직전에 결정되므로, 게임 엔진 에서 처리되어있다고 볼 수 있습니다.
|
||||
|
||||
`sammo::GeneralAI`가 처리를 전담하고 있으며, `sammo::TurnExecutionHelper`가 `sammo::GeneralAI::chooseNationTurn()`, `sammo::GeneralAI::chooseGeneralTurn()`를 호출하는 방식입니다.
|
||||
|
||||
게임 엔진과 분리되어 있지 않으므로, 턴 입력, 세율 조정 등의 작업이 직접 이루어졌습니다.
|
||||
|
||||
### API 처리기
|
||||
|
||||
유기체 서버 시절에서는 `c_*.php` 계열 함수들이 API를 처리하는 형태였고, 이후 HiDCHe 에서 json web api 처리를 위해 `j_*.php` 계열 함수들이 추가되었습니다.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="441px" height="271px" viewBox="-0.5 -0.5 441 271" content="<mxfile><diagram id="ovDIAAWsHlNK0DibyGEH" name="페이지-1">zZjBjpswEIafxlJ7iQAbYh9twraXVq320LMTvAGJhIiQJrtP37ExCQSiUikFLsjM2GB/8zNjg3C4u3wp5CH5lscqQ54TXxBeIc8LAgxXbXivDJQElWFbpHFlcm+G1/RDWaNjrac0VsdWxzLPszI9tI2bfL9Xm7Jlk0WRn9vd3vKs/daD3KqO4XUjs671VxqXiV2Ft7zZv6p0m9RvdgNWeXay7mxXckxknJ8bJhwhHBZ5Xlat3SVUmWZXc6nGvTzwXidWqH05ZIBXDfgts5NdG4pCxCLEfd2gFDEqoYPjIsw9G7Zj+V6TKPLTPlb6YQ7C4pykpXo9yI32niH0YEvKXQZ3MF7Yd6miVJeH83WvFEA9Kt+psniHLnaARy04qxzi2PvzLQ5uDTdpxABbm7Sh314ffaMDDQuoHxYeAAv8ui083Y4E4gHi8GDn50nBoMf43EnwYTwQH3kCPjIA31prjYDWfDY/rQ2F9Qyt+R1Yi8VifkiCEZEEA/TzAR1AOvPUDxsR1rIfVoi4yU9w1bNz+KZM8/1s8lPgTJif6MD8hKIVogQJAmsJIamFwDrIYCJiXUBrq1sm9XPETQ0QGDHXFgYqTAQ4EksdgYZ36dSLn1Cz9wEYXF+fEQDWCcD3H+H8RErIhCKtt8BtSLJWF8iS1h+63ovoafiTq+qe2Ki7Ntd9TOz2IXc/YNjEBZpj6wMWejcniEVMyfzQjirG7vEB0G7+ivaa/VaIMbNpnhvF5ZgUh5wr3gxUrg8WYmV0uESc1JbKhZEI+0sRdBCuHUWpjQ/jiJpHMZD3avIYdEoPGTMG/YcTqNY6A0CDG9ogal9betOF3lO5pk9ganyTdhXOKkzUGOdGm45Ju3u6MWR8xFemoXensp9yp8ThWZS4e56+NybPIUejy6cu4/XnB5A9Xecis1cVrJnMHZtOWMM9O/ZDT6VPYd89aUENjHtgSw1b7vT69+vjwaz9n+HDzYtxQz+s883U8O9Lp+/+P/hwe/s1anyN/8s4+gM=</diagram></mxfile>">
|
||||
<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="441px" height="271px" viewBox="-0.5 -0.5 441 271" content="<mxfile><diagram id="ovDIAAWsHlNK0DibyGEH" name="페이지-1">zZhNk6IwEIZ/Tap2LxYQPsIxQWb2soctD3tGyQhVKBbiqPPrtzsJIoJTHFzloqE7HZOn33SChEab03uV7LLfZSoL4ljpidA5cRzbYhZ8oeWsLSyg2rCu8tR0ag2L/Es2kcZ6yFO573Ssy7Ko813XuCq3W7mqO7akqspjt9tHWXR/dZesZc+wWCVF3/o3T+vMrMIJWvsvma+z5pdtP9SeTdJ0NivZZ0laHq9MNCY0qsqy1q3NKZIFwmu46Li3O97LxCq5rccEODrgMykOZm0kjkgYE+5hgzESsgQ6WDah3DFZ2tfnhkRVHrapxMEsQsUxy2u52CUr9B4h92DL6k0BTxAv+pMz8/2UVS1PVyYz2XdZbmRdnaGL8TqNdIxyXMs8H9s82A3c7CoH1NgSk/r1ZeiWDjQMoGFYdAQs8GNbONiOBeE+4TCw9ecgIeg+Pvsl+Cgdic99AD53BL4las0FrXnh9LQ2FtYjtOb1YM1ms+kh8Z+IxB+hny/oANKZpn7CJ8IKhmFFhKv6BJ84O4uv6rzcTqY++dYL6xMbWZ9IPCfMJcKFtURQ1CJg7RcwEbGsoLXGlir9nHB1BghKQtscDEyoDHAiAszAlTewmsW/ULO3CRh9vj4iAWEvAQtZwdynp1PXfaFO7f7ZoATlET5XDdzbyZAmI6Vb1lQCvKzgxL3pyc59Js8xB8vpR5/x8ucdyA7e+WK100V4XS70hreQ/sU9OfbsmezvnFMd9h8KHMdLtZgrcAHhbmPRLkpENFyGoYOwTRRjpn6HnDA1VAjVd/6IHPSAD6RldD15atm17xx8+q4g8MgCbqhiW7/LDORicB/gJcNWgb4Zqk2BzrEeiinji1Nwuw28sVfbh6Sgf/R1uEH9YPp1kqHO0aW4GZKqHuFu4areKLZ42RxKSu8+MzXpP7P0N+PeSB9wY30RKPeW8jf7Qd3rdFFnbxg+Aj0Erl5Ov6d65//Rh8f2jy3lu/p7kMb/AA==</diagram></mxfile>">
|
||||
<defs/>
|
||||
<g>
|
||||
<rect x="0" y="70" width="120" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
@@ -129,68 +129,13 @@
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 20px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
NPC Action Queue
|
||||
Server Action Queue
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="220" y="24" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
NPC Action Queue
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="160" y="70" width="120" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 85px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
NPCa 세율 20%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="220" y="89" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
NPCa 세율 20%
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="160" y="100" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 120px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
NPCa 턴1
|
||||
<br/>
|
||||
출병 무위
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="220" y="124" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
NPCa 턴1...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="160" y="140" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 160px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
NPCc 턴1
|
||||
<br/>
|
||||
귀환
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="220" y="164" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
NPCc 턴1...
|
||||
Server Action Queue
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
@@ -201,15 +146,15 @@
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 130px; margin-left: 321px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
장수f 경매결과
|
||||
국가a
|
||||
<br/>
|
||||
백마 획득
|
||||
세율 30%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="380" y="134" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
장수f 경매결과...
|
||||
국가a...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
@@ -220,35 +165,34 @@
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 170px; margin-left: 321px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
시스템
|
||||
장수x(국가b)
|
||||
<br/>
|
||||
적토마 잠금
|
||||
사령턴1 발령
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="380" y="174" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
시스템
|
||||
적토마 잠금
|
||||
장수x(국가b)...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="320" y="190" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<rect x="160" y="70" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 321px;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 90px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
국가a
|
||||
장수f 경매결과
|
||||
<br/>
|
||||
세율 30%
|
||||
백마 획득
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="380" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
국가a...
|
||||
<text x="220" y="94" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
장수f 경매결과...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
@@ -259,34 +203,53 @@
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 250px; margin-left: 321px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
장수x(국가b)
|
||||
유니크 경매
|
||||
<br/>
|
||||
사령턴1 발령
|
||||
적토마 잠금
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="380" y="254" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
장수x(국가b)...
|
||||
유니크 경매...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="160" y="180" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<rect x="160" y="110" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 200px; margin-left: 161px;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 130px; margin-left: 161px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
NPCd(국가a)
|
||||
토너먼트 우승자
|
||||
<br/>
|
||||
사령턴1 포상
|
||||
장수b
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="220" y="204" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
NPCd(국가a)...
|
||||
<text x="220" y="134" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
토너먼트 우승자...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="320" y="190" width="120" height="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/>
|
||||
<g transform="translate(-0.5 -0.5)">
|
||||
<switch>
|
||||
<foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 210px; margin-left: 321px;">
|
||||
<div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
|
||||
<div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
|
||||
설문 유니크 시도
|
||||
<br/>
|
||||
장수 c
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="380" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
|
||||
설문 유니크 시도...
|
||||
</text>
|
||||
</switch>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 21 KiB |
+1
-62
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 21 KiB |
Reference in New Issue
Block a user