// Copyright 2008-2018 Yolo Technologies, Inc. All Rights Reserved. https://www.comblockengine.com



#include "kbcmd.h"

#include "client_sdk.h"

#include "client_sdk_ue5.h"

#include "entitydef/entitydef.h"

#include "entitydef/scriptdef_module.h"

#include "entitydef/property.h"

#include "entitydef/method.h"

#include "entitydef/datatype.h"

#include "network/fixed_messages.h"



namespace KBEngine {	



static std::string headerBody = "/*\n\tGenerated by KBEngine!\n\tPlease do not modify this file!\n#REPLACE#\ttools = kbcmd\n*/\n\n";

static std::string moduleSuffix = "Base";

static std::string ConflictTypePrefix = "KBE_";

static std::string namespaceNameBegin = "namespace KBEngine\n{\n\n";

static std::string namespaceNameEnd   = "\n}";



//-------------------------------------------------------------------------------------

ClientSDKUE5::ClientSDKUE5():

	ClientSDK(),

	initBody_(),

	contextHeader_(true)

{

}



//-------------------------------------------------------------------------------------

ClientSDKUE5::~ClientSDKUE5()

{



}



//-------------------------------------------------------------------------------------

std::string ClientSDKUE5::typeToType(const std::string& type)

{

	if (type == "INT8")

	{

		return "int8";

	}

	else if (type == "INT16")

	{

		return "int16";

	}

	else if (type == "INT32")

	{

		return "int32";

	}

	else if (type == "INT64")

	{

		return "int64";

	}

	else if (type == "UINT8")

	{

		return "uint8";

	}

	else if (type == "UINT16")

	{

		return "uint16";

	}

	else if (type == "UINT32")

	{

		return "uint32";

	}

	else if (type == "UINT64")

	{

		return "uint64";

	}

	else if (type == "FLOAT")

	{

		return "float";

	}

	else if (type == "DOUBLE")

	{

		return "double";

	}

	else if (type == "STRING")

	{

		return "FString";

	}

	else if (type == "UNICODE" || type == fmt::format("{}UNICODE", ConflictTypePrefix))

	{

		return "FString";

	}

	else if (type == "PYTHON")

	{

		return "TArray<uint8>";

	}

	else if (type == "PY_DICT")

	{

		return "TArray<uint8>";

	}

	else if (type == "PY_TUPLE")

	{

		return "TArray<uint8>";

	}

	else if (type == "PY_LIST")

	{

		return "TArray<uint8>";

	}

	else if (type == "BLOB")

	{

		return "TArray<uint8>";

	}

	else if (type == "ARRAY")

	{

		return "TArray";

	}

	else if (type == "FIXED_DICT")

	{

		return "TMap";

	}

#ifdef CLIENT_NO_FLOAT

	else if (type == "VECTOR2")

	{

		return "FVector2D";

	}

	else if (type == "VECTOR3")

	{

		return "FVector3f";

	}

	else if (type == "VECTOR4")

	{

		return "FVector4";

	}

#else

	else if (type == "VECTOR2")

	{

		return "FVector2D";

	}

	else if (type == "VECTOR3")

	{

		return "FVector3f";

	}

	else if (type == "VECTOR4")

	{

		return "FVector4";

	}

#endif

	else if (type == "ENTITYCALL")

	{

		return "TArray<uint8>";

	}



	return type;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::getArrayType(DataType* pDataType, std::string& outstr)

{

	if (pDataType->type() == DATA_TYPE_FIXEDARRAY)

	{

		FixedArrayType* pFixedArrayType = static_cast<FixedArrayType*>(pDataType);



		// 如果元素又是数组

		if (pFixedArrayType->getDataType()->type() == DATA_TYPE_FIXEDARRAY)

		{

			if (outstr.size() > 0)

				strutil::kbe_replace(outstr, pDataType->aliasName(), fmt::format("TArray<{}>", pFixedArrayType->getDataType()->aliasName()));

			else

				outstr = fmt::format("TArray<{}>", pFixedArrayType->getDataType()->aliasName());



			return getArrayType(pFixedArrayType->getDataType(), outstr);

		}

		else if (pFixedArrayType->getDataType()->type() == DATA_TYPE_FIXEDDICT)

		{

			if (outstr.size() > 0)

				strutil::kbe_replace(outstr, pDataType->aliasName(), pFixedArrayType->getDataType()->aliasName());

			else

				outstr = pFixedArrayType->getDataType()->aliasName();

		}

		else

		{

			if (outstr.size() > 0)

				strutil::kbe_replace(outstr, pDataType->aliasName(), typeToType(pFixedArrayType->getDataType()->getName()));

			else

				outstr = typeToType(pFixedArrayType->getDataType()->getName());

		}

	}



	outstr = fmt::format("TArray<{}>", outstr);

	return true;

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateTypeFileName()

{

	sourcefileName_ = "";

	headerfileName_ = "KBETypes.h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateEntityModuleFileName(const std::string& moduleName)

{

	sourcefileName_ = moduleName + moduleSuffix + ".cpp";

	headerfileName_ = moduleName + moduleSuffix + ".h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateServerErrorDescrsModuleFileName()

{

	sourcefileName_ = "";

	headerfileName_ = "ServerErrorDescrs.h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateEngineMessagesModuleFileName()

{

	sourcefileName_ = "Messages.cpp";

	headerfileName_ = "Messages.h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateDefsCustomTypesModuleFileName()

{

	sourcefileName_ = "CustomDataTypes.cpp";

	headerfileName_ = "CustomDataTypes.h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onCreateEntityDefsModuleFileName()

{

	sourcefileName_ = "EntityDef.cpp";

	headerfileName_ = "EntityDef.h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

void ClientSDKUE5::onEntityCallModuleFileName(const std::string& moduleName)

{

	sourcefileName_ = std::string("EntityCall") + moduleName + moduleSuffix + ".cpp";

	headerfileName_ = std::string("EntityCall") + moduleName + moduleSuffix + ".h";



	currHeaderPath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";

	currSourcePath_ = basepath_ + "Source/KBEnginePlugins/Public/Engine/";



	changeContextToHeader();

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeServerErrorDescrsModuleBegin()

{

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", "");



	fileBody() += "#pragma once\n\n";

	fileBody() += "#include \"KBECommon.h\"\n\n";



	fileBody() += namespaceNameBegin;

	fileBody() += "// defined in */res/server/server_errors.xml\n\n";

	fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:\n", "ServerErrorDescrs");



	fileBody() += "\tServerErrorDescrs():\n\tserverErrs_()\n\t{\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeServerErrorDescrsModuleErrDescr(int errorID, const std::string& errname, const std::string& errdescr)

{

	fileBody() += fmt::format("\t\t{{\n\t\t\tFKServerErr e;\n\t\t\te.id = {};\n\t\t\te.name = TEXT(\"{}\");\n\t\t\te.descr = TEXT(\"{}\");\n\n\t\t\tserverErrs_.Add(e.id, e);\n", errorID, errname, errdescr);

	fileBody() += "\t\t}\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeServerErrorDescrsModuleEnd()

{

	fileBody() += "\t}\n\n";



	fileBody() += "\tvoid Clear()\n\t{\n\t\tserverErrs_.Empty();\n\t}\n\n";



	fileBody() += "\tFString ServerErrStr(uint16 id)\n\t{\n\t\tFKServerErr e = serverErrs_.FindRef(id);\n\t\treturn FString::Printf(TEXT(\"%s[%s]\"), *e.name, *e.descr);\n\t}\n\n";

	fileBody() += "\tFKServerErr ServerErr(uint16 id)\n\t{\n\t\treturn serverErrs_.FindRef(id);\n\t}\n\n";



	fileBody() += "\tprotected:\n\t\tTMap<uint16, FKServerErr> serverErrs_;";

	fileBody() += "\n};\n";

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEngineMessagesModuleBegin()

{

	changeContextToHeader();



	initBody_ = "";

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", "");



	fileBody() += "#pragma once\n\n";

	fileBody() += "#include \"KBECommon.h\"\n";

	fileBody() += "#include \"MemoryStream.h\"\n\n";



	fileBody() += "// engine-c++ messages\n\n";

	fileBody() += namespaceNameBegin;

	fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:", "Message");



	fileBody() += "\n\tMessage()\n\t{\n";

	fileBody() += "\t\tid = 0;\n";

	fileBody() += "\t\tname = TEXT(\"\");\n";

	fileBody() += "\t\tmsglen = -1;\n";

	fileBody() += "\t\targsType = 0;\n\n";

	 

	fileBody() += "\t\targtypes = TArray<uint8>();";



	fileBody() += "\n\t}\n\n";



	fileBody() += "\n\tMessage(MessageID msgid, const FString& msgname, int16 length, int8 argstype, const TArray<uint8>& msgargtypes)\n\t{\n";

	fileBody() += "\t\tid = msgid;\n";

	fileBody() += "\t\tname = msgname;\n";

	fileBody() += "\t\tmsglen = length;\n";

	fileBody() += "\t\targsType = argstype;\n\n";



	fileBody() += "\t\targtypes = msgargtypes;\n\n";



	fileBody() += "\t\t// DEBUG_MSG(\"Message::Message() : (%s / %d / %d)!\", \n";

	fileBody() += "\t\t//\t\tmsgname, (int32)msgid, (int32)msglen));";



	fileBody() += "\n\t}\n\n";



	fileBody() += "\tvirtual ~Message()\n";

	fileBody() += "\t{\n";

	fileBody() += "\t}\n\n";



	fileBody() += "\tvirtual void handleMessage(MemoryStream& msgstream)\n";

	fileBody() += "\t{\n";

	fileBody() += "\t}\n\n";



	fileBody() += "public:\n";

	fileBody() += "\tMessageID id;\n";

	fileBody() += "\tFString name;\n";

	fileBody() += "\tint16 msglen;\n";

	fileBody() += "\tTArray<uint8> argtypes;\n";

	fileBody() += "\tint8 argsType;\n";



	fileBody() += "};\n\n";



	changeContextToSource();



	fileBody() += "#include \"Messages.h\"\n";

	fileBody() += "#include \"MemoryStream.h\"\n";

	fileBody() += "#include \"KBEngine.h\"\n\n";



	fileBody() += namespaceNameBegin;

	

	fileBody() += "TMap<MessageID, Message*> Messages::loginappMessages;\n";

	fileBody() += "TMap<MessageID, Message*> Messages::baseappMessages;\n";

	fileBody() += "TMap<MessageID, Message*> Messages::clientMessages;\n";

	fileBody() += "TMap<FString, Message*> Messages::messages;\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEngineMessagesModuleMessage(Network::ExposedMessageInfo& messageInfos, COMPONENT_TYPE componentType)

{

	changeContextToHeader();



	fileBody() += fmt::format("class KBENGINEPLUGINS_API Message_{} : public Message\n{{\npublic:\n", messageInfos.name);



	fileBody() += fmt::format("\tMessage_{}(MessageID msgid, const FString& msgname, int16 length, int8 argstype, const TArray<uint8>& msgargtypes):\n\tMessage(msgid, msgname, length, argstype, msgargtypes)\n\t{{\n", messageInfos.name);

	fileBody() += "\n\t}\n\n";



	fileBody() += "\tvoid handleMessage(MemoryStream& msgstream) override;\n";



	changeContextToSource();



	fileBody() += fmt::format("void Message_{}::handleMessage(MemoryStream& msgstream)\n", messageInfos.name);

	fileBody() += "{\n";



	if (messageInfos.argsTypes.size() == 0)

	{

		initBody_ += fmt::format("\t\tMessages::messages.Add(TEXT(\"{}\"), new Message_{}({}, \"{}\", {}, {}, ",

			messageInfos.name, messageInfos.name, messageInfos.id, messageInfos.name, messageInfos.msgLen, (int)messageInfos.argsType);



		initBody_ += "TArray<uint8>()));\n";



		if (componentType == CLIENT_TYPE)

		{

			if (messageInfos.argsType < 0)

			{

				fileBody() += fmt::format("\tKBEngineApp::getSingleton().{}(msgstream);\n", messageInfos.name);

			}

			else

			{

				fileBody() += fmt::format("\tKBEngineApp::getSingleton().{}();\n", messageInfos.name);

			}

		}

	}

	else

	{

		std::string argsparse = "";

		std::string giveargs = "";

		initBody_ += fmt::format("\n\t\tTArray<uint8> {}_argstypes;\n", messageInfos.name);



		for (size_t i = 0; i < messageInfos.argsTypes.size(); ++i)
		{
			int argindex = static_cast<int>(i + 1);
			std::string nativetype = datatype2nativetype(messageInfos.argsTypes[i]);



			KBE_ASSERT(nativetype != "FIXED_DICT" && nativetype != "ARRAY" && nativetype != "PYTHON" && nativetype != "ENTITYCALL");



			std::string readName = nativetype;

			std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

			readName[0] = std::toupper(readName[0]);



			argsparse += fmt::format("\t{} arg{} = msgstream.read{}();\n", typeToType(nativetype), argindex, readName);

			giveargs += fmt::format("arg{}, ", argindex);

			initBody_ += fmt::format("\t\t{}_argstypes.Add({});\n", messageInfos.name, (int)messageInfos.argsTypes[i]);

		}



		if (giveargs.size() > 0)

			giveargs.erase(giveargs.size() - 2, 2);



		initBody_ += fmt::format("\t\tMessages::messages.Add(TEXT(\"{}\"), new Message_{}({}, \"{}\", {}, {}, {}_argstypes));\n",

			messageInfos.name, messageInfos.name, messageInfos.id, messageInfos.name, messageInfos.msgLen, (int)messageInfos.argsType, messageInfos.name);



		if (componentType == CLIENT_TYPE)

		{

			fileBody() += argsparse;

			fileBody() += fmt::format("\tKBEngineApp::getSingleton().{}({});\n", messageInfos.name, giveargs);

		}

	}



	if (componentType == CLIENT_TYPE)

	{

		initBody_ += fmt::format("\t\tMessages::clientMessages.Add({}, Messages::messages[\"{}\"]);\n\n", messageInfos.id, messageInfos.name);

	}

	else if (componentType == LOGINAPP_TYPE)

	{

		initBody_ += fmt::format("\t\tMessages::loginappMessages.Add({}, Messages::messages[\"{}\"]);\n\n", messageInfos.id, messageInfos.name);

	}

	else if (componentType == BASEAPP_TYPE)

	{

		initBody_ += fmt::format("\t\tMessages::baseappMessages.Add({}, Messages::messages[\"{}\"]);\n\n", messageInfos.id, messageInfos.name);

	}



	fileBody() += "}\n\n";



	changeContextToHeader();

	fileBody() += "};\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEngineMessagesModuleEnd()

{

	changeContextToSource();

	fileBody() += namespaceNameEnd;

	changeContextToHeader();



	fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:\n", "Messages");



	fileBody() += "\tstatic TMap<MessageID, Message*> loginappMessages;\n";

	fileBody() += "\tstatic TMap<MessageID, Message*> baseappMessages;\n";

	fileBody() += "\tstatic TMap<MessageID, Message*> clientMessages;\n";

	fileBody() += "\tstatic TMap<FString, Message*> messages;\n";



	fileBody() += "\n\tstatic Message* findClientMessage(MessageID mid)\n\t{\n";

	fileBody() += "\t\treturn clientMessages.FindRef(mid);";

	fileBody() += "\n\t}\n";



	fileBody() += "\n\tstatic Message* findMessage(const FString& mname)\n\t{\n";

	fileBody() += "\t\treturn messages.FindRef(mname);";

	fileBody() += "\n\t}\n";



	fileBody() += "\n\tstatic void clear()\n\t{\n";



	fileBody() += "\t\tloginappMessages.Empty();\n";

	fileBody() += "\t\tbaseappMessages.Empty();\n";

	fileBody() += "\t\tclientMessages.Empty();\n\n";

	fileBody() += "\t\tfor (auto item : messages)\n";

	fileBody() += "\t\t\tdelete item.Value;\n\n";

	fileBody() += "\t\tmessages.Empty();\n";

	fileBody() += "\n\t\tinitialize();";



	fileBody() += "\n\t}\n";



	fileBody() += "\n\tstatic bool initialize()\n\t{\n";



	fileBody() += initBody_;



	fileBody() += "\n\t\treturn true;";

	fileBody() += "\n\t}";

	fileBody() += "\n}\n;";

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleBegin()

{

	changeContextToHeader();



	initBody_ = "";

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", "");



	fileBody() += "#pragma once\n\n";

	fileBody() += "#include \"KBECommon.h\"\n\n";



	fileBody() += namespaceNameBegin;

	fileBody() += "class Entity;\n";

	fileBody() += "class DATATYPE_BASE;\n";

	fileBody() += "class ScriptModule;\n\n";



	fileBody() += "// Manage descriptions of all entities\n\n";

	fileBody() += fmt::format("class KBENGINEPLUGINS_API {}\n{{\npublic:\n", "EntityDef");



	fileBody() += "\tstatic TMap<FString, uint16> datatype2id;\n";

	fileBody() += "\tstatic TMap<FString, DATATYPE_BASE*> datatypes;\n";

	fileBody() += "\tstatic TMap<uint16, DATATYPE_BASE*> id2datatypes;\n";

	fileBody() += "\tstatic TMap<FString, int32> entityclass;\n";

	fileBody() += "\tstatic TMap<FString, ScriptModule*> moduledefs;\n";

	fileBody() += "\tstatic TMap<uint16, ScriptModule*> idmoduledefs;\n\n";



	fileBody() += "\tstatic bool initialize();\n";

	fileBody() += "\tstatic bool reset();\n";

	fileBody() += "\tstatic void clear();\n";

	fileBody() += "\tstatic void initDataTypes();\n";

	fileBody() += "\tstatic void initScriptModules();\n";

	fileBody() += "\tstatic void initDefTypes();\n";

	fileBody() += "\tstatic Entity* createEntity(int utype);\n";



	changeContextToSource();

	

	fileBody() += "#include \"EntityDef.h\"\n";

	fileBody() += "#include \"DataTypes.h\"\n";

	fileBody() += "#include \"CustomDataTypes.h\"\n";

	fileBody() += "#include \"ScriptModule.h\"\n";

	fileBody() += "#include \"Property.h\"\n";

	fileBody() += "#include \"Method.h\"\n";

	fileBody() += "#include \"KBVar.h\"\n";

	fileBody() += "#include \"Entity.h\"\n\n";



	int numEntity = 0;

	const EntityDef::SCRIPT_MODULES& modules = EntityDef::getScriptModules();

	EntityDef::SCRIPT_MODULES::const_iterator iter = modules.begin();

	for (; iter != modules.end(); ++iter)

	{

		if (!iter->get()->hasClient())

			continue;



		++numEntity;



		if(iter->get()->isComponentModule())

			fileBody() += fmt::format("#include \"../Scripts/Components/{}.h\"\n", iter->get()->getName());

		else

			fileBody() += fmt::format("#include \"../Scripts/{}.h\"\n", iter->get()->getName());

	}



	fileBody() += "\n";

	fileBody() += namespaceNameBegin;

	fileBody() += "TMap<FString, uint16> EntityDef::datatype2id;\n";

	fileBody() += "TMap<FString, DATATYPE_BASE*> EntityDef::datatypes;\n";

	fileBody() += "TMap<uint16, DATATYPE_BASE*> EntityDef::id2datatypes;\n";

	fileBody() += "TMap<FString, int32> EntityDef::entityclass;\n";

	fileBody() += "TMap<FString, ScriptModule*> EntityDef::moduledefs;\n";

	fileBody() += "TMap<uint16, ScriptModule*> EntityDef::idmoduledefs;\n\n";



	fileBody() += "bool EntityDef::initialize()\n{\n";

	fileBody() += "\tinitDataTypes();\n";

	fileBody() += "\tinitDefTypes();\n";

	fileBody() += "\tinitScriptModules();\n";

	fileBody() += "\treturn true;\n";

	fileBody() += "}\n\n";



	fileBody() += "bool EntityDef::reset()\n{\n";

	fileBody() += "\tclear();\n";

	fileBody() += "\treturn initialize();\n";

	fileBody() += "}\n\n";



	fileBody() += "void EntityDef::clear()\n";

	fileBody() += "{\n";

	fileBody() += "\tTArray<DATATYPE_BASE*> deleted_datatypes;\n";

	fileBody() += "\tfor (auto& item : EntityDef::datatypes)\n";

	fileBody() += "\t{\n";

	fileBody() += "\t\tint32 idx = deleted_datatypes.Find(item.Value);\n";

	fileBody() += "\t\tif (idx != INDEX_NONE)\n";

	fileBody() += "\t\t\tcontinue;\n";

	fileBody() += "\n";

	fileBody() += "\t\tdeleted_datatypes.Add(item.Value);\n";

	fileBody() += "\t\tdelete item.Value;\n";

	fileBody() += "\t}\n";

	fileBody() += "\n";

	fileBody() += "\tfor (auto& item : EntityDef::moduledefs)\n";

	fileBody() += "\t\tdelete item.Value;\n\n";

	fileBody() += "\tdatatype2id.Empty();\n";

	fileBody() += "\tdatatypes.Empty();\n";

	fileBody() += "\tid2datatypes.Empty();\n";

	fileBody() += "\tentityclass.Empty();\n";

	fileBody() += "\tmoduledefs.Empty();\n";

	fileBody() += "\tidmoduledefs.Empty();\n";

	fileBody() += "}\n\n";



	fileBody() += "void EntityDef::initDataTypes()\n";

	fileBody() += "{\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"UINT8\"), new DATATYPE_UINT8());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"UINT16\"), new DATATYPE_UINT16());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"UINT32\"), new DATATYPE_UINT32());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"UINT64\"), new DATATYPE_UINT64());\n\n";



	fileBody() += "\tdatatypes.Add(TEXT(\"INT8\"), new DATATYPE_INT8());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"INT16\"), new DATATYPE_INT16());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"INT32\"), new DATATYPE_INT32());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"INT64\"), new DATATYPE_INT64());\n\n";



	fileBody() += "\tdatatypes.Add(TEXT(\"FLOAT\"), new DATATYPE_FLOAT());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"DOUBLE\"), new DATATYPE_DOUBLE());\n\n";



	fileBody() += "\tdatatypes.Add(TEXT(\"STRING\"), new DATATYPE_STRING());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"VECTOR2\"), new DATATYPE_VECTOR2());\n\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"VECTOR3\"), new DATATYPE_VECTOR3());\n\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"VECTOR4\"), new DATATYPE_VECTOR4());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"PYTHON\"), new DATATYPE_PYTHON());\n\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"UNICODE\"), new DATATYPE_UNICODE());\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"ENTITYCALL\"), new DATATYPE_ENTITYCALL());\n\n";

	fileBody() += "\tdatatypes.Add(TEXT(\"BLOB\"), new DATATYPE_BLOB());\n";

	fileBody() += "}\n\n";



	fileBody() += "Entity* EntityDef::createEntity(int utype)\n";

	fileBody() += "{\n\tEntity* pEntity = NULL;\n\n";



	if (numEntity > 0)

	{

		fileBody() += "\tswitch(utype)\n\t{\n";



		iter = modules.begin();

		for (; iter != modules.end(); ++iter)

		{

			if (!iter->get()->hasClient() || iter->get()->isComponentModule())

				continue;



			fileBody() += fmt::format("\t\tcase {}:\n", iter->get()->getUType());

			fileBody() += fmt::format("\t\t\tpEntity = new {}();\n\t\t\tbreak;\n", iter->get()->getName());

		}



		fileBody() += "\t\tdefault:\n\t\t\tSCREEN_ERROR_MSG(\"EntityDef::createEntity() : entity(%d) not found!\", utype);\n\t\t\tbreak;\n\t};\n\n";

	}



	fileBody() += "\treturn pEntity;\n}\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleEnd()

{

	changeContextToSource();

	fileBody() += namespaceNameEnd;

	changeContextToHeader();

	fileBody() += "};\n";

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitScriptBegin()

{

	changeContextToSource();

	fileBody() += "void EntityDef::initScriptModules()\n";

	fileBody() += "{\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitScriptEnd()

{

	changeContextToSource();

	fileBody() += "}\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitDefTypesBegin()

{

	changeContextToSource();

	fileBody() += "void EntityDef::initDefTypes()\n";

	fileBody() += "{\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitDefTypesEnd()

{

	changeContextToSource();

	fileBody() += "\tfor(auto& Elem : EntityDef::datatypes)\n\t{\n";

	fileBody() += "\t\tif(Elem.Value)\n\t\t{\n";

	fileBody() += "\t\t\tElem.Value->bind();\n\t\t}\n\t}\n";



	fileBody() += "}\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitDefType(const DataType* pDataType)

{

	changeContextToSource();



	uint16 typeID = datatype2id(pDataType->getName());

	if (typeID == 0 || strcmp(pDataType->getName(), "FIXED_DICT") == 0 || strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		typeID = pDataType->id();

		KBE_ASSERT(typeID > datatype2id("KBE_DATATYPE2ID_MAX"));

	}



	static std::map< int, std::string > type2name;



	fileBody() += fmt::format("\t{{\n");

	fileBody() += fmt::format("\t\tuint16 utype = {};\n", typeID);



	std::string typeName = (strlen(pDataType->aliasName()) > 0 ? pDataType->aliasName() : fmt::format("AnonymousArray_{}", typeID));

	fileBody() += fmt::format("\t\tFString typeName = TEXT(\"{}\");\n", typeName);



	std::map< int, std::string >::iterator iter = type2name.find(typeID);

	if (iter == type2name.end())

		type2name[typeID] = (strlen(pDataType->getName()) > 0 ? pDataType->getName() : typeName);



	if (strcmp(pDataType->getName(), "FIXED_DICT") == 0)

	{

		fileBody() += fmt::format("\t\tDATATYPE_{}* pDatatype = new DATATYPE_{}();\n", typeName, typeName);

		fileBody() += fmt::format("\t\tEntityDef::datatypes.Add(typeName, (DATATYPE_BASE*)pDatatype);\n");

	}

	else if (strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		FixedArrayType* pFixedArrayType = const_cast<FixedArrayType*>(static_cast<const FixedArrayType*>(pDataType));

		typeID = datatype2id(pFixedArrayType->getDataType()->getName());



		if (typeID == 0 || strcmp(pFixedArrayType->getDataType()->getName(), "FIXED_DICT") == 0 ||

			strcmp(pFixedArrayType->getDataType()->getName(), "ARRAY") == 0)

			typeID = pFixedArrayType->getDataType()->id();



		fileBody() += fmt::format("\t\tDATATYPE_{}* pDatatype = new DATATYPE_{}();\n", typeName, typeName);

		fileBody() += fmt::format("\t\tEntityDef::datatypes.Add(typeName, (DATATYPE_BASE*)pDatatype);\n");

	}

	else

	{

		fileBody() += fmt::format("\t\tFString name = TEXT(\"{}\");\n", pDataType->getName());

		fileBody() += fmt::format("\t\tDATATYPE_BASE** fPtr = EntityDef::datatypes.Find(name);\n");

		fileBody() += fmt::format("\t\tDATATYPE_BASE* pVal = fPtr != NULL ? *fPtr : NULL;\n");

		fileBody() += fmt::format("\t\tEntityDef::datatypes.Add(typeName, pVal);\n");

	}



	fileBody() += fmt::format("\t\tEntityDef::id2datatypes.Add(utype, EntityDef::datatypes[typeName]);\n");

	fileBody() += fmt::format("\t\tEntityDef::datatype2id.Add(typeName, utype);\n");

	fileBody() += fmt::format("\t}}\n\n");



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityCallBegin(ScriptDefModule* pScriptDefModule)

{

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", fmt::format("\t\n",

		fileBody()));



	fileBody() += "#pragma once\n\n";

	fileBody() += "#include \"KBECommon.h\"\n";

	fileBody() += "#include \"EntityCall.h\"\n";

	fileBody() += fmt::format("#include \"KBETypes.h\"\n");

	fileBody() += fmt::format("#include \"CustomDataTypes.h\"\n\n");



	{

		std::map<std::string, PropertyDescription*> includesHistroy;

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			if (includesHistroy.find(pEntityComponentType->pScriptDefModule()->getName()) != includesHistroy.end())

				continue;



			fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pEntityComponentType->pScriptDefModule()->getName() + moduleSuffix));

			includesHistroy[pEntityComponentType->pScriptDefModule()->getName()] = pPropertyDescription;

		}

	}



	fileBody() += std::string("\n// defined in ") + pScriptDefModule->getDefSourceFile() + "\n\n";
	fileBody() += namespaceNameBegin;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityCallEnd(ScriptDefModule* pScriptDefModule)

{

	changeContextToSource();

	fileBody() += namespaceNameEnd;

	changeContextToHeader();

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityCallMethodBegin(ScriptDefModule* pScriptDefModule, MethodDescription* pMethodDescription, const char* fillString1, const char* fillString2, COMPONENT_TYPE componentType)

{

	std::string newModuleName;



	if(componentType == BASEAPP_TYPE)

		newModuleName = std::string("EntityBaseEntityCall_") + std::string(pScriptDefModule->getName()) + moduleSuffix;

	else

		newModuleName = std::string("EntityCellEntityCall_") + std::string(pScriptDefModule->getName()) + moduleSuffix;



	changeContextToHeader();



	fileBody() += fmt::format("\tvoid {}({});\n", pMethodDescription->getName(), fillString1);



	changeContextToSource();

	fileBody() += fmt::format("void {}::{}({})\n{{\n", newModuleName, pMethodDescription->getName(), fillString1);



	fileBody() += fmt::format("\tBundle* pBundleRet = newCall(\"{}\", {});\n", pMethodDescription->getName(), (pScriptDefModule->isComponentModule() ? "entityComponentPropertyID" : "0"));;

	fileBody() += fmt::format("\tif(!pBundleRet)\n");

	fileBody() += fmt::format("\t\treturn;\n\n");



	std::vector<DataType*>& argTypes = pMethodDescription->getArgTypes();

	std::vector<DataType*>::iterator iter = argTypes.begin();



	std::string writeName;



	int i = 1;



	for (; iter != argTypes.end(); ++iter)

	{

		DataType* pDataType = (*iter);



		if (pDataType->type() == DATA_TYPE_FIXEDDICT)

		{

			writeName = fmt::format("((DATATYPE_{}*)EntityDef::id2datatypes[{}])->addToStreamEx(*pBundleRet, arg{})",

				pDataType->aliasName(), pDataType->id(), i);

		}

		else if (pDataType->type() == DATA_TYPE_FIXEDARRAY)

		{

			if (strlen(pDataType->aliasName()) > 0)

			{

				writeName = fmt::format("((DATATYPE_{}*)EntityDef::id2datatypes[{}])->addToStreamEx(*pBundleRet, arg{})",

					pDataType->aliasName(), pDataType->id(), i);

			}

			else

			{

				writeName = fmt::format("((DATATYPE_AnonymousArray_{}*)EntityDef::id2datatypes[{}])->addToStreamEx(*pBundleRet, arg{})",

					pDataType->id(), pDataType->id(), i);

			}

		}

		else

		{

			writeName = datatype2nativetype(pDataType->getName());

			std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

			writeName[0] = std::toupper(writeName[0]);



			writeName = fmt::format("pBundleRet->write{}(arg{})", writeName, i);

		}



		fileBody() += fmt::format("\t{};\n", writeName);



		i++;

	}



	fileBody() += fmt::format("\tsendCall(NULL);\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityCallMethodEnd(ScriptDefModule* pScriptDefModule, MethodDescription* pMethodDescription)

{

	changeContextToSource();

	fileBody() += fmt::format("}}\n\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeBaseEntityCallBegin(ScriptDefModule* pScriptDefModule)

{

	changeContextToHeader();

	std::string newModuleName;



	newModuleName = std::string("EntityBaseEntityCall_") + std::string(pScriptDefModule->getName()) + moduleSuffix;

	fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public EntityCall\n{{\npublic:\n", newModuleName);



	if (!pScriptDefModule->isComponentModule())

	{

		std::string initstr = "";



		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			fileBody() += fmt::format("\tEntityBaseEntityCall_{}{}* {};\n",

				pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix, pPropertyDescription->getName());



			initstr += fmt::format("\t{} = new EntityBaseEntityCall_{}{}({}, id);\n",

				pPropertyDescription->getName(), pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix, pPropertyDescription->getUType());

		}



		changeContextToHeader();

		fileBody() += fmt::format("\n\t{}(int32 eid, const FString& ename);\n", newModuleName);

		fileBody() += fmt::format("\n\tvirtual ~{}();\n", newModuleName);



		changeContextToSource();



		fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pScriptDefModule->getName() + moduleSuffix));

		fileBody() += fmt::format("#include \"Bundle.h\"\n\n");



		fileBody() += namespaceNameBegin;

		fileBody() += fmt::format("{}::{}(int32 eid, const FString& ename) : EntityCall(eid, ename)\n{{\n", newModuleName, newModuleName);

		fileBody() += initstr;

	}

	else

	{

		fileBody() += fmt::format("\tuint16 entityComponentPropertyID;\n");



		changeContextToHeader();

		fileBody() += fmt::format("\n\t{}(uint16 ecpID, int32 eid);\n", newModuleName);

		fileBody() += fmt::format("\n\tvirtual ~{}();\n", newModuleName);



		changeContextToSource();



		fileBody() += fmt::format("#include \"{}.h\"\n", (std::string("EntityCall") + pScriptDefModule->getName() + moduleSuffix));

		fileBody() += fmt::format("#include \"Bundle.h\"\n\n");

		fileBody() += namespaceNameBegin;

		fileBody() += fmt::format("{}::{}(uint16 ecpID, int32 eid) : \nEntityCall(eid, \"{}\"),\nentityComponentPropertyID(0)\n{{\n", newModuleName, newModuleName, pScriptDefModule->getName());

		fileBody() += fmt::format("\tentityComponentPropertyID = ecpID;\n");

	}



	changeContextToSource();

	fileBody() += fmt::format("\ttype = ENTITYCALL_TYPE_BASE;\n");

	fileBody() += fmt::format("}}\n");



	fileBody() += fmt::format("\n{}::~{}()\n{{\n", newModuleName, newModuleName);

	if (!pScriptDefModule->isComponentModule())

	{

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			//EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			fileBody() += fmt::format("\tif({})\n\t\tdelete {};\n\n", pPropertyDescription->getName(), pPropertyDescription->getName());

		}

	}



	fileBody() += fmt::format("}}\n\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeBaseEntityCallEnd(ScriptDefModule* pScriptDefModule)

{

	changeContextToHeader();

	fileBody() += fmt::format("}};\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeCellEntityCallBegin(ScriptDefModule* pScriptDefModule)

{

	changeContextToHeader();

	std::string newModuleName;



	newModuleName = std::string("EntityCellEntityCall_") + std::string(pScriptDefModule->getName()) + moduleSuffix;

	fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public EntityCall\n{{\npublic:\n", newModuleName);



	if (!pScriptDefModule->isComponentModule())

	{

		std::string initstr = "";



		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			fileBody() += fmt::format("\tEntityCellEntityCall_{}{}* {};\n",

				pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix, pPropertyDescription->getName());



			initstr += fmt::format("\t{} = new EntityCellEntityCall_{}{}({}, id);\n",

				pPropertyDescription->getName(), pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix, pPropertyDescription->getUType());

		}



		changeContextToHeader();

		fileBody() += fmt::format("\n\t{}(int32 eid, const FString& ename);\n", newModuleName);

		fileBody() += fmt::format("\n\tvirtual ~{}();\n", newModuleName);



		changeContextToSource();

		fileBody() += fmt::format("\n{}::{}(int32 eid, const FString& ename) : EntityCall(eid, ename)\n{{\n", newModuleName, newModuleName);

		fileBody() += initstr;

	}

	else

	{

		fileBody() += fmt::format("\tuint16 entityComponentPropertyID;\n");



		changeContextToHeader();

		fileBody() += fmt::format("\n\t{}(uint16 ecpID, int32 eid);\n", newModuleName);

		fileBody() += fmt::format("\n\tvirtual ~{}();\n", newModuleName);



		changeContextToSource();

		fileBody() += fmt::format("\n{}::{}(uint16 ecpID, int32 eid) : \nEntityCall(eid, \"{}\"),\nentityComponentPropertyID(0)\n{{\n", newModuleName, newModuleName, pScriptDefModule->getName());

		fileBody() += fmt::format("\tentityComponentPropertyID = ecpID;\n");

	}



	changeContextToSource();

	fileBody() += fmt::format("\ttype = ENTITYCALL_TYPE_CELL;\n");

	fileBody() += fmt::format("}}\n");



	fileBody() += fmt::format("\n{}::~{}()\n{{\n", newModuleName, newModuleName);

	if (!pScriptDefModule->isComponentModule())

	{

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			//EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			fileBody() += fmt::format("\tif({})\n\t\tdelete {};\n\n", pPropertyDescription->getName(), pPropertyDescription->getName());

		}

	}



	fileBody() += fmt::format("}}\n\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeCellEntityCallEnd(ScriptDefModule* pScriptDefModule)

{

	changeContextToHeader();

	fileBody() += fmt::format("}};\n");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeCustomDataTypesBegin()

{

	changeContextToHeader();



	initBody_ = "";

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", "");



	fileBody() += "#pragma once\n";

	fileBody() += "#include \"KBECommon.h\"\n";

	fileBody() += "#include \"KBETypes.h\"\n";

	fileBody() += "#include \"MemoryStream.h\"\n";

	fileBody() += "#include \"Bundle.h\"\n";

	fileBody() += "#include \"DataTypes.h\"\n";

	fileBody() += namespaceNameBegin;



	changeContextToSource();

	fileBody() += "#include \"CustomDataTypes.h\"\n";

	fileBody() += "#include \"EntityDef.h\"\n";

	fileBody() += "#include \"KBDebug.h\"\n";

	fileBody() += "#include \"DataTypes.h\"\n";

	fileBody() += "#include \"Runtime/Core/Public/Misc/Variant.h\"\n\n";

	fileBody() += namespaceNameBegin;



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeCustomDataTypesEnd()

{

	changeContextToSource();

	fileBody() += namespaceNameEnd;

	changeContextToHeader();

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::createArrayChildClass(DataType* pRootDataType, DataType* pDataType, const std::string& className, const std::string& tabs, int numLayer)

{

	changeContextToHeader();



	fileBody() += fmt::format("{}class KBENGINEPLUGINS_API DATATYPE_{} : public DATATYPE_BASE\n{}{{\n{}public:\n", tabs, className, tabs, tabs);



	uint16 typeID = datatype2id(pDataType->getName());

	if (typeID == 0 || strcmp(pDataType->getName(), "FIXED_DICT") == 0 || strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		typeID = pDataType->id();

		KBE_ASSERT(typeID > datatype2id("KBE_DATATYPE2ID_MAX"));

	}



	std::string readName;

	std::string typeName = (strlen(pDataType->aliasName()) > 0 ? pDataType->aliasName() : fmt::format("AnonymousArray_{}", typeID));



	bool isFixedType = strcmp(pDataType->getName(), "FIXED_DICT") == 0 ||

		strcmp(pDataType->getName(), "ARRAY") == 0;



	if (strcmp(pDataType->getName(), "FIXED_DICT") == 0)

	{

		readName = fmt::format("itemType.createFromStreamEx(stream, datas.EmplaceAt_GetRef(datas.Num()))");



		fileBody() += fmt::format("{}\tDATATYPE_{} itemType;\n\n",

			tabs, pDataType->aliasName(), pDataType->aliasName());



		// 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别

		// 否则设置为系统List类别

		if (numLayer == 1)

		{

			if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_')

			{

				typeName = fmt::format("TArray<{}>", typeName);

			}

			else

			{

				typeName = pRootDataType->aliasName();

			}

		}

		else

		{

			typeName = fmt::format("TArray<{}>", typeName);

		}



		fileBody() += fmt::format("{}\tvoid createFromStreamEx(MemoryStream& stream, {}& datas)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tuint32 size = stream.readUint32();\n", tabs);

		fileBody() += fmt::format("{}\t\twhile(size > 0)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);

		fileBody() += fmt::format("{}\t\t\t--size;\n", tabs);

		fileBody() += fmt::format("{}\t\t\t{};\n", tabs, readName);

		fileBody() += fmt::format("{}\t\t}};\n\n", tabs);

		fileBody() += fmt::format("{}\t}}\n\n", tabs);





		fileBody() += fmt::format("{}\tvoid addToStreamEx(Bundle& stream, const {}& v)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tstream.writeUint32((uint32)v.Num());\n", tabs);

		fileBody() += fmt::format("{}\t\tfor(int i=0; i<v.Num(); ++i)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);



		std::string writeName;

		if (isFixedType)

		{

			writeName = fmt::format("itemType.addToStreamEx(stream, v[i])");

		}

		else

		{

			writeName = datatype2nativetype(pDataType->getName());

			std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

			writeName[0] = std::toupper(writeName[0]);

			writeName = fmt::format("stream.write{}(v[i])", writeName);

		}



		fileBody() += fmt::format("{}\t\t\t{};\n", tabs, writeName);

		fileBody() += fmt::format("{}\t\t}};\n", tabs);

		fileBody() += fmt::format("{}\t}}\n", tabs);

	}

	else if (strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		FixedArrayType* pFixedArrayType = static_cast<FixedArrayType*>(pDataType);



		std::string classNameStr = typeName;



		// 如果是非匿名的数组,则第一层解析应该直接设置为有名字的类别

		// 否则设置为系统List类别

		if (numLayer == 1)

		{

			if (strlen(pRootDataType->aliasName()) == 0 || pRootDataType->aliasName()[0] == '_')

			{

				typeName = "";

				getArrayType(pFixedArrayType, typeName);

				typeName = fmt::format("TArray<{}>", typeName);

			}

			else

			{

				typeName = pRootDataType->aliasName();

			}

		}

		else

		{

			typeName = "";

			getArrayType(pFixedArrayType, typeName);

			typeName = fmt::format("TArray<{}>", typeName);

		}



		readName = fmt::format("itemType.createFromStreamEx(stream, datas.EmplaceAt_GetRef(datas.Num()))");



		std::string childClassName = classNameStr + "_ChildArray";



		if (!createArrayChildClass(pRootDataType, pFixedArrayType->getDataType(), childClassName, tabs + "\t", numLayer + 1))

			return false;



		fileBody() += fmt::format("{}\tDATATYPE_{} itemType;\n\n",

			tabs, childClassName, childClassName);



		fileBody() += fmt::format("{}\tvoid createFromStreamEx(MemoryStream& stream, {}& datas)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tuint32 size = stream.readUint32();\n", tabs);

		fileBody() += fmt::format("{}\t\twhile(size > 0)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);

		fileBody() += fmt::format("{}\t\t\t--size;\n", tabs);

		fileBody() += fmt::format("{}\t\t\t{};\n", tabs, readName);

		fileBody() += fmt::format("{}\t\t}};\n\n", tabs);

		fileBody() += fmt::format("{}\t}}\n\n", tabs);





		fileBody() += fmt::format("{}\tvoid addToStreamEx(Bundle& stream, const {}& v)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tstream.writeUint32((uint32)v.Num());\n", tabs);

		fileBody() += fmt::format("{}\t\tfor(int i=0; i<v.Num(); ++i)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);



		std::string writeName;

		if (isFixedType)

		{

			writeName = fmt::format("itemType.addToStreamEx(stream, v[i])", writeName);

		}

		else

		{

			writeName = datatype2nativetype(pDataType->getName());

			std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

			writeName[0] = std::toupper(writeName[0]);

			writeName = fmt::format("stream.write{}(v[i])", writeName);

		}



		fileBody() += fmt::format("{}\t\t\t{};\n", tabs, writeName);

		fileBody() += fmt::format("{}\t\t}};\n", tabs);

		fileBody() += fmt::format("{}\t}}\n", tabs);

	}

	else

	{

		readName = datatype2nativetype(pDataType->getName());

		typeName = typeToType(readName);

		std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

		readName[0] = std::toupper(readName[0]);

		readName = fmt::format("stream.read{}()", readName);



		fileBody() += fmt::format("{}\tvoid createFromStreamEx(MemoryStream& stream, TArray<{}>& datas)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tuint32 size = stream.readUint32();\n", tabs);

		fileBody() += fmt::format("{}\t\twhile(size > 0)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);

		fileBody() += fmt::format("{}\t\t\t--size;\n", tabs);

		fileBody() += fmt::format("{}\t\t\tdatas.Add({});\n", tabs, readName);

		fileBody() += fmt::format("{}\t\t}};\n\n", tabs);

		fileBody() += fmt::format("{}\t}}\n\n", tabs);



		fileBody() += fmt::format("{}\tvoid addToStreamEx(Bundle& stream, const TArray<{}>& v)\n{}\t{{\n", tabs, typeName, tabs);

		fileBody() += fmt::format("{}\t\tstream.writeUint32((uint32)v.Num());\n", tabs);

		fileBody() += fmt::format("{}\t\tfor(int i=0; i<v.Num(); ++i)\n", tabs);

		fileBody() += fmt::format("{}\t\t{{\n", tabs);



		std::string writeName;

		writeName = datatype2nativetype(pDataType->getName());

		std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

		writeName[0] = std::toupper(writeName[0]);

		writeName = fmt::format("stream.write{}(v[i])", writeName);



		fileBody() += fmt::format("{}\t\t\t{};\n", tabs, writeName);

		fileBody() += fmt::format("{}\t\t}};\n", tabs);

		fileBody() += fmt::format("{}\t}}\n", tabs);

	}



	fileBody() += fmt::format("{}}};\n\n", tabs);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeCustomDataType(const DataType* pDataType)

{

	changeContextToHeader();



	uint16 typeID = datatype2id(pDataType->getName());

	if (typeID == 0 || strcmp(pDataType->getName(), "FIXED_DICT") == 0 || strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		typeID = pDataType->id();

		KBE_ASSERT(typeID > datatype2id("KBE_DATATYPE2ID_MAX"));

	}



	static std::map< int, std::string > type2name;



	std::string typeName = (strlen(pDataType->aliasName()) > 0 ? pDataType->aliasName() : fmt::format("AnonymousArray_{}", typeID));



	std::map< int, std::string >::iterator iter = type2name.find(typeID);

	if (iter == type2name.end())

		type2name[typeID] = (strlen(pDataType->getName()) > 0 ? pDataType->getName() : typeName);



	if (strcmp(pDataType->getName(), "FIXED_DICT") == 0)

	{

		fileBody() += fmt::format("\nclass KBENGINEPLUGINS_API DATATYPE_{} : DATATYPE_BASE\n{{\npublic:\n", typeName);

		std::map<std::string, std::string> allClassName;



		FixedDictType* dictdatatype = const_cast<FixedDictType*>(static_cast<const FixedDictType*>(pDataType));



		// 先创建属性

		{

			FixedDictType::FIXEDDICT_KEYTYPE_MAP& keys = dictdatatype->getKeyTypes();

			FixedDictType::FIXEDDICT_KEYTYPE_MAP::const_iterator keyiter = keys.begin();

			for (; keyiter != keys.end(); ++keyiter)

			{

				DataType* pKeyDataType = keyiter->second->dataType;

				if (strcmp(pKeyDataType->getName(), "FIXED_DICT") == 0)

				{

					fileBody() += fmt::format("\tDATATYPE_{} {}_DataType;\n",

						pKeyDataType->aliasName(), keyiter->first, pKeyDataType->aliasName());

				}

				else if (strcmp(pKeyDataType->getName(), "ARRAY") == 0)

				{

					FixedArrayType* pFixedArrayType = const_cast<FixedArrayType*>(static_cast<const FixedArrayType*>(pKeyDataType));



					std::string className = pKeyDataType->aliasName();



					if (strlen(pFixedArrayType->aliasName()) == 0 || pFixedArrayType->aliasName()[0] == '_')

					{

						std::map<std::string, std::string>::iterator findChildClassNameIter = allClassName.find(className + "_ChildArray");



						if (findChildClassNameIter == allClassName.end())

						{

							allClassName[className + "_ChildArray"] = typeName;

							createArrayChildClass(pFixedArrayType, pFixedArrayType->getDataType(), className + "_ChildArray", "\t");

						}



						fileBody() += fmt::format("\tDATATYPE_{} {}_DataType;\n\n",

							className + "_ChildArray", keyiter->first, className + "_ChildArray");

					}

					else

					{

						fileBody() += fmt::format("\tDATATYPE_{} {}_DataType;\n\n",

							className, keyiter->first, className);

					}

				}

				else

				{

				}

			}

		}



		// 创建createFromStreamEx方法

		{

			changeContextToHeader();

			fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::createFromStreamEx(MemoryStream& stream, {}& datas)\n{{\n", typeName, typeName);



			FixedDictType::FIXEDDICT_KEYTYPE_MAP& keys = dictdatatype->getKeyTypes();

			FixedDictType::FIXEDDICT_KEYTYPE_MAP::const_iterator keyiter = keys.begin();

			for (; keyiter != keys.end(); ++keyiter)

			{

				DataType* pKeyDataType = keyiter->second->dataType;

				if (strcmp(pKeyDataType->getName(), "FIXED_DICT") == 0)

				{

					fileBody() += fmt::format("\t{}_DataType.createFromStreamEx(stream, datas.{});\n", keyiter->first, keyiter->first);

				}

				else if (strcmp(pKeyDataType->getName(), "ARRAY") == 0)

				{

					fileBody() += fmt::format("\t{}_DataType.createFromStreamEx(stream, datas.{});\n", keyiter->first, keyiter->first);

				}

				else

				{

					std::string readName = datatype2nativetype(pKeyDataType->getName());

					std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

					readName[0] = std::toupper(readName[0]);

					readName = fmt::format("stream.read{}()", readName);



					fileBody() += fmt::format("\tdatas.{} = {};\n", keyiter->first, readName);

				}

			}



			fileBody() += fmt::format("}}\n\n");

		}



		// 创建addToStreamEx方法

		{

			changeContextToHeader();

			fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::addToStreamEx(Bundle& stream, const {}& v)\n{{\n", typeName, typeName);



			FixedDictType::FIXEDDICT_KEYTYPE_MAP& keys = dictdatatype->getKeyTypes();

			FixedDictType::FIXEDDICT_KEYTYPE_MAP::const_iterator keyiter = keys.begin();

			for (; keyiter != keys.end(); ++keyiter)

			{

				DataType* pKeyDataType = keyiter->second->dataType;

				if (strcmp(pKeyDataType->getName(), "FIXED_DICT") == 0)

				{

					fileBody() += fmt::format("\t{}_DataType.addToStreamEx(stream, v.{});\n", keyiter->first, keyiter->first);

				}

				else if (strcmp(pKeyDataType->getName(), "ARRAY") == 0)

				{

					fileBody() += fmt::format("\t{}_DataType.addToStreamEx(stream, v.{});\n", keyiter->first, keyiter->first);

				}

				else

				{

					std::string writeName = datatype2nativetype(pKeyDataType->getName());

					std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

					writeName[0] = std::toupper(writeName[0]);



					fileBody() += fmt::format("\tstream.write{}(v.{});\n", writeName, keyiter->first);

				}

			}



			fileBody() += fmt::format("}}\n\n");

		}



		changeContextToHeader();

		fileBody() += fmt::format("}};\n\n");



	}

	else if (strcmp(pDataType->getName(), "ARRAY") == 0)

	{

		FixedArrayType* pFixedArrayType = const_cast<FixedArrayType*>(static_cast<const FixedArrayType*>(pDataType));

		typeID = datatype2id(pFixedArrayType->getDataType()->getName());



		if (typeID == 0 || strcmp(pFixedArrayType->getDataType()->getName(), "FIXED_DICT") == 0 ||

			strcmp(pFixedArrayType->getDataType()->getName(), "ARRAY") == 0)

			typeID = pFixedArrayType->getDataType()->id();



		std::string itemTypeName = typeToType(type2name[typeID]);

		if (itemTypeName == "")

		{

			itemTypeName = pFixedArrayType->getDataType()->aliasName();

		}



		std::string className = typeName;



		if (strlen(pFixedArrayType->aliasName()) == 0 || pFixedArrayType->aliasName()[0] == '_')

		{

			typeName = "";

			getArrayType(pFixedArrayType, typeName);

		}



		std::string readName;

		fileBody() += fmt::format("\nclass KBENGINEPLUGINS_API DATATYPE_{} : DATATYPE_BASE\n{{\npublic:\n", className);



		bool isFixedType = strcmp(pFixedArrayType->getDataType()->getName(), "FIXED_DICT") == 0 ||

			strcmp(pFixedArrayType->getDataType()->getName(), "ARRAY") == 0;



		if (strcmp(pFixedArrayType->getDataType()->getName(), "FIXED_DICT") == 0)

		{

			readName = fmt::format("itemType.createFromStreamEx(stream, childDatas)", readName);



			fileBody() += fmt::format("\tDATATYPE_{} itemType;\n\n",

				pFixedArrayType->getDataType()->aliasName(), pFixedArrayType->getDataType()->aliasName());



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::createFromStreamEx(MemoryStream& stream, {}& datas)\n{{\n", className, typeName);

			fileBody() += fmt::format("\tuint32 size = stream.readUint32();\n");

			fileBody() += fmt::format("\twhile(size > 0)\n");

			fileBody() += fmt::format("\t{{\n");

			fileBody() += fmt::format("\t\t--size;\n");

			fileBody() += fmt::format("\t\t{} childDatas;\n", pFixedArrayType->getDataType()->aliasName());

			fileBody() += fmt::format("\t\t{};\n", readName);

			fileBody() += fmt::format("\t\tdatas.Add(childDatas);\n");

			fileBody() += fmt::format("\t}};\n\n");

			fileBody() += fmt::format("}}\n\n");



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::addToStreamEx(Bundle& stream, const {}& v)\n{{\n", className, typeName);

			fileBody() += fmt::format("\tstream.writeUint32((uint32)v.Num());\n");

			fileBody() += fmt::format("\tfor(int i=0; i<v.Num(); ++i)\n");

			fileBody() += fmt::format("\t{{\n");



			std::string writeName;

			if (isFixedType)

			{

				writeName = fmt::format("itemType.addToStreamEx(stream, v[i])", writeName);

			}

			else

			{

				writeName = datatype2nativetype(pFixedArrayType->getDataType()->getName());

				std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

				writeName[0] = std::toupper(writeName[0]);

				writeName = fmt::format("stream.write{}(v[i])", writeName);

			}



			fileBody() += fmt::format("\t\t{};\n", writeName);

			fileBody() += fmt::format("\t}};\n");

			fileBody() += fmt::format("}}\n\n");



			changeContextToHeader();

			fileBody() += fmt::format("}};\n\n");

		}

		else if (strcmp(pFixedArrayType->getDataType()->getName(), "ARRAY") == 0)

		{

			readName = fmt::format("itemType.createFromStreamEx(stream, datas)", readName);



			createArrayChildClass(pFixedArrayType, pFixedArrayType->getDataType(), className + "_ChildArray", "\t");



			fileBody() += fmt::format("\tDATATYPE_{} itemType;\n\n",

				className + "_ChildArray", className + "_ChildArray");



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::createFromStreamEx(MemoryStream& stream, {}& datas)\n{{\n", className, typeName);

			fileBody() += fmt::format("\t{};\n", readName);

			fileBody() += fmt::format("}}\n\n");



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::addToStreamEx(Bundle& stream, const {}& v)\n{{\n", className, typeName);

			std::string writeName = fmt::format("itemType.addToStreamEx(stream, v)", writeName);

			fileBody() += fmt::format("\t{};\n", writeName);

			fileBody() += fmt::format("}}\n");



			changeContextToHeader();

			fileBody() += fmt::format("}};\n\n");

		}

		else

		{

			readName = datatype2nativetype(pFixedArrayType->getDataType()->getName());

			std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

			readName[0] = std::toupper(readName[0]);

			readName = fmt::format("stream.read{}()", readName);



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid createFromStreamEx(MemoryStream& stream, {}& datas);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::createFromStreamEx(MemoryStream& stream, {}& datas)\n{{\n", className, typeName);

			fileBody() += fmt::format("\tuint32 size = stream.readUint32();\n");

			fileBody() += fmt::format("\twhile(size > 0)\n");

			fileBody() += fmt::format("\t{{\n");

			fileBody() += fmt::format("\t\t--size;\n");

			fileBody() += fmt::format("\t\tdatas.Add({});\n", readName);

			fileBody() += fmt::format("\t}};\n\n");

			fileBody() += fmt::format("}}\n\n");



			changeContextToHeader();

			fileBody() += fmt::format("\tvoid addToStreamEx(Bundle& stream, const {}& v);\n", typeName);



			changeContextToSource();

			fileBody() += fmt::format("void DATATYPE_{}::addToStreamEx(Bundle& stream, const {}& v)\n{{\n", className, typeName);

			fileBody() += fmt::format("\tstream.writeUint32((uint32)v.Num());\n");

			fileBody() += fmt::format("\tfor(int i=0; i<v.Num(); ++i)\n");

			fileBody() += fmt::format("\t{{\n");



			std::string writeName;

			if (isFixedType)

			{

				writeName = fmt::format("itemType.addToStreamEx(stream, v[i])", writeName);

			}

			else

			{

				writeName = datatype2nativetype(pFixedArrayType->getDataType()->getName());

				std::transform(writeName.begin(), writeName.end(), writeName.begin(), tolower);

				writeName[0] = std::toupper(writeName[0]);

				writeName = fmt::format("stream.write{}(v[i])", writeName);

			}



			fileBody() += fmt::format("\t\t{};\n", writeName);

			fileBody() += fmt::format("\t}};\n");

			fileBody() += fmt::format("}}\n\n");



			changeContextToHeader();

			fileBody() += fmt::format("}};\n\n");

		}

	}

	else

	{

	}



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitScript_ScriptModule(ScriptDefModule* pScriptDefModule)

{

	fileBody() += fmt::format("\tScriptModule* p{}Module = new ScriptModule(\"{}\", {});\n", pScriptDefModule->getName(), pScriptDefModule->getName(), pScriptDefModule->getUType());

	fileBody() += fmt::format("\tEntityDef::moduledefs.Add(TEXT(\"{}\"), p{}Module);\n", pScriptDefModule->getName(), pScriptDefModule->getName());

	fileBody() += fmt::format("\tEntityDef::idmoduledefs.Add({}, p{}Module);\n\n", pScriptDefModule->getUType(), pScriptDefModule->getName());

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitScript_MethodDescr(ScriptDefModule* pScriptDefModule, MethodDescription* pDescr, COMPONENT_TYPE componentType)

{

	// 如果pDescr为None,并且是客户端方法,那么需要强制设定useMethodDescrAlias为true,否则默认为false将会出现问题

	if (!pDescr && componentType == CLIENT_TYPE)

	{

		fileBody() += fmt::format("\tp{}Module->useMethodDescrAlias = true;\n", pScriptDefModule->getName());

		return true;

	}



	assert(pDescr);



	fileBody() += fmt::format("\tTArray<DATATYPE_BASE*> {}_{}_args;\n", pScriptDefModule->getName(), pDescr->getName());



	const std::vector<DataType*>& args = pDescr->getArgTypes();

	std::vector<DataType*>::const_iterator argiter = args.begin();

	for (; argiter != args.end(); ++argiter)

	{

		uint16 typeID = datatype2id((*argiter)->getName());

		if (typeID == 0 || strcmp((*argiter)->getName(), "FIXED_DICT") == 0 || strcmp((*argiter)->getName(), "ARRAY") == 0)

			typeID = (*argiter)->id();



		fileBody() += fmt::format("\t{}_{}_args.Add(EntityDef::id2datatypes[{}]);\n", pScriptDefModule->getName(), pDescr->getName(), typeID);

	}



	fileBody() += fmt::format("\n\tMethod* p{}_{} = new Method();\n", pScriptDefModule->getName(), pDescr->getName());

	fileBody() += fmt::format("\tp{}_{}->name = TEXT(\"{}\");\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->getName());

	fileBody() += fmt::format("\tp{}_{}->methodUtype = {};\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->getUType());

	fileBody() += fmt::format("\tp{}_{}->aliasID = {};\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->aliasID());

	fileBody() += fmt::format("\tp{}_{}->args = {}_{}_args;\n\n", pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());



	fileBody() += fmt::format("\tp{}Module->methods.Add(TEXT(\"{}\"), p{}_{}); \n",

		pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());



	if (pDescr->aliasID() != -1)

	{

		if (componentType == CLIENT_TYPE)

		{

			fileBody() += fmt::format("\tp{}Module->useMethodDescrAlias = true;\n", pScriptDefModule->getName());

			fileBody() += fmt::format("\tp{}Module->idmethods.Add((uint16)p{}_{}->aliasID, p{}_{});\n\n",

				pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

		}

		else

		{

			KBE_ASSERT(false);

		}

	}

	else

	{

		if (componentType == CLIENT_TYPE)

		{

			fileBody() += fmt::format("\tp{}Module->useMethodDescrAlias = false;\n", pScriptDefModule->getName());

			fileBody() += fmt::format("\tp{}Module->idmethods.Add(p{}_{}->methodUtype, p{}_{});\n\n",

				pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

		}

		if (componentType == BASEAPP_TYPE)

		{

			fileBody() += fmt::format("\tp{}Module->base_methods.Add(TEXT(\"{}\"), p{}_{});\n\n",

				pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());



			fileBody() += fmt::format("\tp{}Module->idbase_methods.Add(p{}_{}->methodUtype, p{}_{});\n\n",

				pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

		}

		else

		{

			fileBody() += fmt::format("\tp{}Module->cell_methods.Add(TEXT(\"{}\"), p{}_{});\n\n",

				pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());



			fileBody() += fmt::format("\tp{}Module->idcell_methods.Add(p{}_{}->methodUtype, p{}_{});\n\n",

				pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

		}

	}



	fileBody() += fmt::format("\t//DEBUG_MSG(\"EntityDef::initScriptModules: add({}), method({} / {}).\");\n\n",

		pScriptDefModule->getName(), pDescr->getName(), pDescr->getUType());



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityDefsModuleInitScript_PropertyDescr(ScriptDefModule* pScriptDefModule, PropertyDescription* pDescr)

{

	uint16 typeID = datatype2id(pDescr->getDataType()->getName());

	bool isFixedType = strcmp(pDescr->getDataType()->getName(), "FIXED_DICT") == 0 || strcmp(pDescr->getDataType()->getName(), "ARRAY") == 0;



	if (typeID == 0 || isFixedType)

		typeID = pDescr->getDataType()->id();



	fileBody() += fmt::format("\tProperty* p{}_{} = new Property();\n", pScriptDefModule->getName(), pDescr->getName());

	fileBody() += fmt::format("\tp{}_{}->name = TEXT(\"{}\");\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->getName());

	fileBody() += fmt::format("\tp{}_{}->properUtype = {};\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->getUType());

	fileBody() += fmt::format("\tp{}_{}->properFlags = {};\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->getFlags());

	fileBody() += fmt::format("\tp{}_{}->aliasID = {};\n", pScriptDefModule->getName(), pDescr->getName(), pDescr->aliasID());



	if (isFixedType)

	{

		fileBody() += fmt::format("\tp{}_{}->pDefaultVal = EntityDef::id2datatypes[{}]->parseDefaultValStr(\"{}\");\n",

			pScriptDefModule->getName(), pDescr->getName(), typeID, pDescr->getDefaultValStr());

	}

	else

	{

		std::string readName = typeToType(datatype2nativetype(typeID));



		if (readName == "FVector2D" || readName == "FVector3f" || readName == "FVector4")

		{

			fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar({}());\n", pScriptDefModule->getName(),

				pDescr->getName(), readName);

		}

		else if (readName == "FString")

		{

			fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar({}());\n", pScriptDefModule->getName(),

				pDescr->getName(), readName);

		}

		else if (readName == "PYTHON" || readName == "PY_DICT" || readName == "PY_TUPLE" || readName == "PY_LIST" || readName == "TArray<uint8>")

		{

			fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar(TArray<uint8>());\n", pScriptDefModule->getName(),

				pDescr->getName());

		}

		else if (pDescr->getDataType()->type() == DATA_TYPE_ENTITY_COMPONENT)

		{

		}

		else

		{

			if (readName == "float")

			{

				fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar(FCString::Atof(TEXT(\"{}\")));\n", 

					pScriptDefModule->getName(), pDescr->getName(), pDescr->getDefaultValStr());

			}

			if(readName == "double")

			{

				fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar(FCString::Atod(TEXT(\"{}\")));\n", 

					pScriptDefModule->getName(), pDescr->getName(), pDescr->getDefaultValStr());

			}

			else if (readName == "int8" || readName == "int16" || readName == "int32" || readName == "int64" ||

				readName == "uint8" || readName == "uint16" || readName == "uint32" || readName == "uint64")

			{

				fileBody() += fmt::format("\tKBVar* p{}_{}_defval = new KBVar(({})FCString::Atoi64(TEXT(\"{}\")));\n", 

					pScriptDefModule->getName(), pDescr->getName(), readName, pDescr->getDefaultValStr());

			}

		}



		if (pDescr->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

			fileBody() += fmt::format("\tp{}_{}->pDefaultVal = p{}_{}_defval;\n", pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

	}



	fileBody() += fmt::format("\tp{}Module->propertys.Add(TEXT(\"{}\"), p{}_{}); \n\n",

		pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());



	if (pDescr->aliasID() != -1)

	{

		fileBody() += fmt::format("\tp{}Module->usePropertyDescrAlias = true;\n", pScriptDefModule->getName());

		fileBody() += fmt::format("\tp{}Module->idpropertys.Add((uint16)p{}_{}->aliasID, p{}_{});\n\n",

			pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

	}

	else

	{

		fileBody() += fmt::format("\tp{}Module->usePropertyDescrAlias = false;\n", pScriptDefModule->getName());

		fileBody() += fmt::format("\tp{}Module->idpropertys.Add(p{}_{}->properUtype, p{}_{});\n\n",

			pScriptDefModule->getName(), pScriptDefModule->getName(), pDescr->getName(), pScriptDefModule->getName(), pDescr->getName());

	}



	fileBody() += fmt::format("\t//DEBUG_MSG(\"EntityDef::initScriptModules: add({}), property({} / {}).\");\n\n",

		pScriptDefModule->getName(), pDescr->getName(), pDescr->getUType());



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypesBegin()

{

	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", "");



	fileBody() += "#pragma once\n\n";

	fileBody() += "#include \"KBECommon.h\"\n\n";

	fileBody() += namespaceNameBegin;

	fileBody() += "\n// defined in */scripts/entity_defs/types.xml\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypesEnd()

{

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeBegin(std::string typeName, FixedDictType* pDataType)

{

	initBody_ = "";

	fileBody() += fmt::format("class {}\n{{\npublic:\n", typeName);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeEnd(std::string typeName, FixedDictType* pDataType)

{

	if (initBody_.size() > 0)

	{

		initBody_ = std::string(":\n") + initBody_;

		initBody_.erase(initBody_.size() - 2);

	}



	fileBody() += fmt::format("\n\t{}(){}\n\t{{\n\t}}\n", typeName, initBody_);

	fileBody() += "\n};\n\n";



	fileBody() += fmt::format("inline bool operator ==(const {}& a, const {}& b)\n{{\n", typeName, typeName);

	fileBody() += "\treturn ";



	FixedDictType::FIXEDDICT_KEYTYPE_MAP& keysMap = pDataType->getKeyTypes();

	FixedDictType::FIXEDDICT_KEYTYPE_MAP::iterator iter = keysMap.begin();

	for (; iter != keysMap.end(); ++iter)

	{

		if (iter != keysMap.begin())

			fileBody() += " && ";



		fileBody() += fmt::format("a.{} == b.{}", iter->first, iter->first);

	}



	fileBody() += ";\n};\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeBegin(std::string typeName, FixedArrayType* pDataType, const std::string& parentClass)

{

	initBody_ = "";

	fileBody() += fmt::format("class {}{}\n{{\npublic:\n", typeName, (parentClass.size() > 0 ? std::string(" : public ") + parentClass : ""));

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeEnd(std::string typeName, FixedArrayType* pDataType)

{

	if (initBody_.size() > 0)

	{

		initBody_ = std::string(":\n") + initBody_;

		initBody_.erase(initBody_.size() - 2);

	}



	fileBody() += fmt::format("\n\t{}(){}\n\t{{\n\t}}\n", typeName, initBody_);

	fileBody() += "\n};\n\n";



	fileBody() += fmt::format("inline bool operator ==(const {}& a, const {}& b)\n{{\n", typeName, typeName);

	fileBody() += "\treturn a == b";

	fileBody() += ";\n};\n\n";

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeBegin(std::string typeName, DataType* pDataType)

{

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeEnd(std::string typeName, DataType* pDataType)

{

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_AliasName(const std::string& itemName, const std::string& childItemName)

{

	if (childItemName == "UINT8" || childItemName == "UINT16" || childItemName == "UINT32" || childItemName == "UINT64" ||

		childItemName == "INT8" || childItemName == "INT16" || childItemName == "INT32" || childItemName == "INT64" ||

		childItemName == "FLOAT" || childItemName == "DOUBLE")

	{

		std::string ntype = typeToType(childItemName);

		fileBody() += fmt::format("typedef {} {};\n\n", ntype, itemName);

	}

	else if (childItemName == "STRING")

	{

		std::string ntype = typeToType(childItemName);

		fileBody() += fmt::format("typedef {} {};\n\n", ntype, itemName);

	}

	else if (childItemName == "UNICODE")

	{

		std::string ntype = typeToType(childItemName);

		fileBody() += fmt::format("typedef {} {}{};\n\n", ntype, ConflictTypePrefix, itemName);

	}

	else if (childItemName == "PYTHON" || childItemName == "PY_DICT" || childItemName == "PY_TUPLE" ||

		childItemName == "PY_LIST" || childItemName == "ENTITYCALL" || childItemName == "BLOB")

	{

		std::string ntype = "TArray<uint8>";

		fileBody() += fmt::format("typedef {} {};\n\n", ntype, itemName);

	}

	else if (childItemName == "VECTOR2" || childItemName == "VECTOR3" || childItemName == "VECTOR4")

	{

		std::string ntype = typeToType(childItemName);

		fileBody() += fmt::format("typedef {} {};\n\n", ntype, itemName);

	}



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_INT8(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tint8 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_INT16(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tint16 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_INT32(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tint32 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_INT64(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tint64 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_UINT8(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tuint8 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_UINT16(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tuint16 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_UINT32(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tuint32 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_UINT64(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tuint64 {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, 0);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_FLOAT(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tfloat {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "0.0f");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_DOUBLE(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tdouble {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "0.0");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_STRING(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tFString {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_UNICODE(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tFString {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_PYTHON(const std::string& itemName, const std::string& childItemName)

{

	return writeTypeItemType_BLOB(itemName, childItemName);

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_PY_DICT(const std::string& itemName, const std::string& childItemName)

{

	return writeTypeItemType_BLOB(itemName, childItemName);

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_PY_TUPLE(const std::string& itemName, const std::string& childItemName)

{

	return writeTypeItemType_BLOB(itemName, childItemName);

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_PY_LIST(const std::string& itemName, const std::string& childItemName)

{

	return writeTypeItemType_BLOB(itemName, childItemName);

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_BLOB(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tTArray<uint8> {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_ARRAY(const std::string& itemName, const std::string& childItemName, DataType* pDataType)

{

	std::string typeStr;



	if (childItemName.size() == 0 || childItemName[0] == '_')

	{

		getArrayType(pDataType, typeStr);

	}

	else

	{

		typeStr = childItemName;

	}



	fileBody() += fmt::format("\t{} {};\n", typeStr, itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_FIXED_DICT(const std::string& itemName, const std::string& childItemName, DataType* pDataType)

{

	fileBody() += fmt::format("\t{} {};\n", childItemName, itemName, childItemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_VECTOR2(const std::string& itemName, const std::string& childItemName)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector2D {};\n", itemName);

#else

	fileBody() += fmt::format("\tFVector2D {};\n", itemName);

#endif



	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_VECTOR3(const std::string& itemName, const std::string& childItemName)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector3f {};\n", itemName);

#else

	fileBody() += fmt::format("\tFVector3f {};\n", itemName);

#endif



	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_VECTOR4(const std::string& itemName, const std::string& childItemName)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector4 {};\n", itemName);

#else

	fileBody() += fmt::format("\tFVector4 {};\n", itemName);

#endif



	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeTypeItemType_ENTITYCALL(const std::string& itemName, const std::string& childItemName)

{

	fileBody() += fmt::format("\tTArray<uint8> {};\n", itemName);

	initBody_ += fmt::format("\t{}({}),\n", itemName, "");

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityModuleBegin(ScriptDefModule* pEntityScriptDefModule)

{

	changeContextToHeader();



	std::string newModuleName = fmt::format("{}{}", pEntityScriptDefModule->getName(), moduleSuffix);



	if (!pEntityScriptDefModule->isComponentModule())

		initBody_ = "\tEntity(),\n\tpBaseEntityCall(NULL),\n\tpCellEntityCall(NULL),\n";

	else

		initBody_ = "\tEntityComponent(),\n\tpBaseEntityCall(NULL),\n\tpCellEntityCall(NULL),\n";



	fileBody() = headerBody;

	strutil::kbe_replace(fileBody(), "#REPLACE#", fmt::format("\tPlease inherit this module, such as: (class {} : public {}{})\n",

		pEntityScriptDefModule->getName(), pEntityScriptDefModule->getName(), moduleSuffix));



	fileBody() += "#pragma once\n";

	fileBody() += "#include \"KBECommon.h\"\n";



	if (!pEntityScriptDefModule->isComponentModule())

	{

		fileBody() += "#include \"Entity.h\"\n";

	}

	else

	{

		fileBody() += "#include \"EntityComponent.h\"\n";

	}



	fileBody() += "#include \"KBETypes.h\"\n";

	



	if (pEntityScriptDefModule->isComponentModule())

	{

		fileBody() += "#include \"ServerErrorDescrs.h\"\n";

	}



	fileBody() += fmt::format("#include \"EntityCall{}.h\"\n\n", newModuleName);



	fileBody() += namespaceNameBegin;

	fileBody() += "class Method;\n";

	fileBody() += "class Property;\n";

	fileBody() += "class MemoryStream;\n";



	std::map<std::string, PropertyDescription*> includesHistroy;

	ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

	ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

	for (; propIter != clientPropertys.end(); ++propIter)

	{

		PropertyDescription* pPropertyDescription = propIter->second;



		if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

			continue;



		EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



		if (includesHistroy.find(pEntityComponentType->pScriptDefModule()->getName()) != includesHistroy.end())

			continue;



		fileBody() += fmt::format("class {}{};\n", pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix);

		includesHistroy[pEntityComponentType->pScriptDefModule()->getName()] = pPropertyDescription;

	}



	fileBody() += std::string("\n// defined in ") + pEntityScriptDefModule->getDefSourceFile() + "\n";


	if (pEntityScriptDefModule->isComponentModule())

	{

		fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public EntityComponent\n{{\npublic:\n", newModuleName);



		// 写entityCall属性

		fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName);

		fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n", newModuleName);

		fileBody() += fmt::format("\tScriptModule* getScriptModule();\n\n");



		changeContextToSource();

		

		fileBody() += fmt::format("#include \"{}.h\"\n", newModuleName);

		fileBody() += fmt::format("#include \"KBVar.h\"\n");

		fileBody() += fmt::format("#include \"Entity.h\"\n");

		fileBody() += fmt::format("#include \"EntityDef.h\"\n");

		fileBody() += fmt::format("#include \"ScriptModule.h\"\n");

		fileBody() += fmt::format("#include \"Property.h\"\n");

		fileBody() += fmt::format("#include \"Method.h\"\n");

		fileBody() += fmt::format("#include \"DataTypes.h\"\n");

		fileBody() += fmt::format("#include \"CustomDataTypes.h\"\n");

		fileBody() += fmt::format("#include \"MemoryStream.h\"\n\n");

		fileBody() += namespaceNameBegin;

	}

	else

	{

		fileBody() += fmt::format("\t// Please inherit and implement \"class {} : public {}\"\n", pEntityScriptDefModule->getName(), newModuleName);

		fileBody() += fmt::format("class KBENGINEPLUGINS_API {} : public Entity\n{{\npublic:\n", newModuleName);



		// 写entityCall属性

		fileBody() += fmt::format("\tEntityBaseEntityCall_{}* pBaseEntityCall;\n", newModuleName);

		fileBody() += fmt::format("\tEntityCellEntityCall_{}* pCellEntityCall;\n\n", newModuleName);



		changeContextToSource();

		fileBody() += fmt::format("#include \"{}.h\"\n", newModuleName);

		fileBody() += fmt::format("#include \"KBVar.h\"\n");

		fileBody() += fmt::format("#include \"EntityDef.h\"\n");

		fileBody() += fmt::format("#include \"ScriptModule.h\"\n");

		fileBody() += fmt::format("#include \"Property.h\"\n");

		fileBody() += fmt::format("#include \"Method.h\"\n");

		fileBody() += fmt::format("#include \"DataTypes.h\"\n");

		fileBody() += fmt::format("#include \"CustomDataTypes.h\"\n");

		fileBody() += fmt::format("#include \"MemoryStream.h\"\n");

		fileBody() += fmt::format("#include \"EntityComponent.h\"\n\n");



		std::map<std::string, PropertyDescription*> includesHistroy;

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



			if (includesHistroy.find(pEntityComponentType->pScriptDefModule()->getName()) != includesHistroy.end())

				continue;



			fileBody() += fmt::format("#include \"Scripts/Components/{}.h\"\n\n", pEntityComponentType->pScriptDefModule()->getName());

			includesHistroy[pEntityComponentType->pScriptDefModule()->getName()] = pPropertyDescription;

		}



		fileBody() += namespaceNameBegin;

	}



	changeContextToHeader();

	// 函数返回后,后续流程为写实体属性..

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityModuleEnd(ScriptDefModule* pEntityScriptDefModule)

{

	changeContextToHeader();



	if (initBody_.size() > 0)

	{

		initBody_ = std::string(":\n") + initBody_;

		initBody_.erase(initBody_.size() - 2);

	}



	std::string newModuleName = fmt::format("{}{}", pEntityScriptDefModule->getName(), moduleSuffix);



	fileBody() += fmt::format("\n\t{}();\n", newModuleName);

	fileBody() += fmt::format("\tvirtual ~{}();\n", newModuleName);



	changeContextToSource();

	fileBody() += fmt::format("\n{}::{}(){}\n{{\n", newModuleName, newModuleName, initBody_);



	if (!pEntityScriptDefModule->isComponentModule())

	{

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();

			fileBody() += fmt::format("\t{}->pOwner = this;\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t{}->ownerID = id_;\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t{}->entityComponentPropertyID = {};\n", pPropertyDescription->getName(), pPropertyDescription->getUType());

			fileBody() += fmt::format("\t{}->name_ = \"{}\";\n\n", pPropertyDescription->getName(), pEntityComponentType->pScriptDefModule()->getName());

		}

	}



	fileBody() += fmt::format("}}\n");

	

	fileBody() += fmt::format("\n{}::~{}()\n{{\n", newModuleName, newModuleName);



	if (!pEntityScriptDefModule->isComponentModule())

	{

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			//EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();

			fileBody() += fmt::format("\tif({})\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t\tdelete {};\n\n", pPropertyDescription->getName());

		}

	}



	fileBody() += fmt::format("\tif(pBaseEntityCall)\n");

	fileBody() += fmt::format("\t\tdelete pBaseEntityCall;\n\n");



	fileBody() += fmt::format("\tif(pCellEntityCall)\n");

	fileBody() += fmt::format("\t\tdelete pCellEntityCall;\n\n");



	fileBody() += "}\n";



	// attach组件

	if (!pEntityScriptDefModule->isComponentModule())

	{

		changeContextToHeader();

		fileBody() += fmt::format("\n\tvoid attachComponents() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nvoid {}::attachComponents()\n{{\n", newModuleName);



		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			fileBody() += fmt::format("\t{}->onAttached(this);\n", pPropertyDescription->getName());

		}



		fileBody() += fmt::format("}}\n");

	}



	// detach组件

	if (!pEntityScriptDefModule->isComponentModule())

	{

		changeContextToHeader();

		fileBody() += fmt::format("\tvoid detachComponents() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nvoid {}::detachComponents()\n{{\n", newModuleName);



		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			fileBody() += fmt::format("\t{}->onDetached(this);\n", pPropertyDescription->getName());

		}



		fileBody() += fmt::format("}}\n");

	}



	std::vector<PropertyDescription*> components;



	ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

	ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

	for (; propIter != clientPropertys.end(); ++propIter)

	{

		PropertyDescription* pPropertyDescription = propIter->second;



		if (pPropertyDescription->getDataType()->type() == DATA_TYPE_ENTITY_COMPONENT)

			components.push_back(pPropertyDescription);

	}



	if (!components.empty())

	{

		changeContextToHeader();

		fileBody() += fmt::format("\tTArray<EntityComponent*> getComponents(FString componentName, bool all) override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nTArray<EntityComponent*> {}::getComponents(FString componentName, bool all)\n{{\n", newModuleName);

	

		fileBody() += fmt::format("\tTArray<EntityComponent*> founds;\n\n");



		std::vector<PropertyDescription*>::const_iterator iter = components.begin();

		for (; iter != components.end(); ++iter)

		{

			PropertyDescription* pPropertyDescription = *iter;

			fileBody() += fmt::format("\tif({}->name_ == componentName)\n\t{{\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t\tfounds.Add({});\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t\tif(!all)\n");

			fileBody() += fmt::format("\t\t\treturn founds;\n\t}}\n\n");

		}



		fileBody() += "\treturn founds;\n";

		fileBody() += "}\n";

	}



	fileBody() += namespaceNameEnd;



	changeContextToHeader();

	fileBody() += "\n};\n";

	fileBody() += namespaceNameEnd;

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProcessMessagesMethod(ScriptDefModule* pEntityScriptDefModule)

{

	std::string ownstr = "";

	if (pEntityScriptDefModule->isComponentModule())

		ownstr = "pOwner->";



	changeContextToHeader();



	// EntityCall

	std::string newModuleName = fmt::format("{}{}", pEntityScriptDefModule->getName(), moduleSuffix);



	if (pEntityScriptDefModule->isComponentModule())

	{

		changeContextToHeader();

		fileBody() += fmt::format("\n\tvoid createFromStream(MemoryStream& stream) override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nvoid {}::createFromStream(MemoryStream& stream)\n{{\n", newModuleName);

		fileBody() += fmt::format("\tEntityComponent::createFromStream(stream);\n");

		fileBody() += fmt::format("}}\n");



		changeContextToHeader();

		fileBody() += fmt::format("\n\tvoid onGetBase() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nvoid {}::onGetBase()\n{{\n", newModuleName);

		sourcefileBody_ += fmt::format("\townerID = pOwner->id();\n\n");

		fileBody() += fmt::format("\tif(pBaseEntityCall)\n");

		fileBody() += fmt::format("\t\tdelete pBaseEntityCall;\n\n");

		fileBody() += fmt::format("\tpBaseEntityCall = new EntityBaseEntityCall_{}(entityComponentPropertyID, ownerID);\n", newModuleName);

		fileBody() += "}\n\n";



		changeContextToHeader();

		fileBody() += fmt::format("\tvoid onGetCell() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("void {}::onGetCell()\n{{\n", newModuleName);

		sourcefileBody_ += fmt::format("\townerID = pOwner->id();\n\n");

		fileBody() += fmt::format("\tif(pCellEntityCall)\n");

		fileBody() += fmt::format("\t\tdelete pCellEntityCall;\n\n");

		fileBody() += fmt::format("\tpCellEntityCall = new EntityCellEntityCall_{}(entityComponentPropertyID, ownerID);\n", newModuleName);

		fileBody() += "}\n";



		changeContextToHeader();

		fileBody() += fmt::format("\tvoid onLoseCell() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("\nvoid {}::onLoseCell()\n{{\n", newModuleName);

		fileBody() += fmt::format("\tdelete pCellEntityCall;\n");

		fileBody() += fmt::format("\tpCellEntityCall = NULL;\n");

		fileBody() += "}\n\n";

	}



	if (pEntityScriptDefModule->isComponentModule())

	{

		sourcefileBody_ += fmt::format("\nScriptModule* {}::getScriptModule()\n{{\n", newModuleName);

		sourcefileBody_ += fmt::format("\treturn *EntityDef::moduledefs.Find(\"{}\");\n", pEntityScriptDefModule->getName());

		sourcefileBody_ += "}\n";

	}



	if (!pEntityScriptDefModule->isComponentModule())

	{

		{

			changeContextToHeader();

			fileBody() += fmt::format("\n\tvoid onComponentsEnterworld() override;\n");



			changeContextToSource();

			fileBody() += fmt::format("\nvoid {}::onComponentsEnterworld()\n{{\n", newModuleName);



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				fileBody() += fmt::format("\t{}->onEnterworld();\n", pPropertyDescription->getName());

			}



			fileBody() += fmt::format("}}\n");

		}



		{

			changeContextToHeader();

			fileBody() += fmt::format("\tvoid onComponentsLeaveworld() override;\n");



			changeContextToSource();

			fileBody() += fmt::format("\nvoid {}::onComponentsLeaveworld()\n{{\n", newModuleName);



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				fileBody() += fmt::format("\t{}->onLeaveworld();\n", pPropertyDescription->getName());

			}



			fileBody() += fmt::format("}}\n");

		}



		{

			changeContextToHeader();

			fileBody() += fmt::format("\n\tvoid onGetBase() override;\n");



			changeContextToSource();

			fileBody() += fmt::format("\nvoid {}::onGetBase()\n{{\n", newModuleName);

			fileBody() += fmt::format("\tif(pBaseEntityCall)\n");

			fileBody() += fmt::format("\t\tdelete pBaseEntityCall;\n\n");

			fileBody() += fmt::format("\tpBaseEntityCall = new EntityBaseEntityCall_{}(id(), className());\n", newModuleName);



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				fileBody() += fmt::format("\t{}->onGetBase();\n", pPropertyDescription->getName());

			}



			fileBody() += fmt::format("}}\n");

		}



		{

			changeContextToHeader();

			fileBody() += fmt::format("\tvoid onGetCell() override;\n");



			changeContextToSource();

			fileBody() += fmt::format("\nvoid {}::onGetCell()\n{{\n", newModuleName);

			fileBody() += fmt::format("\tif(pCellEntityCall)\n");

			fileBody() += fmt::format("\t\tdelete pCellEntityCall;\n\n");

			fileBody() += fmt::format("\tpCellEntityCall = new EntityCellEntityCall_{}(id(), className());\n", newModuleName);





			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				fileBody() += fmt::format("\t{}->onGetCell();\n", pPropertyDescription->getName());

			}



			fileBody() += "}\n";

		}



		{

			changeContextToHeader();

			fileBody() += fmt::format("\tvoid onLoseCell() override;\n\n");



			changeContextToSource();

			fileBody() += fmt::format("\nvoid {}::onLoseCell()\n{{\n", newModuleName);

			fileBody() += fmt::format("\tdelete pCellEntityCall;\n");

			fileBody() += fmt::format("\tpCellEntityCall = NULL;\n");



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				fileBody() += fmt::format("\t{}->onLoseCell();\n", pPropertyDescription->getName());

			}



			fileBody() += "}\n\n";

		}



		changeContextToHeader();

		fileBody() += fmt::format("\tEntityCall* getBaseEntityCall() override;\n");



		changeContextToSource();

		fileBody() += fmt::format("EntityCall* {}::getBaseEntityCall()\n{{\n", newModuleName);

		fileBody() += fmt::format("\treturn pBaseEntityCall;\n");

		fileBody() += "}\n";



		changeContextToHeader();

		fileBody() += fmt::format("\tEntityCall* getCellEntityCall() override;\n\n");



		changeContextToSource();

		fileBody() += fmt::format("\nEntityCall* {}::getCellEntityCall()\n{{\n", newModuleName);

		fileBody() += fmt::format("\treturn pCellEntityCall;\n");

		fileBody() += "}\n";

	}



	// 处理方法

	changeContextToHeader();



	if (!pEntityScriptDefModule->isComponentModule())

		fileBody() += fmt::format("\n\tvoid onRemoteMethodCall(MemoryStream& stream) override;\n");

	else

		fileBody() += fmt::format("\n\tvoid onRemoteMethodCall(uint16 methodUtype, MemoryStream& stream) override;\n");



	changeContextToSource();



	if (!pEntityScriptDefModule->isComponentModule())

		fileBody() += fmt::format("\nvoid {}::onRemoteMethodCall(MemoryStream& stream)\n{{\n", newModuleName);

	else

		fileBody() += fmt::format("\nvoid {}::onRemoteMethodCall(uint16 methodUtype, MemoryStream& stream)\n{{\n", newModuleName);



	ScriptDefModule::METHODDESCRIPTION_MAP& clientMethods = pEntityScriptDefModule->getClientMethodDescriptions();

	if (clientMethods.size() > 0)

	{

		fileBody() += fmt::format("\tScriptModule* sm = *EntityDef::moduledefs.Find(\"{}\");\n", pEntityScriptDefModule->getName());

		

		int entityComponentSize = 0;

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			++entityComponentSize;

		}



		if (!pEntityScriptDefModule->isComponentModule())

		{

			fileBody() += fmt::format("\tuint16 methodUtype = 0;\n", pEntityScriptDefModule->getName());

			fileBody() += fmt::format("\tuint16 componentPropertyUType = 0;\n\n");

			fileBody() += fmt::format("\tif (sm->usePropertyDescrAlias)\n\t{{\n");

			fileBody() += fmt::format("\t\tcomponentPropertyUType = stream.readUint8();\n");

			fileBody() += fmt::format("\t}}\n\telse\n\t{{\n");

			fileBody() += fmt::format("\t\tcomponentPropertyUType = stream.readUint16();\n\t}}\n\n");



			fileBody() += fmt::format("\tif (sm->useMethodDescrAlias)\n\t{{\n");

			fileBody() += fmt::format("\t\tmethodUtype = stream.read<uint8>();\n");



			bool foundComponentNoUseMethodDescrAlias = false;



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;



				EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();

				if (!pEntityComponentType->pScriptDefModule()->useMethodDescrAlias())

				{

					foundComponentNoUseMethodDescrAlias = true;

					break;

				}

			}



			if (foundComponentNoUseMethodDescrAlias)

			{

				sourcefileBody_ += fmt::format("\n\t\tif(componentPropertyUType > 0)\n");

				sourcefileBody_ += fmt::format("\t\t{{\n");

				sourcefileBody_ += fmt::format("\t\t\tbool useComponentMethodDescrAlias = true;\n");

				sourcefileBody_ += fmt::format("\t\t\tProperty* pComponentPropertyDescription = sm->idpropertys[componentPropertyUType];\n\n");

				sourcefileBody_ += fmt::format("\t\t\tswitch(pComponentPropertyDescription->properUtype)\n");

				sourcefileBody_ += fmt::format("\t\t\t{{\n");



				for (propIter = clientPropertys.begin(); propIter != clientPropertys.end(); ++propIter)

				{

					PropertyDescription* pPropertyDescription = propIter->second;



					if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

						continue;



					EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();

					if (!pEntityComponentType->pScriptDefModule()->useMethodDescrAlias())

					{

						sourcefileBody_ += fmt::format("\t\t\t\tcase {}:\n", pPropertyDescription->getUType());

						sourcefileBody_ += fmt::format("\t\t\t\t\tuseComponentMethodDescrAlias = false;\n", pPropertyDescription->getName());

						sourcefileBody_ += fmt::format("\t\t\t\t\tbreak;\n");

					}

				}



				sourcefileBody_ += fmt::format("\t\t\t\tdefault:\n");

				sourcefileBody_ += fmt::format("\t\t\t\t\tbreak;\n");

				sourcefileBody_ += fmt::format("\t\t\t}}\n\n");



				sourcefileBody_ += fmt::format("\t\t\tif(!useComponentMethodDescrAlias)\n");

				sourcefileBody_ += fmt::format("\t\t\t{{\n");

				sourcefileBody_ += fmt::format("\t\t\t\tstream.rpos(stream.rpos() - 1);\n");

				sourcefileBody_ += fmt::format("\t\t\t\tmethodUtype = stream.read<uint16>();\n");

				sourcefileBody_ += fmt::format("\t\t\t}}\n");



				sourcefileBody_ += fmt::format("\t\t}}\n");

			}



			fileBody() += fmt::format("\t}}\n\telse\n\t{{\n");

			fileBody() += fmt::format("\t\tmethodUtype = stream.read<uint16>();\n\t}}\n\n");



			fileBody() += fmt::format("\tif(componentPropertyUType > 0)\n\t{{\n");

			if (entityComponentSize > 0)

			{

				fileBody() += fmt::format("\t\tProperty* pComponentPropertyDescription = sm->idpropertys[componentPropertyUType];\n\n");

				fileBody() += fmt::format("\t\tswitch(pComponentPropertyDescription->properUtype)\n\t\t{{\n");



				ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

				ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

				for (; propIter != clientPropertys.end(); ++propIter)

				{

					PropertyDescription* pPropertyDescription = propIter->second;



					if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

						continue;





					fileBody() += fmt::format("\t\t\tcase {}:\n", pPropertyDescription->getUType());

					fileBody() += fmt::format("\t\t\t\t{}->onRemoteMethodCall(methodUtype, stream);\n", pPropertyDescription->getName());

					fileBody() += fmt::format("\t\t\t\tbreak;\n");

				}



				fileBody() += fmt::format("\t\t}}\n");



				

			}

			else

			{

				fileBody() += fmt::format("\t\tKBE_ASSERT(false);\n");

			}



			fileBody() += fmt::format("\n\t\treturn;\n");

			fileBody() += fmt::format("\t}}\n\n");



			fileBody() += fmt::format("\tMethod* pMethod = sm->idmethods[methodUtype];\n\n");

		}

		else

		{

			fileBody() += fmt::format("\tMethod* pMethod = sm->idmethods[methodUtype];\n\n");

		}



		fileBody() += fmt::format("\tswitch(pMethod->methodUtype)\n\t{{\n");



		ScriptDefModule::METHODDESCRIPTION_MAP::iterator methodIter = clientMethods.begin();

		for (; methodIter != clientMethods.end(); ++methodIter)

		{

			MethodDescription* pMethodDescription = methodIter->second;



			fileBody() += fmt::format("\t\tcase {}:\n\t\t{{\n", pMethodDescription->getUType());



			std::vector<DataType*>& argTypes = pMethodDescription->getArgTypes();

			std::vector<DataType*>::iterator iter = argTypes.begin();



			int i = 1;

			std::string argsStr;



			for (; iter != argTypes.end(); ++iter)

			{

				DataType* pDataType = (*iter);



				uint16 typeID = datatype2id(pDataType->getName());

				if (typeID == 0 || strcmp(pDataType->getName(), "FIXED_DICT") == 0 || strcmp(pDataType->getName(), "ARRAY") == 0)

					typeID = pDataType->id();



				argsStr += fmt::format("{}_arg{}, ", pMethodDescription->getName(), i);



				std::string readName = datatype2nativetype(pDataType->getName());

				if (readName.size() > 0)

				{

					std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

					readName[0] = std::toupper(readName[0]);

				}



				std::string nativetype = datatype2nativetype(typeID);

				if (strcmp(pDataType->getName(), "FIXED_DICT") == 0)

				{

					fileBody() += fmt::format("\t\t\t{} {}_arg{};\n", pDataType->aliasName(), pMethodDescription->getName(), i);



					fileBody() += fmt::format("\t\t\t((DATATYPE_{}*)pMethod->args[{}])->createFromStreamEx(stream, {}_arg{});\n",

						pDataType->aliasName(), (i - 1), pMethodDescription->getName(), i);

				}

				else if (strcmp(pDataType->getName(), "ARRAY") == 0)

				{

					std::string typestr;

					getArrayType(pDataType, typestr);



					if (strlen(pDataType->aliasName()) > 0)

					{

						fileBody() += fmt::format("\t\t\t{} {}_arg{};\n",

							pDataType->aliasName(), pMethodDescription->getName(), i);



						fileBody() += fmt::format("\t\t\t((DATATYPE_{}*)pMethod->args[{}])->createFromStreamEx(stream, {}_arg{});\n",

							pDataType->aliasName(), (i - 1), pMethodDescription->getName(), i);

					}

					else

					{

						fileBody() += fmt::format("\t\t\t{} {}_arg{};\n",

							typestr, pMethodDescription->getName(), i);



						fileBody() += fmt::format("\t\t\t((DATATYPE_AnonymousArray_{}*)pMethod->args[{}])->createFromStreamEx(stream, {}_arg{});\n",

							typeID, (i - 1), pMethodDescription->getName(), i);

					}

				}

				else

				{

					fileBody() += fmt::format("\t\t\t{} {}_arg{} = stream.read{}();\n",

						typeToType(nativetype), pMethodDescription->getName(), i, readName);

				}



				++i;

			}



			if (argsStr.size() > 0)

				argsStr.erase(argsStr.size() - 2, 2);



			fileBody() += fmt::format("\t\t\t{}({});\n", pMethodDescription->getName(), argsStr);

			fileBody() += fmt::format("\t\t\tbreak;\n\t\t}}\n");

		}



		fileBody() += fmt::format("\t\tdefault:\n");

		fileBody() += fmt::format("\t\t\tbreak;\n");

		fileBody() += fmt::format("\t}};\n");

	}



	fileBody() += "}\n";



	// 处理属性

	ENTITY_PROPERTY_UID posuid = 0;

	if (posuid == 0)

	{

		posuid = ENTITY_BASE_PROPERTY_UTYPE_POSITION_XYZ;

		Network::FixedMessages::MSGInfo* msgInfo =

			Network::FixedMessages::getSingleton().isFixed("Property::position");



		if (msgInfo != NULL)

			posuid = msgInfo->msgid;

	}



	PropertyDescription positionDescription(posuid, "VECTOR3", "position", ED_FLAG_ALL_CLIENTS, true, DataTypes::getDataType("VECTOR3"), false, "", 0, "", DETAIL_LEVEL_FAR);

	if (pEntityScriptDefModule->usePropertyDescrAlias() && positionDescription.aliasID() == -1)

		positionDescription.aliasID(ENTITY_BASE_PROPERTY_ALIASID_POSITION_XYZ);



	ENTITY_PROPERTY_UID diruid = 0;

	if (diruid == 0)

	{

		diruid = ENTITY_BASE_PROPERTY_UTYPE_DIRECTION_ROLL_PITCH_YAW;

		Network::FixedMessages::MSGInfo* msgInfo = Network::FixedMessages::getSingleton().isFixed("Property::direction");

		if (msgInfo != NULL)

			diruid = msgInfo->msgid;

	}



	PropertyDescription directionDescription(diruid, "VECTOR3", "direction", ED_FLAG_ALL_CLIENTS, true, DataTypes::getDataType("VECTOR3"), false, "", 0, "", DETAIL_LEVEL_FAR);

	if (pEntityScriptDefModule->usePropertyDescrAlias() && directionDescription.aliasID() == -1)

		directionDescription.aliasID(ENTITY_BASE_PROPERTY_ALIASID_DIRECTION_ROLL_PITCH_YAW);



	ENTITY_PROPERTY_UID spaceuid = 0;

	if (spaceuid == 0)

	{

		spaceuid = ENTITY_BASE_PROPERTY_UTYPE_SPACEID;

		Network::FixedMessages::MSGInfo* msgInfo = Network::FixedMessages::getSingleton().isFixed("Property::spaceID");

		if (msgInfo != NULL)

			spaceuid = msgInfo->msgid;

	}



	PropertyDescription spaceDescription(spaceuid, "UINT32", "spaceID", ED_FLAG_OWN_CLIENT, true, DataTypes::getDataType("UINT32"), false, "", 0, "", DETAIL_LEVEL_FAR);

	if (pEntityScriptDefModule->usePropertyDescrAlias() && spaceDescription.aliasID() == -1)

		spaceDescription.aliasID(ENTITY_BASE_PROPERTY_ALIASID_SPACEID);



	changeContextToHeader();

	if (pEntityScriptDefModule->isComponentModule())

		fileBody() += fmt::format("\tvoid onUpdatePropertys(uint16 propUtype, MemoryStream& stream, int maxCount) override;\n");

	else

		fileBody() += fmt::format("\tvoid onUpdatePropertys(MemoryStream& stream) override;\n");



	changeContextToSource();

	if (pEntityScriptDefModule->isComponentModule())

		fileBody() += fmt::format("\nvoid {}::onUpdatePropertys(uint16 propUtype, MemoryStream& stream, int maxCount)\n{{\n", newModuleName);

	else

		fileBody() += fmt::format("\nvoid {}::onUpdatePropertys(MemoryStream& stream)\n{{\n", newModuleName);



	fileBody() += fmt::format("\tScriptModule* sm = *EntityDef::moduledefs.Find(\"{}\");\n\n", pEntityScriptDefModule->getName());



	if (pEntityScriptDefModule->isComponentModule())

		sourcefileBody_ += fmt::format("\twhile(stream.length() > 0 && maxCount-- != 0)\n\t{{\n");

	else

		sourcefileBody_ += fmt::format("\twhile(stream.length() > 0)\n\t{{\n");



	fileBody() += fmt::format("\t\tuint16 componentPropertyUType = 0;\n");



	if (!pEntityScriptDefModule->isComponentModule())

	{

		fileBody() += fmt::format("\t\tuint16 properUtype = 0;\n\n");



		int entityComponentSize = 0;

		ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

				continue;



			++entityComponentSize;

		}



		fileBody() += fmt::format("\t\tif (sm->usePropertyDescrAlias)\n\t\t{{\n");

		fileBody() += fmt::format("\t\t\tcomponentPropertyUType = stream.readUint8();\n");

		fileBody() += fmt::format("\t\t\tproperUtype = stream.read<uint8>();\n");

		fileBody() += fmt::format("\t\t}}\n\t\telse\n\t\t{{\n");

		fileBody() += fmt::format("\t\t\tcomponentPropertyUType = stream.readUint16();\n");

		fileBody() += fmt::format("\t\t\tproperUtype = stream.read<uint16>();\n\t\t}}\n\n");



		fileBody() += fmt::format("\t\tif(componentPropertyUType > 0)\n\t\t{{\n");

		if (entityComponentSize > 0)

		{

			fileBody() += fmt::format("\t\t\tProperty* pComponentPropertyDescription = sm->idpropertys[componentPropertyUType];\n\n");

			fileBody() += fmt::format("\t\t\tswitch(pComponentPropertyDescription->properUtype)\n\t\t\t{{\n");



			ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();

			ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

			for (; propIter != clientPropertys.end(); ++propIter)

			{

				PropertyDescription* pPropertyDescription = propIter->second;



				if (pPropertyDescription->getDataType()->type() != DATA_TYPE_ENTITY_COMPONENT)

					continue;





				fileBody() += fmt::format("\t\t\t\tcase {}:\n", pPropertyDescription->getUType());

				fileBody() += fmt::format("\t\t\t\t\t{}->onUpdatePropertys(properUtype, stream, -1);\n", pPropertyDescription->getName());

				fileBody() += fmt::format("\t\t\t\t\tbreak;\n");

			}



			fileBody() += fmt::format("\t\t\t}}\n");

		}

		else

		{

			fileBody() += fmt::format("\t\t\tKBE_ASSERT(false);\n");

		}



		fileBody() += fmt::format("\n\t\t\treturn;\n");

		fileBody() += fmt::format("\t\t}}\n\n");



		fileBody() += fmt::format("\t\tProperty* pProp = sm->idpropertys[properUtype];\n\n");

	}

	else

	{

		fileBody() += fmt::format("\t\tuint16 properUtype = propUtype;\n\n");



		fileBody() += fmt::format("\t\tif (properUtype == 0)\n\t\t{{\n");

		fileBody() += fmt::format("\t\t\tif (sm->usePropertyDescrAlias)\n\t\t\t{{\n");

		fileBody() += fmt::format("\t\t\t\tcomponentPropertyUType = stream.readUint8();\n");

		fileBody() += fmt::format("\t\t\t\tproperUtype = stream.read<uint8>();\n");

		fileBody() += fmt::format("\t\t\t}}\n\t\t\telse\n\t\t\t{{\n");

		fileBody() += fmt::format("\t\t\t\tcomponentPropertyUType = stream.readUint16();\n");

		fileBody() += fmt::format("\t\t\t\tproperUtype = stream.read<uint16>();\n\t\t\t}}\n");

		fileBody() += fmt::format("\t\t}}\n\n");



		fileBody() += fmt::format("\t\tProperty* pProp = sm->idpropertys[properUtype];\n\n");

	}



	ScriptDefModule::PROPERTYDESCRIPTION_MAP clientPropertys = pEntityScriptDefModule->getClientPropertyDescriptions();



	// entity即使在属性小于0时仍然存在默认属性,而组件则可能因为没有属性导致空switch编译出错

	if (!pEntityScriptDefModule->isComponentModule() || clientPropertys.size() > 0)

	{

		fileBody() += fmt::format("\t\tswitch(pProp->properUtype)\n\t\t{{\n");



		if (!pEntityScriptDefModule->isComponentModule())

		{

			clientPropertys[positionDescription.getName()] = &positionDescription;

			clientPropertys[directionDescription.getName()] = &directionDescription;

			clientPropertys[spaceDescription.getName()] = &spaceDescription;

		}



		ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

		for (; propIter != clientPropertys.end(); ++propIter)

		{

			PropertyDescription* pPropertyDescription = propIter->second;



			if (pPropertyDescription->getDataType()->type() == DATA_TYPE_ENTITY_COMPONENT)

			{

				fileBody() += fmt::format("\t\t\tcase {}:\n", pPropertyDescription->getUType());

				fileBody() += fmt::format("\t\t\t\t{}->createFromStream(stream);\n", pPropertyDescription->getName());

				fileBody() += fmt::format("\t\t\t\tbreak;\n");

				continue;

			}



			std::string typestr;



			if (std::string("position") == pPropertyDescription->getName() ||

				std::string("direction") == pPropertyDescription->getName())

			{

#ifdef CLIENT_NO_FLOAT

				typestr = "FVector3f";

#else

				typestr = "FVector3f";

#endif

			}

			else

			{

				if (std::string("spaceID") == pPropertyDescription->getName())

				{

					fileBody() += fmt::format("\t\t\tcase {}:\n\t\t\t{{\n", pPropertyDescription->getUType());

					fileBody() += fmt::format("\t\t\t\tstream.readUint32();\n");

					fileBody() += fmt::format("\t\t\t\tbreak;\n\t\t\t}}\n");

					continue;

				}

				else

				{

					std::string findstr = fmt::format(" {};", pPropertyDescription->getName());

					std::string::size_type fpos = headerfileBody_.find(findstr);

					std::string::size_type fposStart = headerfileBody_.rfind("\t", fpos - 1);

					std::string::size_type fposEnd = headerfileBody_.rfind(" ", fpos);



					typestr.assign(headerfileBody_.begin() + fposStart + 1, headerfileBody_.begin() + fposEnd);

				}

			}



			fileBody() += fmt::format("\t\t\tcase {}:\n\t\t\t{{\n", pPropertyDescription->getUType());

			fileBody() += fmt::format("\t\t\t\t{} oldval_{} = {};\n", typestr, pPropertyDescription->getName(), pPropertyDescription->getName());



			std::string readName = datatype2nativetype(pPropertyDescription->getDataType()->getName());

			if (readName.size() > 0)

			{

				std::transform(readName.begin(), readName.end(), readName.begin(), tolower);

				readName[0] = std::toupper(readName[0]);

			}

			else

			{

				KBE_ASSERT(false);

			}



			if (pPropertyDescription->getDataType()->type() == DATA_TYPE_FIXEDDICT)

			{

				readName = fmt::format("((DATATYPE_{}*)EntityDef::id2datatypes[{}])->createFromStreamEx(stream, {})",

					pPropertyDescription->getDataType()->aliasName(), pPropertyDescription->getDataType()->id(), pPropertyDescription->getName());



				fileBody() += fmt::format("\t\t\t\t{};\n", readName);

			}

			else if (pPropertyDescription->getDataType()->type() == DATA_TYPE_FIXEDARRAY)

			{

				if (strlen(pPropertyDescription->getDataType()->aliasName()) > 0)

				{

					readName = fmt::format("((DATATYPE_{}*)EntityDef::id2datatypes[{}])->createFromStreamEx(stream, {})",

						pPropertyDescription->getDataType()->aliasName(), pPropertyDescription->getDataType()->id(), pPropertyDescription->getName());

				}

				else

				{

					readName = fmt::format("((DATATYPE_AnonymousArray_{}*)EntityDef::id2datatypes[{}])->createFromStreamEx(stream, {})",

						pPropertyDescription->getDataType()->id(), pPropertyDescription->getDataType()->id(), pPropertyDescription->getName());

				}



				fileBody() += fmt::format("\t\t\t\t{};\n", readName);

			}

			else

			{

				readName = fmt::format("stream.read{}()", readName);

				fileBody() += fmt::format("\t\t\t\t{} = {};\n", pPropertyDescription->getName(), readName);

			}



			std::string name = pPropertyDescription->getName();

			name[0] = std::toupper(name[0]);

			fileBody() += fmt::format("\n\t\t\t\tif(pProp->isBase())\n\t\t\t\t{{\n");

			fileBody() += fmt::format("\t\t\t\t\tif({}inited())\n", ownstr);

			fileBody() += fmt::format("\t\t\t\t\t\ton{}Changed(oldval_{});\n\t\t\t\t}}\n", name, pPropertyDescription->getName());

			fileBody() += fmt::format("\t\t\t\telse\n\t\t\t\t{{\n");

			fileBody() += fmt::format("\t\t\t\t\tif({}inWorld())\n", ownstr);

			fileBody() += fmt::format("\t\t\t\t\t\ton{}Changed(oldval_{});\n", name, pPropertyDescription->getName());

			fileBody() += fmt::format("\t\t\t\t}}\n\n");

			fileBody() += fmt::format("\t\t\t\tbreak;\n\t\t\t}}\n");

		}



		fileBody() += fmt::format("\t\t\tdefault:\n");

		fileBody() += fmt::format("\t\t\t\tbreak;\n");

		fileBody() += fmt::format("\t\t}};\n");

	}



	fileBody() += "\t}\n";

	fileBody() += "}\n";



	// 处理属性callPropertysSetMethods

	changeContextToHeader();

	fileBody() += fmt::format("\tvoid callPropertysSetMethods() override;\n");



	changeContextToSource();

	fileBody() += fmt::format("\nvoid {}::callPropertysSetMethods()\n{{\n", newModuleName);

	fileBody() += fmt::format("\tScriptModule* sm = EntityDef::moduledefs[\"{}\"];\n", pEntityScriptDefModule->getName());

	fileBody() += fmt::format("\tTMap<uint16, Property*>& pdatas = sm->idpropertys;\n\n");



	ScriptDefModule::PROPERTYDESCRIPTION_MAP::const_iterator propIter = clientPropertys.begin();

	for (; propIter != clientPropertys.end(); ++propIter)

	{

		PropertyDescription* pPropertyDescription = propIter->second;



		std::string typestr;



		if (std::string("spaceID") == pPropertyDescription->getName())

			continue;



		if (std::string("position") == pPropertyDescription->getName() ||

			std::string("direction") == pPropertyDescription->getName())

		{

#ifdef CLIENT_NO_FLOAT

			typestr = "FVector3f";

#else

			typestr = "FVector3f";

#endif

		}

		else

		{

			std::string findstr = fmt::format(" {};", pPropertyDescription->getName());

			std::string::size_type fpos = headerfileBody_.find(findstr);

			std::string::size_type fposStart = headerfileBody_.rfind("\t", fpos - 1);

			std::string::size_type fposEnd = headerfileBody_.rfind(" ", fpos);



			typestr.assign(headerfileBody_.begin() + fposStart + 1, headerfileBody_.begin() + fposEnd);

		}



		if (pPropertyDescription->getDataType()->type() == DATA_TYPE_ENTITY_COMPONENT)

		{

			fileBody() += fmt::format("\t{}->callPropertysSetMethods();\n\n", pPropertyDescription->getName());

		}

		else

		{

			fileBody() += fmt::format("\t{} oldval_{} = {};\n", typestr, pPropertyDescription->getName(), pPropertyDescription->getName());



			std::string name = pPropertyDescription->getName();

			name[0] = std::toupper(name[0]);



			fileBody() += fmt::format("\tProperty* pProp_{} = pdatas[{}];\n", pPropertyDescription->getName(), (pEntityScriptDefModule->usePropertyDescrAlias() ?

				pPropertyDescription->aliasID() : pPropertyDescription->getUType()));



			fileBody() += fmt::format("\tif(pProp_{}->isBase())\n\t{{\n", pPropertyDescription->getName());

			fileBody() += fmt::format("\t\tif({}inited() && !{}inWorld())\n", ownstr, ownstr);

			fileBody() += fmt::format("\t\t\ton{}Changed(oldval_{});\n", name, pPropertyDescription->getName());

			fileBody() += fmt::format("\t}}\n\telse\n\t{{\n");

			fileBody() += fmt::format("\t\tif({}inWorld())\n\t\t{{\n", ownstr);

			fileBody() += fmt::format("\t\t\tif(pProp_{}->isOwnerOnly() && !{}isPlayer())\n\t\t\t{{\n\t\t\t}}\n\t\t\telse\n\t\t\t{{\n", pPropertyDescription->getName(), ownstr);

			fileBody() += fmt::format("\t\t\t\ton{}Changed(oldval_{});\n\t\t\t}}\n", name, pPropertyDescription->getName());

			fileBody() += fmt::format("\t\t}}\n\t}}\n\n");

		}

	}



	fileBody() += "}\n";



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityPropertyComponent(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	EntityComponentType * pEntityComponentType = (EntityComponentType*)pPropertyDescription->getDataType();



	fileBody() += fmt::format("\t{}{}* {};\n", pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix, pPropertyDescription->getName(),

		pEntityComponentType->pScriptDefModule()->getName());



	initBody_ += fmt::format("\t{}(new {}()),\n", pPropertyDescription->getName(), pEntityComponentType->pScriptDefModule()->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const {}{}& oldValue) {{}}\n", name, pEntityComponentType->pScriptDefModule()->getName(), moduleSuffix);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_INT8(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tint8 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((int8)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(int8 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_INT16(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tint16 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((int16)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(int16 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_INT32(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tint32 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((int32)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(int32 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_INT64(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tint64 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((int64)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(int64 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_UINT8(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tuint8 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((uint8)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(uint8 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_UINT16(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tuint16 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((uint16)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(uint16 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_UINT32(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tuint32 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((uint32)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(uint32 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_UINT64(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tuint64 {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}((uint64)FCString::Atoi64(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(uint64 oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_FLOAT(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tfloat {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(FCString::Atof(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0.0f"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(float oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_DOUBLE(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tdouble {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(FCString::Atod(TEXT(\"{}\"))),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : "0.0"));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(double oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_STRING(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tFString {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(TEXT(\"{}\")),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : ""));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const FString& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_UNICODE(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tFString {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(TEXT(\"{}\")),\n", pPropertyDescription->getName(), (strlen(pPropertyDescription->getDefaultValStr()) > 0 ? pPropertyDescription->getDefaultValStr() : ""));



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const FString& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_PYTHON(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	ERROR_MSG("ClientSDKUE5::writeEntityProperty_PYTHON(): nonsupport!\n");

	return false;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_PY_DICT(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	ERROR_MSG("ClientSDKUE5::writeEntityProperty_PY_DICT(): nonsupport!\n");

	return false;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_PY_TUPLE(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	ERROR_MSG("ClientSDKUE5::writeEntityProperty_PY_TUPLE(): nonsupport!\n");

	return false;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_PY_LIST(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	ERROR_MSG("ClientSDKUE5::writeEntityProperty_PY_LIST(): nonsupport!\n");

	return false;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_BLOB(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tTArray<uint8> {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_ARRAY(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	if (std::string("ARRAY") == pPropertyDescription->getDataTypeName())

	{

		std::string s = fileBody();

		fileBody() = "";



		bool ret = writeTypeItemType_ARRAY(pPropertyDescription->getName(), pPropertyDescription->getDataType()->aliasName(), pPropertyDescription->getDataType());

		std::vector<std::string> values;

		KBEngine::strutil::kbe_splits(fileBody(), " ", values);

		fileBody() = s + fileBody();



		std::string name = pPropertyDescription->getName();

		name[0] = std::toupper(name[0]);

		fileBody() += fmt::format("\t\tvirtual void on{}Changed(const {}& oldValue) {{}}\n", name, values[1]);

		return ret;

	}

	else

	{

		fileBody() += fmt::format("\t{} {};\n", pPropertyDescription->getDataTypeName(), pPropertyDescription->getName());

		initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



		std::string name = pPropertyDescription->getName();

		name[0] = std::toupper(name[0]);

		fileBody() += fmt::format("\tvirtual void on{}Changed(const {}& oldValue) {{}}\n", name, pPropertyDescription->getDataTypeName());

	} 



	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_FIXED_DICT(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\t{} {};\n", pPropertyDescription->getDataTypeName(), pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const {}& oldValue) {{}}\n", name, pPropertyDescription->getDataTypeName());

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_VECTOR2(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector2D {};\n", pPropertyDescription->getName());

#else

	fileBody() += fmt::format("\tFVector2D {};\n", pPropertyDescription->getName());

#endif



	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const FVector2D& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_VECTOR3(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector3f {};\n", pPropertyDescription->getName());

#else

	fileBody() += fmt::format("\tFVector3f {};\n", pPropertyDescription->getName());

#endif



	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const FVector3f& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_VECTOR4(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

#ifdef CLIENT_NO_FLOAT

	fileBody() += fmt::format("\tFVector4 {};\n", pPropertyDescription->getName());

#else

	fileBody() += fmt::format("\tFVector4 {};\n", pPropertyDescription->getName());

#endif



	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const FVector4& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityProperty_ENTITYCALL(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, PropertyDescription* pPropertyDescription)

{

	fileBody() += fmt::format("\tTArray<uint8> {};\n", pPropertyDescription->getName());

	initBody_ += fmt::format("\t{}(),\n", pPropertyDescription->getName());



	std::string name = pPropertyDescription->getName();

	name[0] = std::toupper(name[0]);

	fileBody() += fmt::format("\tvirtual void on{}Changed(const TArray<uint8>& oldValue) {{}}\n", name);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityMethod(ScriptDefModule* pEntityScriptDefModule,

	ScriptDefModule* pCurrScriptDefModule, MethodDescription* pMethodDescription, const char* fillString)

{

	fileBody() += fmt::format("\tvirtual void {}({}) = 0; \n", pMethodDescription->getName(), fillString);

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityMethodArgs_ARRAY(FixedArrayType* pFixedArrayType, std::string& stackArgsTypeBody, const std::string& childItemName)

{

	// 对于匿名数组需要解析,否则直接填类型名称

	if (childItemName.size() == 0 || childItemName[0] == '_')

	{

		std::string typeStr;

		getArrayType(pFixedArrayType, typeStr);

		stackArgsTypeBody += fmt::format("const {}&", typeStr);

	}

	else

	{

		stackArgsTypeBody += fmt::format("const {}&", childItemName);

	}

	

	return true;

}



//-------------------------------------------------------------------------------------

bool ClientSDKUE5::writeEntityMethodArgs_Const_Ref(DataType* pDataType, std::string& stackArgsTypeBody)

{

	stackArgsTypeBody = std::string("const ") + stackArgsTypeBody + "&";

	return true;

}



//-------------------------------------------------------------------------------------

}