mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-10-13 06:15:51 +00:00
perf[protocol]: 支持指定协议生成的路径
This commit is contained in:
1 parent
8ae6926bd6
commit
04918a4ab8
11 files changed
+97
-38
No files matched your search
@@ -32,6 +32,7 @@ public class NetConfig {
|
||||
* 协议生成属性变量对应于{@link GenerateOperation}
|
||||
*/
|
||||
private boolean foldProtocol;
|
||||
private String protocolPath;
|
||||
private String protocolParam;
|
||||
private boolean generateJsProtocol;
|
||||
private boolean generateCsProtocol;
|
||||
@@ -73,6 +74,14 @@ public class NetConfig {
|
||||
this.foldProtocol = foldProtocol;
|
||||
}
|
||||
|
||||
public String getProtocolPath() {
|
||||
return protocolPath;
|
||||
}
|
||||
|
||||
public void setProtocolPath(String protocolPath) {
|
||||
this.protocolPath = protocolPath;
|
||||
}
|
||||
|
||||
public String getProtocolParam() {
|
||||
return protocolParam;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ public class PacketService implements IPacketService {
|
||||
var protocolLocation = NetContext.getConfigManager().getLocalConfig().getProtocolLocation();
|
||||
|
||||
var foldProtocol = NetContext.getConfigManager().getLocalConfig().isFoldProtocol();
|
||||
var protocolPath = NetContext.getConfigManager().getLocalConfig().getProtocolPath();
|
||||
var protocolParam = NetContext.getConfigManager().getLocalConfig().getProtocolParam();
|
||||
var generateJsProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateJsProtocol();
|
||||
var generateCsharpProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateCsProtocol();
|
||||
@@ -90,6 +91,7 @@ public class PacketService implements IPacketService {
|
||||
var generateGdProtocol = NetContext.getConfigManager().getLocalConfig().isGenerateGdProtocol();
|
||||
var generateOperation = new GenerateOperation();
|
||||
generateOperation.setFoldProtocol(foldProtocol);
|
||||
generateOperation.setProtocolPath(protocolPath);
|
||||
generateOperation.setProtocolParam(protocolParam);
|
||||
if (generateJsProtocol) {
|
||||
generateOperation.getGenerateLanguages().add(CodeLanguage.JavaScript);
|
||||
|
||||
@@ -94,6 +94,7 @@ public class NetDefinitionParser implements BeanDefinitionParser {
|
||||
resolvePlaceholder("generate-lua-protocol", "generateLuaProtocol", builder, element, parserContext);
|
||||
resolvePlaceholder("generate-gd-protocol", "generateGdProtocol", builder, element, parserContext);
|
||||
resolvePlaceholder("fold-protocol", "foldProtocol", builder, element, parserContext);
|
||||
resolvePlaceholder("protocol-path", "protocolPath", builder, element, parserContext);
|
||||
resolvePlaceholder("protocol-param", "protocolParam", builder, element, parserContext);
|
||||
|
||||
var registryElement = DomUtils.getFirstChildElementByTagName(element, "registry");
|
||||
|
||||
@@ -71,7 +71,8 @@
|
||||
<xsd:attribute name="generate-lua-protocol" type="xsd:string" default="false"/>
|
||||
<xsd:attribute name="generate-gd-protocol" type="xsd:string" default="false"/>
|
||||
<xsd:attribute name="fold-protocol" type="xsd:string" default="false"/>
|
||||
<xsd:attribute name="protocol-param" type="xsd:string" default="false"/>
|
||||
<xsd:attribute name="protocol-path" type="xsd:string"/>
|
||||
<xsd:attribute name="protocol-param" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="config" type="configType"/>
|
||||
|
||||
@@ -32,12 +32,17 @@ public class GenerateOperation {
|
||||
public static final GenerateOperation NO_OPERATION = new GenerateOperation();
|
||||
|
||||
/**
|
||||
* 折叠协议,生成协议文件会和Java源文件保持相同的目录结构
|
||||
* 折叠协议,生成协议文件会和Java源文件保持相同的目录结构,默认不折叠
|
||||
*/
|
||||
private boolean foldProtocol;
|
||||
|
||||
/**
|
||||
* 生成协议文件的后缀名称,如果不指定,用语言约定的默认名称
|
||||
* 生成协议的路径,默认为当前运行项目的路径
|
||||
*/
|
||||
private String protocolPath;
|
||||
|
||||
/**
|
||||
* 保留参数
|
||||
*/
|
||||
private String protocolParam;
|
||||
|
||||
@@ -46,6 +51,14 @@ public class GenerateOperation {
|
||||
*/
|
||||
private final Set<CodeLanguage> generateLanguages = EnumSet.noneOf(CodeLanguage.class);
|
||||
|
||||
public String getProtocolPath() {
|
||||
return protocolPath;
|
||||
}
|
||||
|
||||
public void setProtocolPath(String protocolPath) {
|
||||
this.protocolPath = protocolPath;
|
||||
}
|
||||
|
||||
public boolean isFoldProtocol() {
|
||||
return foldProtocol;
|
||||
}
|
||||
|
||||
@@ -98,28 +98,28 @@ public abstract class GenerateProtocolFile {
|
||||
// 生成C#协议
|
||||
var generateLanguages = generateOperation.getGenerateLanguages();
|
||||
if (generateLanguages.contains(CodeLanguage.CSharp)) {
|
||||
GenerateCsUtils.init();
|
||||
GenerateCsUtils.init(generateOperation);
|
||||
GenerateCsUtils.createProtocolManager();
|
||||
allSortedGenerateProtocols.forEach(it -> GenerateCsUtils.createCsProtocolFile((ProtocolRegistration) it));
|
||||
}
|
||||
|
||||
// 生成Javascript协议
|
||||
if (generateLanguages.contains(CodeLanguage.JavaScript)) {
|
||||
GenerateJsUtils.init();
|
||||
GenerateJsUtils.init(generateOperation);
|
||||
allSortedGenerateProtocols.forEach(it -> GenerateJsUtils.createJsProtocolFile((ProtocolRegistration) it));
|
||||
GenerateJsUtils.createProtocolManager(allSortedGenerateProtocols);
|
||||
}
|
||||
|
||||
// 生成Lua协议
|
||||
if (generateLanguages.contains(CodeLanguage.Lua)) {
|
||||
GenerateLuaUtils.init();
|
||||
GenerateLuaUtils.init(generateOperation);
|
||||
GenerateLuaUtils.createProtocolManager(allSortedGenerateProtocols);
|
||||
allSortedGenerateProtocols.forEach(it -> GenerateLuaUtils.createLuaProtocolFile((ProtocolRegistration) it));
|
||||
}
|
||||
|
||||
// 生成GdScript协议
|
||||
if (generateLanguages.contains(CodeLanguage.GdScript)) {
|
||||
GenerateGdUtils.init();
|
||||
GenerateGdUtils.init(generateOperation);
|
||||
GenerateGdUtils.createProtocolManager(allSortedGenerateProtocols);
|
||||
allSortedGenerateProtocols.forEach(it -> GenerateGdUtils.createGdProtocolFile((ProtocolRegistration) it));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
package com.zfoo.protocol.serializer.cs;
|
||||
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolDocument;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolFile;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolPath;
|
||||
@@ -39,7 +40,7 @@ import static com.zfoo.protocol.util.StringUtils.TAB;
|
||||
*/
|
||||
public abstract class GenerateCsUtils {
|
||||
|
||||
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "CsProtocol/";
|
||||
private static String protocolOutputRootPath = "CsProtocol/";
|
||||
|
||||
private static Map<ISerializer, ICsSerializer> csSerializerMap;
|
||||
|
||||
@@ -47,9 +48,11 @@ public abstract class GenerateCsUtils {
|
||||
return csSerializerMap.get(serializer);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
|
||||
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
|
||||
public static void init(GenerateOperation generateOperation) {
|
||||
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
|
||||
|
||||
FileUtils.deleteFile(new File(protocolOutputRootPath));
|
||||
FileUtils.createDirectory(protocolOutputRootPath);
|
||||
|
||||
csSerializerMap = new HashMap<>();
|
||||
csSerializerMap.put(BooleanSerializer.INSTANCE, new CsBooleanSerializer());
|
||||
@@ -70,6 +73,7 @@ public abstract class GenerateCsUtils {
|
||||
|
||||
public static void clear() {
|
||||
csSerializerMap = null;
|
||||
protocolOutputRootPath = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +89,7 @@ public abstract class GenerateCsUtils {
|
||||
|
||||
for (var fileName : list) {
|
||||
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
|
||||
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "cs/")));
|
||||
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "cs/")));
|
||||
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
|
||||
}
|
||||
}
|
||||
@@ -128,8 +132,8 @@ public abstract class GenerateCsUtils {
|
||||
csBuilder.append(TAB).append("}").append(LS);
|
||||
csBuilder.append("}").append(LS);
|
||||
|
||||
var protocolOutputPath = StringUtils.format("{}{}/{}.cs"
|
||||
, PROTOCOL_OUTPUT_ROOT_PATH
|
||||
var protocolOutputPath = StringUtils.format("{}/{}/{}.cs"
|
||||
, protocolOutputRootPath
|
||||
, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId)
|
||||
, protocolClazzName);
|
||||
FileUtils.writeStringToFile(new File(protocolOutputPath), csBuilder.toString());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
package com.zfoo.protocol.serializer.gd;
|
||||
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolDocument;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolFile;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolPath;
|
||||
@@ -39,7 +40,7 @@ import static com.zfoo.protocol.util.StringUtils.TAB;
|
||||
*/
|
||||
public abstract class GenerateGdUtils {
|
||||
|
||||
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "gdProtocol/";
|
||||
private static String protocolOutputRootPath = "gdProtocol/";
|
||||
|
||||
private static Map<ISerializer, IGdSerializer> gdSerializerMap;
|
||||
|
||||
@@ -47,9 +48,11 @@ public abstract class GenerateGdUtils {
|
||||
return gdSerializerMap.get(serializer);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
|
||||
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
|
||||
public static void init(GenerateOperation generateOperation) {
|
||||
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
|
||||
|
||||
FileUtils.deleteFile(new File(protocolOutputRootPath));
|
||||
FileUtils.createDirectory(protocolOutputRootPath);
|
||||
|
||||
gdSerializerMap = new HashMap<>();
|
||||
gdSerializerMap.put(BooleanSerializer.INSTANCE, new GdBooleanSerializer());
|
||||
@@ -70,6 +73,7 @@ public abstract class GenerateGdUtils {
|
||||
|
||||
public static void clear() {
|
||||
gdSerializerMap = null;
|
||||
protocolOutputRootPath = null;
|
||||
}
|
||||
|
||||
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
|
||||
@@ -77,7 +81,7 @@ public abstract class GenerateGdUtils {
|
||||
|
||||
for (var fileName : list) {
|
||||
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
|
||||
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "gd/")));
|
||||
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "gd/")));
|
||||
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
|
||||
}
|
||||
|
||||
@@ -104,7 +108,7 @@ public abstract class GenerateGdUtils {
|
||||
.filter(it -> Objects.nonNull(it))
|
||||
.forEach(it -> gdBuilder.append(TAB).append(StringUtils.format("protocols[{}] = {}", it.protocolId(), it.protocolConstructor().getDeclaringClass().getSimpleName())).append(LS));
|
||||
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, "ProtocolManager.gd")), gdBuilder.toString());
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.gd")), gdBuilder.toString());
|
||||
}
|
||||
|
||||
public static void createGdProtocolFile(ProtocolRegistration registration) {
|
||||
@@ -130,8 +134,8 @@ public abstract class GenerateGdUtils {
|
||||
// readObject method
|
||||
gdBuilder.append(readObject(registration));
|
||||
|
||||
var protocolOutputPath = StringUtils.format("{}{}/{}.gd"
|
||||
, PROTOCOL_OUTPUT_ROOT_PATH
|
||||
var protocolOutputPath = StringUtils.format("{}/{}/{}.gd"
|
||||
, protocolOutputRootPath
|
||||
, GenerateProtocolPath.getProtocolPath(protocolId)
|
||||
, protocolClazzName);
|
||||
FileUtils.writeStringToFile(new File(protocolOutputPath), gdBuilder.toString());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
package com.zfoo.protocol.serializer.js;
|
||||
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolDocument;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolFile;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolPath;
|
||||
@@ -40,7 +41,7 @@ import static com.zfoo.protocol.util.StringUtils.TAB;
|
||||
*/
|
||||
public abstract class GenerateJsUtils {
|
||||
|
||||
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "jsProtocol/";
|
||||
private static String protocolOutputRootPath = "jsProtocol/";
|
||||
|
||||
private static Map<ISerializer, IJsSerializer> jsSerializerMap;
|
||||
|
||||
@@ -48,9 +49,11 @@ public abstract class GenerateJsUtils {
|
||||
return jsSerializerMap.get(serializer);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
|
||||
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
|
||||
public static void init(GenerateOperation generateOperation) {
|
||||
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
|
||||
|
||||
FileUtils.deleteFile(new File(protocolOutputRootPath));
|
||||
FileUtils.createDirectory(protocolOutputRootPath);
|
||||
|
||||
jsSerializerMap = new HashMap<>();
|
||||
jsSerializerMap.put(BooleanSerializer.INSTANCE, new JsBooleanSerializer());
|
||||
@@ -71,6 +74,7 @@ public abstract class GenerateJsUtils {
|
||||
|
||||
public static void clear() {
|
||||
jsSerializerMap = null;
|
||||
protocolOutputRootPath = null;
|
||||
}
|
||||
|
||||
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
|
||||
@@ -80,7 +84,7 @@ public abstract class GenerateJsUtils {
|
||||
|
||||
for (var fileName : list) {
|
||||
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
|
||||
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "js/")));
|
||||
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "js/")));
|
||||
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
|
||||
}
|
||||
|
||||
@@ -112,7 +116,7 @@ public abstract class GenerateJsUtils {
|
||||
|
||||
jsBuilder.append("export default ProtocolManager;").append(LS);
|
||||
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, "ProtocolManager.js")), jsBuilder.toString());
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.js")), jsBuilder.toString());
|
||||
}
|
||||
|
||||
public static void createJsProtocolFile(ProtocolRegistration registration) {
|
||||
@@ -142,8 +146,8 @@ public abstract class GenerateJsUtils {
|
||||
jsBuilder.append(LS).append(StringUtils.format("export default {};", protocolClazzName)).append(LS);
|
||||
|
||||
|
||||
var protocolOutputPath = StringUtils.format("{}{}/{}.js"
|
||||
, PROTOCOL_OUTPUT_ROOT_PATH
|
||||
var protocolOutputPath = StringUtils.format("{}/{}/{}.js"
|
||||
, protocolOutputRootPath
|
||||
, GenerateProtocolPath.getProtocolPath(protocolId)
|
||||
, protocolClazzName);
|
||||
FileUtils.writeStringToFile(new File(protocolOutputPath), jsBuilder.toString());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
package com.zfoo.protocol.serializer.lua;
|
||||
|
||||
import com.zfoo.protocol.generate.GenerateOperation;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolDocument;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolFile;
|
||||
import com.zfoo.protocol.generate.GenerateProtocolPath;
|
||||
@@ -40,7 +41,7 @@ import static com.zfoo.protocol.util.StringUtils.TAB;
|
||||
*/
|
||||
public abstract class GenerateLuaUtils {
|
||||
|
||||
private static final String PROTOCOL_OUTPUT_ROOT_PATH = "LuaProtocol/";
|
||||
private static String protocolOutputRootPath = "LuaProtocol/";
|
||||
|
||||
private static Map<ISerializer, ILuaSerializer> luaSerializerMap;
|
||||
|
||||
@@ -48,9 +49,11 @@ public abstract class GenerateLuaUtils {
|
||||
return luaSerializerMap.get(serializer);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
FileUtils.deleteFile(new File(PROTOCOL_OUTPUT_ROOT_PATH));
|
||||
FileUtils.createDirectory(PROTOCOL_OUTPUT_ROOT_PATH);
|
||||
public static void init(GenerateOperation generateOperation) {
|
||||
protocolOutputRootPath = FileUtils.joinPath(generateOperation.getProtocolPath(), protocolOutputRootPath);
|
||||
|
||||
FileUtils.deleteFile(new File(protocolOutputRootPath));
|
||||
FileUtils.createDirectory(protocolOutputRootPath);
|
||||
|
||||
luaSerializerMap = new HashMap<>();
|
||||
luaSerializerMap.put(BooleanSerializer.INSTANCE, new LuaBooleanSerializer());
|
||||
@@ -71,6 +74,7 @@ public abstract class GenerateLuaUtils {
|
||||
|
||||
public static void clear() {
|
||||
luaSerializerMap = null;
|
||||
protocolOutputRootPath = null;
|
||||
}
|
||||
|
||||
public static void createProtocolManager(List<IProtocolRegistration> protocolList) throws IOException {
|
||||
@@ -78,7 +82,7 @@ public abstract class GenerateLuaUtils {
|
||||
|
||||
for (var fileName : list) {
|
||||
var fileInputStream = ClassUtils.getFileFromClassPath(fileName);
|
||||
var createFile = new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, StringUtils.substringAfterFirst(fileName, "lua/")));
|
||||
var createFile = new File(StringUtils.format("{}/{}", protocolOutputRootPath, StringUtils.substringAfterFirst(fileName, "lua/")));
|
||||
FileUtils.writeInputStreamToFile(createFile, fileInputStream);
|
||||
}
|
||||
|
||||
@@ -110,7 +114,7 @@ public abstract class GenerateLuaUtils {
|
||||
luaBuilder.append("ProtocolManager.initProtocol = initProtocol").append(LS);
|
||||
luaBuilder.append("return ProtocolManager").append(LS);
|
||||
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}{}", PROTOCOL_OUTPUT_ROOT_PATH, "ProtocolManager.lua")), luaBuilder.toString());
|
||||
FileUtils.writeStringToFile(new File(StringUtils.format("{}/{}", protocolOutputRootPath, "ProtocolManager.lua")), luaBuilder.toString());
|
||||
}
|
||||
|
||||
public static void createLuaProtocolFile(ProtocolRegistration registration) {
|
||||
@@ -144,8 +148,8 @@ public abstract class GenerateLuaUtils {
|
||||
luaBuilder.append(StringUtils.format("return {}", protocolClazzName)).append(LS);
|
||||
|
||||
|
||||
var protocolOutputPath = StringUtils.format("{}{}/{}.lua"
|
||||
, PROTOCOL_OUTPUT_ROOT_PATH
|
||||
var protocolOutputPath = StringUtils.format("{}/{}/{}.lua"
|
||||
, protocolOutputRootPath
|
||||
, GenerateProtocolPath.getCapitalizeProtocolPath(protocolId)
|
||||
, protocolClazzName);
|
||||
FileUtils.writeStringToFile(new File(protocolOutputPath), luaBuilder.toString());
|
||||
|
||||
@@ -64,6 +64,23 @@ public abstract class FileUtils {
|
||||
return System.getProperty("user.dir");
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接父路径和子路径
|
||||
*
|
||||
* @return 绝对路径
|
||||
*/
|
||||
public static String joinPath(String parentPath, String childPath) {
|
||||
if (StringUtils.isEmpty(parentPath)) {
|
||||
return new File(childPath).getAbsolutePath();
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(childPath)) {
|
||||
return new File(parentPath).getAbsolutePath();
|
||||
}
|
||||
|
||||
return new File(parentPath, childPath).getAbsolutePath();
|
||||
}
|
||||
|
||||
//---------------------------------搜索文件--------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user