Jump to content

Distraught

Honorable Member
  • Posts

    270
  • Joined

  • Last visited

  • Days Won

    38
  • Feedback

    100%

Everything posted by Distraught

  1. Fixed reload function and std::async launch policy. It was using std::launch::async before but to let the operating system use thread pooling (msvc implementation) it had to be std::launch::async | std::launch::deferred.
  2. I posted a solution there. Just have to add the partid of the sashes where you see switch (i) { case CRaceData::PART_WEAPON: case CRaceData::PART_WEAPON_LEFT: break; default: SetMotionPointer(m_LODControllerVector[i]); break; } and the first code snippet to where you attach the sashes.
  3. if (CGrannyLODController* pLODController = m_LODControllerVector[dwPartIndex]) { if (CGrannyModelInstance* pWeaponModelInstance = pLODController->GetModelInstance()) { CGraphicThing* pItemGraphicThing = pItemData->GetModelThing(); if (CGrannyMotion* pItemMotion = pItemGraphicThing->GetMotionPointer(0)) { pWeaponModelInstance->SetMotionPointer(pItemMotion); } } } Add the code above to the end of void CActorInstance::AttachWeapon(DWORD dwParentPartIndex, DWORD dwPartIndex, CItemData * pItemData) function in ActorInstanceAttach.cpp and ThingInstance.cpp in the function bool CGraphicThingInstance::SetMotion(DWORD dwMotionKey, float blendTime, int loopCount, float speedRatio) modify std::for_each(m_LODControllerVector.begin(), m_LODControllerVector.end(), SetMotionPointer); to for (int i = 0; i < m_LODControllerVector.size(); ++i) { switch (i) { case CRaceData::PART_WEAPON: case CRaceData::PART_WEAPON_LEFT: break; default: SetMotionPointer(m_LODControllerVector[i]); break; } } and add these to the includes #include "../GameLib/GameType.h" #include "../GameLib/RaceData.h" to make it work when the weapon is equipped. ??
  4. M2 Download Center Download Here ( Internal ) If you wanna bring some serialization to the networking, send floating point numbers safely between the server and the client or just don't want to define packet structures for everything this will be useful for you. We will use rapidjson library for parsing and creating json strings but don't worry I created some helper functions to make it easier. So let's start first on the server side! Add JsonPacket.cpp and h to your game project and put the content of the include folder to you include directory. Open up input.h and add the following to CInputProcessor base class: int RecvJsonPacket(LPDESC desc, const char* data, size_t uiBytes); Now go to input.cpp and add the definition: int CInputProcessor::RecvJsonPacket(LPDESC desc, const char* data, size_t uiBytes) { if (nullptr == desc || uiBytes < sizeof(TPacketJson)) { return -1; } const TPacketJson* packet = (const TPacketJson*)data; if (uiBytes < sizeof(TPacketJson) + packet->length || uiBytes > (1 << 12)) { return -1; } Json::Document json; json.Parse<rapidjson::kParseStopWhenDoneFlag>(data + sizeof(TPacketJson)); switch (json.GetParseError()) { case rapidjson::kParseErrorNone: case rapidjson::kParseErrorDocumentEmpty: break; default: sys_err("Json Parse Error (code %d)", (int)json.GetParseError()); return -1; } if (!JsonPacket::Recv(desc, (JsonPacket::Type)packet->type, json)) { return -1; } return packet->length; } Don't forget to include JsonPacket.h and json.h! Now go to input_main.cpp and find the function CInputMain::Analyze. Add this case: case HEADER_CG_JSON: if ((iExtraLen = RecvJsonPacket(d, c_pData, m_iBufferLeft)) < 0) { return -1; } break; Go to packet.h and add this structure: struct TPacketJson { uint8_t header; int32_t type; uint32_t length; }; Add them to the packet header enumerations: HEADER_CG_JSON = 170, HEADER_GC_JSON = 170, Go to packet_info.cpp and add by the others add the following in constructor of CPatcketInfoCG. Set(HEADER_CG_JSON, sizeof(TPacketJson), "Json Packet", true); Finally add JsonPacket.cpp to you Makefile too. Now let's get to the client side! Add JsonPacket.cpp and h to your UserInterface project and the content of the include folder to your include directory. Go to PythonNetworkStream.h and add the following to CPythonNetworkStream class: bool RecvJsonPacket(); Now to go to PythonNetworkStream.cpp and add the definition: bool CPythonNetworkStream::RecvJsonPacket() { TPacketJson packet; if (!Recv(sizeof(TPacketJson), &packet)) { return false; } std::vector<char> buffer(packet.length); if (!Recv(packet.length, buffer.data())) { return false; } Json::Document json; json.ParseInsitu<rapidjson::kParseStopWhenDoneFlag>(buffer.data()); switch (json.GetParseError()) { case rapidjson::kParseErrorNone: case rapidjson::kParseErrorDocumentEmpty: break; default: return false; } return JsonPacket::Recv((JsonPacket::Type)packet.type, json); } Don't forget to include JsonPacket.h and json.h! Go to PythonNetworkStreamPhaseGame.cpp and add the following case in the CPythonNetworkStream::GamePhase function: case HEADER_GC_JSON: ret = RecvJsonPacket(); return; Go to Packet.h and add the struct: struct TPacketJson { uint8_t header; int32_t type; uint32_t length; }; Add these to the packet header enumerations: HEADER_CG_JSON = 170, HEADER_GC_JSON = 170, Go to PythonNetworkStream.cpp again and add this to the CMainPacketHeaderMap constructor: Set(HEADER_GC_JSON, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketJson), DYNAMIC_SIZE_PACKET)); If you would like to send a packet, just add a new packet type to the enum and here's a sample code, it works the exact same way on server and client side: #include "JsonPacket.h" void SomeFunction() { Json::Document testPacket = Json::CreateJsonObject(); Json::SetValue(testPacket, "fieldName1", "string value"); Json::SetValue(testPacket, "fieldName2", 123); Json::SetValue(testPacket, "fieldName3", true); JsonPacket::Send(JsonPacket::Type::PACKET_TYPE_TEST, testPacket); } And here's the download link for the files: [Hidden Content] Hope you like it! Good luck!
  5. Actually I still use mysql5.7 because it has better performance than mysql8 but less security. Normally the mysql server is not reachable from the outside so security is not really the thing.
  6. +1 for liquid dnb
  7. Hey guys, Have anyone ever seen something like this? Alas I can't debug it because it's really random and happened just about a few times but after like a character select it goes back to normal. Any idea?
  8. As the posts of the updates were lost, now I put them in this reply. UPDATE V1.2 fixed fbx conversion in case of several meshes added option to specify flags as arguments Download: [Hidden Content] UPDATE V1.3 fixed material texture binding changed Y-up to Z-up Download: [Hidden Content]
  9. M2 Download Center Download Here ( Internal ) Hey again Yesterday I was looking into mss32.dll and just found out this is the library being responsible for loading asi, mix, m3d, etc.. files. So I made a library that will hook the Miles Sound System so that it won't load unwanted files, only what is needed. Download: [Hidden Content] VirusTotal: [Hidden Content] There are 3 files in the zip: .lib -> put it in your extern/lib folder .h -> put it in your extern/include folder .dll -> put it in your client Open UserInterface/UserInterface.cpp and find the WinMain function. Add this to the beginning of the function: DistraughtProtector::Initialize(); DistraughtProtector::SetFileBlockedCallback(&HackerDetected); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssmp3.asi", 125952); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssvoice.asi", 197120); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssa3d.m3d", 83456); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssds3d.m3d", 70656); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssdx7.m3d", 80896); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\msseax.m3d", 103424); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssrsx.m3d", 354816); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\msssoft.m3d", 67072); DistraughtProtector::AddAllowedMilesProviderLibrary("miles\\mssdsp.flt", 93696); You have to specify the files that are enabled to load by the Miles Sound System (path, file size in bytes). And add this before that function: static void _stdcall HackerDetected(const char* blockedFile) { MessageBox(NULL, blockedFile, ApplicationStringTable_GetStringz(IDS_APP_NAME, "APP_NAME"), MB_ICONSTOP); } This is a callback where you get notified if the user would load a file that he/she shouldn't You don't have to specify a callback, in that case remove DistraughtProtector::SetFileBlockedCallback(&HackerDetected); from WinMain and the client just simply won't load the dangerous files. Here's an image what it should look like: After that just add DistraughtProtector::Destroy(); to the end of WinMain (surely before the return!). Hope you like it! If you have ideas what new features should I add to the library, let me know in the comments!
  10. Compile your game with -g flag for debug symbols and if it's not a live environment I suggest you use -O0 also.
  11. Change std::vector <LPITEM> item_gets(NULL); to std::vector <LPITEM> item_gets; And by the way those item_gets->GetName() at the end should be item_gets[i]->GetName()
  12. No one defined what they mean by interacting real-time. Interacting real time can also mean like sending messages what could be achieved. What I was talking about still makes sense as I told them their possibilities, just really have your time understanding it. This construction could matter tho. You ought to understand what I am saying instead of just trying to get it personal because your message was nothing but trying to be bitchy about anything.
  13. M2 Download Center Download Here ( Internal ) Hey guys, I just programmed this feature for my server but I thought it can be really useful for everyone so now I release it. This stuff is about how you can load images, etc. in the game without directly packing it into the client but uploading them to a web-server. In this tutorial we will make it work for images, but you can extend it to any type of file you want. There are not much requirements we only use up to C++11 features and you have to have libcurl library. Open up EterLib/ResourceManager.h and add add the following to the end of the class (don't forget to include <future> and <utility>): private: std::list<std::future<CResource*>> ongoingDownloads; public: void AddDownload(std::future<CResource*>&& f) { ongoingDownloads.emplace_back(std::forward<std::future<CResource*>>(f)); } Go to EterLib/ResourceManager.cpp and find the CResourceManager::Update function, add the following to the end of it: for (auto it = ongoingDownloads.begin(); it != ongoingDownloads.end();) { if (it->wait_for(std::chrono::seconds(0)) == std::future_status::ready) { it->get()->LoadDownloadedData(); it = ongoingDownloads.erase(it); } else { ++it; } } Next, open EterLib/Resource.h, find the constructor and modify it like: CResource(const char* c_szFileName, bool _loadFromNetwork = false); After add the following to the end of the class: protected: bool loadFromNetwork; private: std::vector<BYTE> downloadedData; public: void LoadDownloadedData(); Then go to EterLib/Resource.cpp, find the constructor and also modify it like: CResource::CResource(const char* c_szFileName, bool _loadFromNetwork) : me_state(STATE_EMPTY) , loadFromNetwork(_loadFromNetwork) { SetFileName(c_szFileName); } In the same file, add this to the beginning right after the includes: #include <curl/curl.h> #include "ResourceManager.h" #define ASSET_SERVER "[Hidden Content]" static size_t CurlWriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { if (nullptr != userp) { std::vector<BYTE>& vec = *((std::vector<BYTE>*)userp); vec.reserve(vec.size() + (size * nmemb)); for (size_t i = 0; i < size * nmemb; ++i) { vec.push_back(((BYTE*)contents)[i]); } } return size * nmemb; } void CResource::LoadDownloadedData() { if (downloadedData.empty()) return; Clear(); if (OnLoad(downloadedData.size(), downloadedData.data())) { me_state = STATE_EXIST; } else { Tracef("CResource::Load Error %s\n", GetFileName()); me_state = STATE_ERROR; } downloadedData.clear(); } Now, - still in the same file - find CResource::Load function and modify it like this: void CResource::Load() { if (me_state != STATE_EMPTY) return; std::string fileName = GetFileName(); if (loadFromNetwork && downloadedData.empty()) { CResourceManager::instance().AddDownload(std::move(std::async(std::launch::async | std::launch::deferred, [this, fileName]() { std::string url = ASSET_SERVER; url += fileName; CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadedData); curl_easy_perform(curl); curl_easy_cleanup(curl); } return this; }))); fileName = "d:/ymir work/ui/placeholder.tga"; } DWORD dwStart = ELTimer_GetMSec(); CMappedFile file; LPCVOID fileData; //Tracenf("Load %s", c_szFileName); if (CEterPackManager::Instance().Get(file, fileName.c_str(), &fileData)) { m_dwLoadCostMiliiSecond = ELTimer_GetMSec() - dwStart; //Tracef("CResource::Load %s (%d bytes) in %d ms\n", c_szFileName, file.Size(), m_dwLoadCostMiliiSecond); if (OnLoad(file.Size(), fileData)) { me_state = STATE_EXIST; } else { Tracef("CResource::Load Error %s\n", fileName.c_str()); me_state = STATE_ERROR; return; } } else { if (OnLoad(0, NULL)) me_state = STATE_EXIST; else { Tracef("CResource::Load file not exist %s\n", fileName.c_str()); me_state = STATE_ERROR; } } } Still in Resource.cpp, find the CResource::Reload function and modify like: void CResource::Reload() { Tracef("CResource::Reload %s\n", GetFileName()); if (loadFromNetwork) { if (downloadedData.empty()) { std::string fileName = GetFileName(); CResourceManager::instance().AddDownload(std::move(std::async(std::launch::async | std::launch::deferred, [this, fileName]() { std::string url = ASSET_SERVER; url += "/"; url += fileName; CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &downloadedData); curl_easy_perform(curl); curl_easy_cleanup(curl); } return this; }))); } } else { Clear(); CMappedFile file; LPCVOID fileData; if (CEterPackManager::Instance().Get(file, GetFileName(), &fileData)) { if (OnLoad(file.Size(), fileData)) { me_state = STATE_EXIST; } else { me_state = STATE_ERROR; return; } } else { if (OnLoad(0, NULL)) me_state = STATE_EXIST; else { me_state = STATE_ERROR; } } } } Open EterLib/GrpImage.h and modify the constructor: CGraphicImage(const char* c_szFileName, DWORD dwFilter = D3DX_FILTER_LINEAR, bool loadFromNetwork = false); In EterLib/GrpImage.cpp also modify it: CGraphicImage::CGraphicImage(const char * c_szFileName, DWORD dwFilter, bool loadFromNetwork) : CResource(c_szFileName, loadFromNetwork) , m_dwFilter(dwFilter) { m_rect.bottom = m_rect.right = m_rect.top = m_rect.left = 0; } Finally open ScriptLib/Resource.cpp and add this somewhere the beginning: CResource* NewOnlineImage(const char* c_szFileName) { return new CGraphicImage(c_szFileName, D3DX_FILTER_LINEAR, true); } Go down where you see m_resManager.RegisterResourceNewFunctionPointer("jpg", NewImage); and add after: m_resManager.RegisterResourceNewFunctionPointer("oimg", NewOnlineImage); We're done! Now if you use *.oimg extension anywhere it will load them from what you define as ASSET_SERVER in EterLib/Resource.cpp ([Hidden Content]filename.oimg). You have to rename the image you upload from the original extension to oimg! Put a placeholder image at "d:\ymir work\ui\placeholder.tga" that it will load while waiting for bigger images. GIF in action (normal size image, the pic in the right bottom corner): GIF of loading a big (10MB image) that takes more time: Hope you like it!
  14. Or you can skip this all and just modify that if in CGraphicTextInstance::Render to if (m_isCursor && (ELTimer_GetMSec() / 500) & 1)
  15. And you really think the compiler won't optimize it anyway?
  16. Theoretically en bloc it gives some performance gain. For example converting meshes to 16bit indices even tho sounds strange because modern cpus work faster with their native word size but the less cache miss because of the size optimization can turn the balance to the other way around.
  17. It writes that out if you do that. But here it is: Optimizing mesh indices... Optimizing vertexes for CPU cache... Cleaning unreferenced materials...
  18. haha that was intentional
  19. M2 Download Center Download Here ( Internal ) Hey guys, Last night I was kinda playing with granny a bit and this tool was born. I hope it will be useful for most of you! Optimize, change textures, convert to fbx or 3ds, etc... Download: [Hidden Content] Usage: Just drag and drop a gr2 file on the exe and choose what you would like the program to do. P.S.: Don't be surprised if the new gr2 file becomes bigger than it was, it is because this tool saves them without compression for better performance.
  20. M2 Download Center Download Here ( Internal ) Hey guys, I needed to be able to scroll on the ui with the mouse wheel and I thought it will be useful for others too so here's what to do. EterPythonLib PythonWindow.h Add virtual BOOL OnMouseWheel(int nLen); after like virtual BOOL OnMouseMiddleButtonUp(); In PythonWindow.cpp add the following function: BOOL CWindow::OnMouseWheel(int nLen) { long lValue; return PyCallClassMemberFunc(m_poHandler, "OnMouseWheel", Py_BuildValue("(i)", nLen), &lValue) && 0 != lValue; } In PythonWindowManager.h add bool RunMouseWheel(int nLen); after like void RunMouseMiddleButtonUp(long x, long y); In PythonWindowManager.cpp add the definition somewhere: bool CWindowManager::RunMouseWheel(int nLen) { CWindow* pWin = GetPointWindow(); while (pWin) { if (pWin->OnMouseWheel(nLen)) return true; pWin = pWin->GetParent(); } return false; } UserInterface In PythonApplicationEvent.cpp override the following function: void CPythonApplication::OnMouseWheel(int nLen) { UI::CWindowManager& rkWndMgr = UI::CWindowManager::Instance(); if (!rkWndMgr.RunMouseWheel(nLen)) { CCameraManager& rkCmrMgr = CCameraManager::Instance(); if (CCamera* pkCmrCur = rkCmrMgr.GetCurrentCamera()) pkCmrCur->Wheel(nLen); } } Then root/ui.py and find ScrollBar class and add this function to it: def OnMouseWheel(self, nLen): if nLen > 0: self.OnUp() return True elif nLen < 0: self.OnDown() return True return False But you can use OnMouseWheel everywhere to listen to scrolling. Good luck!
  21. I type the same for the third time now. Packet around will not send anything to the peers because other cores just really don't give a shit what happened real-time with your character. Who sees you (and this is why it sends to them) is connected to the same core as you are. WHAT YOU THINK HOW THE FUCK SENDS ONE CORE THE DATA TO ALL ANOTHER? THE SAME WAY AS IF THEY WERE NOT ON THE SAME MACHINE
  22. Actually this is how the game now works. Don't put a map in more than one channel and its redirecting you between its cores.
  23. Read again. The server only has to know eg. the position of others if they are on the same map with you (sorta kinda). What do you think, why do you divide cores by maps? They are each a running server instance. When you start your server, you begin with the db because that application is going to receive a packet from each of the cores when they start running and distributes to the others. If you look into the sources, you will find out that a lot of communication acts are not even sent to all the peers just what needs to be known on other channels too (like shouts). It is completely irrelevant if those server instances are on the same machine or not if they get the address of the same db app.
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.