-
Posts
1161 -
Joined
-
Days Won
10 -
Feedback
100%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Karbust
-
-
GitHub: => (or )
This tutorial is also available on the GitHub repo.
Metin2-InfluxDB
The purpose of this is to be able to create dashboards with the timeseries statistics, like the ones seen on the video made with Grafana.
Install InfluxDB: https://docs.influxdata.com/influxdb/v2.1/install/
Information
If you intend on using Cloudflare (and nginx as reverse proxy, since InfluxDB’s default port is 8086, which isn’t supported by Cloudflare, if you choose the docker installation, just map it to a port supported by Cloudflare, preferably HTTPS), you will need to create a firewall exception to bypass all rules that come from your metin2 game server so it doesn’t get blocked or challenged.
I recommend setting up nginx as reverse proxy, that way the port 443 can be used for all hosts configured on nginx.
On FreeBSD, only InfluxDB 1.8.* is available, not recommended, since the latest major stable version is 2.1. This tutorial was made for version 2.1, there may be differences on the requests.
An IP address can be used, but a domain with SSL setup is preferable, for obvious reasons.
InfluxDB Setup
Create an organization
Create a bucket
Lib cURL
FreeBSD Setup
Install it:
pkg install curl
And link it on the Makefile:
-lcurl
Windows Setup
For Windows it works with both vcpkg and compiling the lib manually.
Shared lib:
vcpkg install curl[openssl]:x86-windows
Static lib:
vcpkg install curl[openssl]:x86-windows-static
Auto Event Manager
In case you already have this class/file, just compare and make the necessary changes. All the changes related to Influx are wrapped with the macro INFLUX_STATS.
Don't forget to also make the necessary changes on
main.cpp
. If you are already using this you won't need to include the header and initialize the class.Edit Time
The default is send the data every 10 minutes.
On the file
InfluxData.cpp
, edit this code:void CInfluxData::Check(int day, int hour, int minute, int second) { int lastNumber = minute % 10; if (isInfluxEnabled && lastNumber == 0 && second == 00)
If
lastNumber = 0
, then it means the number is divisible by, in this case, 10. Make sure when you edit the time to don't forget the seconds part, if you don't use it, it will run every second inside the minute you want to run it.Examples for other times
Every minute
if (isInfluxEnabled && second == 00)
Every 5 minutes
int lastNumber = minute % 5;
Every 30 seconds
int lastNumber = seconds % 30; if (isInfluxEnabled && lastNumber == 0)
Configuration
To use this make sure you have it only enabled on ONE core per channel, the online counter inside the channel is common between the cores, just add this on the CONFIG file to enable Influx on the core.
INFLUX_ENABLE: 1
The rest of the settings, can either be set on the source or by CONFIG options (this are the default values set on the source):
INFLUX_URL: http://127.0.0.1:8086 INFLUX_TOKEN: <token> INFLUX_ORG: <organization> INFLUX_BUCKET: <bucket>
NodeJS Version
In case you don't to use the source, a NodeJS version is available where you can use the Metin2 API to get the user count and send it to Influx.
The source method is preferred.
Acknowledgments:
Gurgarath for testing the tutorial on Windows.
Deliris for testing the tutorial on FreeBSD.
- 27
- 1
- 10
- 2
- 9
-
Open it on excel and work with the formulas.
- 1
-
Did you buy it from him? Because it's not free on his website.
We don't support leaked content.
- 1
-
1 minute ago, lime said:
I don't want to be rude, but I wouldn't like to hear some kids raging at me while I'm chill farming and destroying stones.
Yes, it would be great if you could mute specific people with a button near the `Whisper` button on the upper side of the window, or if you could disable the function completely, or if you can do it Group/Guild only.
Is portaudio part of this project?
I'll give it a yes for the system, no for buying such thing.
For now, I only have it enabled on groups.
I'm also working on an implementation that would allow the users to enable voice on an entire map, like a commerce map, or whatever.
Users can mute/unmute themselves. Push-To-Talk will also be possible.
- 1
-
I'm doing a system that offers voice ingame, it is almost done. Would anyone consider buying a system that would offer Voice Ingame?
Leave your feedback please.
Thank you
- 1
- 1
-
Sup guys
DISCLAIMER: The code on this topic of only useful if have done changes to the Pet System (like putting it on the slot) and/or use the Mount System that follows the character if you have it on a slot. The code for the horse is valid for everyone.
This code was done by @ Mali and he asked me to share it.
This code is to fix a bug on observer mode, like guild wars.
- If you have a pet on the slot and it respawns every time you teleport, this affects you.
- If you have a mount on the slot and it respawns every time you teleport, this affects you.
- If you only have the mount following you and you unmount while on observer, it will affect you.
- This last one is also valid of the horse.
The bug consists on having any of the points described above which will make the pet, mount or horse visible to everyone when the player is in observer mode.
Something like this (the player Faisca is the observer on a guild war):
SpoilerLet's start
Open char_horse.cpp, and after:
Spoilerm_chHorse->SetRider(this);
Add:
Spoilerm_chHorse->SetObserverMode(IsObserverMode());
Open PetSystem.cpp
Search for:
Spoilerif (0 != m_pkChar) { m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y); m_dwVID = m_pkChar->GetVID(); return m_dwVID; }
And make it like this:
Spoilerif (0 != m_pkChar) { m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y); m_dwVID = m_pkChar->GetVID(); m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode()); return m_dwVID; }
Search for:
Spoilerm_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
Add after:
Spoilerm_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());
At the end of the file add this:
Spoilervoid CPetSystem::UpdateObserver() { if (!m_pkOwner) return; const bool bFlag = m_pkOwner->IsObserverMode(); for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter) { const CPetActor* petActor = iter->second; if (petActor == nullptr) continue; const LPCHARACTER petCh = petActor->GetCharacter(); if (petCh) petCh->SetObserverMode(bFlag); } }
Open PetSystem.h, and after:
Spoilervoid DeletePet(CPetActor* petActor);
Add:
Spoilervoid UpdateObserver();
Open entity.cpp
Inside this function:
Spoilervoid CEntity::SetObserverMode(bool bFlag)
Change it like this:
Spoilerif (IsType(ENTITY_CHARACTER)) { LPCHARACTER ch = (LPCHARACTER) this; LPCHARACTER chHorse = ch->GetHorse(); if (chHorse) chHorse->SetObserverMode(bFlag); CPetSystem* petSystem = ch->GetPetSystem(); if (petSystem) petSystem->UpdateObserver(); ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0); }
You are finished if you don't use a special mount system.
Now, if you have the file MountSystem.cpp, open it, and search for:
Spoilerif (0 != m_pkChar) { m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y); m_dwVID = m_pkChar->GetVID(); return m_dwVID; }
And edit like this:
Spoilerif (0 != m_pkChar) { m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y); m_dwVID = m_pkChar->GetVID(); m_pkChar->SetObserverMode(m_pkOwner->IsObserverMode()); return m_dwVID; }
Search for:
Spoilerm_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
Add after:
Spoilerm_pkChar->SetObserverMode(m_pkOwner->IsObserverMode());
At the end of the file add this:
Spoilervoid CMountSystem::UpdateObserver() { for (TMountActorMap::const_iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { const CMountActor* mountActor = iter->second; if (mountActor == nullptr) continue; const LPCHARACTER mountCh = mountActor->GetCharacter(); if (mountCh) mountCh->SetObserverMode(m_pkOwner->IsObserverMode()); } }
Open MountSystem.h, and after:
Spoilervoid DeleteMount(CMountActor* mountActor);
Add:
Spoilervoid UpdateObserver();
Then edit entity.cpp again like this:
Spoilerif (IsType(ENTITY_CHARACTER)) { LPCHARACTER ch = (LPCHARACTER) this; LPCHARACTER chHorse = ch->GetHorse(); if (chHorse) chHorse->SetObserverMode(bFlag); CPetSystem* petSystem = ch->GetPetSystem(); if (petSystem) petSystem->UpdateObserver(); CMountSystem* mountSystem = ch->GetMountSystem(); if (mountSystem) mountSystem->UpdateObserver(); ch->ChatPacket(CHAT_TYPE_COMMAND, "ObserverMode %d", m_bIsObserver ? 1 : 0); }
And your are finished.
Thanks again to @ Mali for helping me solve this issue.
- 26
- 1
- 5
- 1
- 9
-
-
17 hours ago, HattanBinNassar said:
So informative , thanks a lot ,, my fear of building a website has increased to the roof
No one should face fear when starting, we all start somewhere, sometimes is just trial and error.
I read a lot of blog entries (mostly all on medium) and documentation for something I'm learning or trying to achieve or trying to compare to alternatives and see which one is the most performant and/or more secure.
I have a lot of books, some which I have personally used for both college and personal projects, you can find them here: https://ebooks.karbust.me/Technology/
- 1
-
2 hours ago, HattanBinNassar said:
Nice , this informative , what do you think as a web dev is the most potential risk of a website ?
SQL Injection, bad handling of sessions and/or authentication cookies/tokens, remote code execution
If you don't sanitize every single thing you get from the frontend and it's supposed to end up in a database, then you are open to the risk of SQL Injection. I recommend the use of ORMs, since it already handles almost all the boring part of sanitizing input.
If you don't write good code and end up doing some sketchy shit that executes commands on the server running the website, then your are fucked...
Authentication is some of the hard parts of doing a good website, there are discussions on where should the information be saved, either cookies or local storage and manually attach it to every request. I work with JWT, and I always put the token on cookies so it goes attached to every request when CORS with Allow Credentials set to true. Also make sure you use strict true so it doesn't go on requests to other domains. Obviously cookies can be grabbed by some third party trick, but it's hard and if you put a expire date on JWT and use refresh tokens and IP validation, then you are better served.
- 1
-
account.account can have insert, select and update, not only to email and password like you referenced.
player.guild only select
player.player can have select and update (in case you have an unbug function, otherwise only select)
player.item or player.item_award only insert, depending on which table you use
Other tables related to item shop and purchases should have, at least, insert and select
- 1
-
Sashes base item vnum is fixed in the binary source, starting at 85000.
Use and ID after the last basic sash and check if it works.
- 1
-
7 hours ago, HattanBinNassar said:
1 - is it possible to limit the client login attempts to 1 per 10 minutes ?
2 - is it possible to limit the login & create accounts to 2 per ip ?
Yes to both questions.
For the first you need to make changes in the source, somewhere in input_login, maybe, never did it.
For the second, assuming you are doing it in PHP, I have no idea how to do it, just search for route rate limit in php on google. In NodeJS (ExpressJS or others) would be a lot easier.
-
I'm having an issue with this and I have no idea what is causing it...
This is what I was able to gather, the issue is coming from this lines:
I put the code like this:
DWORD dwSocket2 = pItemAward->dwSocket2; sys_err("Socket2 0: %u", dwSocket2); sys_err("bType: %d", pItemTable->bType); sys_err("bSubType: %d", pItemTable->bSubType); if (pItemTable->bType == ITEM_UNIQUE) { #ifdef ENABLE_EXTEND_ITEM_AWARD // 12.04.2019 - Correction for unique items based on the real time. const long lValue0 = pItemTable->alValues[ITEM_SOCKET_REMAIN_SEC]; const long lValue2 = pItemTable->alValues[ITEM_SOCKET_UNIQUE_REMAIN_TIME]; const time_t tNow = CClientManager::instance().GetCurrentTime(); dwSocket2 = (lValue2 == 0) ? static_cast<DWORD>(lValue0) : static_cast<DWORD>(tNow + lValue0); sys_err("Socket2 1: %u", dwSocket2); #else if (pItemAward->dwSocket2 != 0) dwSocket2 = pItemAward->dwSocket2; else dwSocket2 = pItemTable->alValues[0]; #endif }
And this is the output:
SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Socket2 0: 28435 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: bType: 16 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: bSubType: 2 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Socket2 1: 180 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Query: INSERT INTO item (id, owner_id, item.window, pos, vnum, count, socket0, socket1, socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6) VALUES(2000000012, 1, 'MALL', 1, 61096, 1, 28433, 28434, 180, 72, 65, 71, 30, 5, 12, 9, 20, 12, 8, 0, 0, 0, 0)
This is the proto of that item:
61096 LaminaXPTO ITEM_WEAPON WEAPON_TWO_HANDED 3 ANTI_ASSASSIN | ANTI_SURA | ANTI_MUDANG | ANTI_DROP | ANTI_SELL ITEM_TUNABLE WEAR_WEAPON NONE 0 0 0 0 15 LEVEL 240 LIMIT_NONE 0 APPLY_ATT_SPEED 65 APPLY_ATTBONUS_HUMAN 55 APPLY_CRITICAL_PCT 50 0 550 650 600 700 70 0 3 -1
This is what I used to create it:
INSERT INTO `player`.`item_award` (`login`, `vnum`, `count`, `socket0`, `socket1`, `socket2`, `attrtype0`, `attrvalue0`, `attrtype1`, `attrvalue1`, `attrtype2`, `attrvalue2`, `attrtype3`, `attrvalue3`, `attrtype4`, `attrvalue4`, `mall`) VALUES ( 'admin', -- LOGIN 61096, -- ITEM ID 1, -- COUNT 28433, 28434, 28435, -- SLOTS 72, 65, -- DM 71, 30, -- DH, 5, 12, -- APPLY_STR 9, 20, -- APPLY_CAST_SPEED 12, 8, -- APPLY_POISON_PCT 1 -- LOCATION );
This is the result on item_award:
id pid login vnum count given_time taken_time item_id why socket0 socket1 socket2 socket3 socket4 socket5 attrtype0 attrvalue0 attrtype1 attrvalue1 attrtype2 attrvalue2 attrtype3 attrvalue3 attrtype4 attrvalue4 attrtype5 attrvalue5 attrtype6 attrvalue6 mall 19 0 admin 61096 1 1000-01-01 00:00:00 28433 28434 28435 0 0 0 72 65 71 30 5 12 9 20 12 8 0 0 0 0 1
And this is what I get when I open the mall:
id owner_id window pos count vnum transmutation socket0 socket1 socket2 socket3 socket4 socket5 attrtype0 attrvalue0 attrtype1 attrvalue1 attrtype2 attrvalue2 attrtype3 attrvalue3 attrtype4 attrvalue4 attrtype5 attrvalue5 attrtype6 attrvalue6 2000000012 1 MALL 1 1 61096 0 28433 28434 180 0 0 0 72 65 71 30 5 12 9 20 12 8 0 0 0 0
The Socket2 is getting fucked up and I have no clue why. I have no idea how the item type is being assumed as ITEM_UNIQUE.
Anyone has any idea on how to solve it?
For some reason the same db works on my other server and this issue doesn't happen, the only difference is the mysql database.
Thank you
16 hours ago, Karbust said:I'm having an issue with this and I have no idea what is causing it...
This is what I was able to gather, the issue is coming from this lines:
I put the code like this:
DWORD dwSocket2 = pItemAward->dwSocket2; sys_err("Socket2 0: %u", dwSocket2); sys_err("bType: %d", pItemTable->bType); sys_err("bSubType: %d", pItemTable->bSubType); if (pItemTable->bType == ITEM_UNIQUE) { #ifdef ENABLE_EXTEND_ITEM_AWARD // 12.04.2019 - Correction for unique items based on the real time. const long lValue0 = pItemTable->alValues[ITEM_SOCKET_REMAIN_SEC]; const long lValue2 = pItemTable->alValues[ITEM_SOCKET_UNIQUE_REMAIN_TIME]; const time_t tNow = CClientManager::instance().GetCurrentTime(); dwSocket2 = (lValue2 == 0) ? static_cast<DWORD>(lValue0) : static_cast<DWORD>(tNow + lValue0); sys_err("Socket2 1: %u", dwSocket2); #else if (pItemAward->dwSocket2 != 0) dwSocket2 = pItemAward->dwSocket2; else dwSocket2 = pItemTable->alValues[0]; #endif }
And this is the output:
SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Socket2 0: 28435 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: bType: 16 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: bSubType: 2 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Socket2 1: 180 SYSERR: Jan 14 20:31:34 :: RESULT_SAFEBOX_LOAD: Query: INSERT INTO item (id, owner_id, item.window, pos, vnum, count, socket0, socket1, socket2, attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3, attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6) VALUES(2000000012, 1, 'MALL', 1, 61096, 1, 28433, 28434, 180, 72, 65, 71, 30, 5, 12, 9, 20, 12, 8, 0, 0, 0, 0)
This is the proto of that item:
61096 LaminaXPTO ITEM_WEAPON WEAPON_TWO_HANDED 3 ANTI_ASSASSIN | ANTI_SURA | ANTI_MUDANG | ANTI_DROP | ANTI_SELL ITEM_TUNABLE WEAR_WEAPON NONE 0 0 0 0 15 LEVEL 240 LIMIT_NONE 0 APPLY_ATT_SPEED 65 APPLY_ATTBONUS_HUMAN 55 APPLY_CRITICAL_PCT 50 0 550 650 600 700 70 0 3 -1
This is what I used to create it:
INSERT INTO `player`.`item_award` (`login`, `vnum`, `count`, `socket0`, `socket1`, `socket2`, `attrtype0`, `attrvalue0`, `attrtype1`, `attrvalue1`, `attrtype2`, `attrvalue2`, `attrtype3`, `attrvalue3`, `attrtype4`, `attrvalue4`, `mall`) VALUES ( 'admin', -- LOGIN 61096, -- ITEM ID 1, -- COUNT 28433, 28434, 28435, -- SLOTS 72, 65, -- DM 71, 30, -- DH, 5, 12, -- APPLY_STR 9, 20, -- APPLY_CAST_SPEED 12, 8, -- APPLY_POISON_PCT 1 -- LOCATION );
This is the result on item_award:
id pid login vnum count given_time taken_time item_id why socket0 socket1 socket2 socket3 socket4 socket5 attrtype0 attrvalue0 attrtype1 attrvalue1 attrtype2 attrvalue2 attrtype3 attrvalue3 attrtype4 attrvalue4 attrtype5 attrvalue5 attrtype6 attrvalue6 mall 19 0 admin 61096 1 1000-01-01 00:00:00 28433 28434 28435 0 0 0 72 65 71 30 5 12 9 20 12 8 0 0 0 0 1
And this is what I get when I open the mall:
id owner_id window pos count vnum transmutation socket0 socket1 socket2 socket3 socket4 socket5 attrtype0 attrvalue0 attrtype1 attrvalue1 attrtype2 attrvalue2 attrtype3 attrvalue3 attrtype4 attrvalue4 attrtype5 attrvalue5 attrtype6 attrvalue6 2000000012 1 MALL 1 1 61096 0 28433 28434 180 0 0 0 72 65 71 30 5 12 9 20 12 8 0 0 0 0
The Socket2 is getting fucked up and I have no clue why. I have no idea how the item type is being assumed as ITEM_UNIQUE.
Anyone has any idea on how to solve it?
For some reason the same db works on my other server and this issue doesn't happen, the only difference is the mysql database.
Thank you
Related to my problem from above, and thanks to @ Abel(Tiger) for sending me this post by him:
This particular problem has been solved, but more issues arose.
First, if I added 3 stones, the 1st and 2nd slot would be set as 1 and only the 3rd would have a stone, that issue has been fixed by changing void ItemAwardManager::CheckItemSocket function's body to this:
void ItemAwardManager::CheckItemSocket(TItemAward & rkItemAward, const TItemTable & rkItemTable) { // check for limited time items auto hasTimeLimit = false; for (size_t i = 0 ; i < ITEM_LIMIT_MAX_NUM && !hasTimeLimit; i++) { if (LIMIT_REAL_TIME == rkItemTable.aLimits[i].bType || LIMIT_REAL_TIME_START_FIRST_USE == rkItemTable.aLimits[i].bType) hasTimeLimit = true; } // check slottable sockets for non limited time items const auto maxSockets = std::min<int>(rkItemTable.bGainSocketPct, ITEM_SOCKET_MAX_NUM); if (maxSockets <= 0 || hasTimeLimit) return; //This if's have been changed to check if the socket* is 0, and only then set it to 1 if (maxSockets >= 1 && rkItemAward.dwSocket0 == 0) rkItemAward.dwSocket0 = 1; if (maxSockets >= 2 && rkItemAward.dwSocket1 == 0) rkItemAward.dwSocket1 = 1; if (maxSockets >= 3 && rkItemAward.dwSocket2 == 0) rkItemAward.dwSocket2 = 1; }
Then another problem presented itself, if I set socket2 as 0, it wouldn't be changed to 1 on the function above, because it would edit the value on pItemTable and not on the variable dwSocket2 that is used on the query. This issue was fixed by changing this:
//Change the function call with this: ItemAwardManager::instance().CheckItemSocket(*pItemAward, *pItemTable, &dwSocket2); //Change the function header on ItemAwardManager.h with this: void CheckItemSocket(TItemAward & pkItemAward, const TItemTable & pkItemTable, DWORD *dwSocket2); //Change the function body with this: void ItemAwardManager::CheckItemSocket(TItemAward & rkItemAward, const TItemTable & rkItemTable, DWORD *dwSocket2) { // check for limited time items auto hasTimeLimit = false; for (size_t i = 0 ; i < ITEM_LIMIT_MAX_NUM && !hasTimeLimit; i++) { if (LIMIT_REAL_TIME == rkItemTable.aLimits[i].bType || LIMIT_REAL_TIME_START_FIRST_USE == rkItemTable.aLimits[i].bType) hasTimeLimit = true; } // check slottable sockets for non limited time items const auto maxSockets = std::min<int>(rkItemTable.bGainSocketPct, ITEM_SOCKET_MAX_NUM); if (maxSockets <= 0 || hasTimeLimit) return; if (maxSockets >= 1 && rkItemAward.dwSocket0 == 0) rkItemAward.dwSocket0 = 1; if (maxSockets >= 2 && rkItemAward.dwSocket1 == 0) rkItemAward.dwSocket1 = 1; if (maxSockets >= 3 && rkItemAward.dwSocket2 == 0) { rkItemAward.dwSocket2 = 1; *dwSocket2 = 1; } }
Then another problem come up, ITEM_UNIQUE would always replace the value you set on socket2 by the default value of the item, and to fix this, just change:
//This: if (pItemTable->bType == ITEM_UNIQUE) //With this: if (pItemTable->bType == ITEM_UNIQUE && pItemAward->dwSocket2 == 0)
Hope this helps someone.
- 13
- 2
- 3
-
- 49
- 8
- 2
- 13
-
6 minutes ago, 3bd0 said:
Hi,
Did anyone manage to use Cef (Chromium Embedded Framework) version 90 or newer with metin 2? While older versions work fine for me, newer version don't. When I open the browser the client just crash without any apparent reason.
Thanks.
With me it doesn't crash, but the window stays white for some reason...
-
Seems like that lib isn't static (it's dynamic), which means it will require that the to be placed on the same folder as the executable.
Ask the dev for the DLL.
This anti-cheat is being sold on metin2dev:
- 1
-
Did you add the path on the source? (The code on your last post.)
Did you import npc3 on Index or on source?
Did you replace the texture paths on the gr2 models with npc3?
-
Auth and chanel's are going to be accessible by the player, it's useless changing them because they can get them anyway.
-
The ones not blurred are on the official client:
The rest is probably some proprietary models.
-
3 minutes ago, Draveniou1 said:
In all versions there are loaded codes that load unjustly in freebsd example USB / CAMERA and many more it is in vain to unjustly load these systems
At this point I can't decide if you are just trolling or your are dumb as f***. You are talking about the drivers INSIDE THE KERNEL that's no system or software or none of that shit you have been talking about. If you want to remove this you just remove them from the fucking KERNEL and build it yourself. This doesn't affect performance at all.
Go ahead and report me for "bothering" your.
- 1
-
5 minutes ago, Draveniou1 said:
FreeBSD 13 Will it be clean or will all have these useless codes as in 11.4 ? If you notice FreeBSD loads close to 700 MB on a host medium these 700 MB ram is from bad code Thanks
Not sure what you are talking about, the screenshot I posted above is running on FreeBSD 13 and doesn't even reach 650MB of RAM and that's with 400MB of them being used by MySQL server...
-
Update
Added a slider component that can be enabled or disabled (enabled by default) (instructions on how to use it are available on the repository).
Changed from CRA (Create-React-App aka react-scripts) to Vite, which allows for a faster development, build time and reduced package size. Also replaced the compression method from "maximum" to "normal", since there is no difference in sizes, but takes much less time to build.
- 27
- 1
- 1
- 1
- 7
- 1
- 19
-
2 minutes ago, Draveniou1 said:
I do not know from freebsd why i am doing this message to find such a freebsd
edit:
@ Karbust I know only for SendMail but there are many other systems that load unjustly
That's why I said for you to learn it, test it and then share the results.
- 1
-
7 minutes ago, Draveniou1 said:
Try to find freebsd without useless codes active
And then you can tell me your time and your details in detail and you will notice big differences in speed your server and in gameBruh, you never tried it, but you are sure as fuck that it would work. I admire your confidence and persistence...
Learn FreeBSD, do it yourself and then share the results.
GR2 -> FBX Exporter [+ Source]
in Tools & Programs
Posted · Edited by Metin2 Dev
Core X - External 2 Internal
Without those changes: https://metin2.download/picture/KEsNS2jtTUTXw32WZKAw6YfAegY24ig8/.gif
With those changes: https://metin2.download/picture/fofDIklu9ykjoR2cBqPu1i3a3n8W9765/.gif
Code used (with it false that weird flying bug doesn't happen):
I attempted to apply that update to see if it would solve the left shoulder issue, but apparently it didn't.
To fix it manually just need to mirror Bone_shoulder_03 on XY axis and adjust the position manually.