Install Steam
login
|
language
简体中文 (Simplified Chinese)
繁體中文 (Traditional Chinese)
日本語 (Japanese)
한국어 (Korean)
ไทย (Thai)
Български (Bulgarian)
Čeština (Czech)
Dansk (Danish)
Deutsch (German)
Español - España (Spanish - Spain)
Español - Latinoamérica (Spanish - Latin America)
Ελληνικά (Greek)
Français (French)
Italiano (Italian)
Bahasa Indonesia (Indonesian)
Magyar (Hungarian)
Nederlands (Dutch)
Norsk (Norwegian)
Polski (Polish)
Português (Portuguese - Portugal)
Português - Brasil (Portuguese - Brazil)
Română (Romanian)
Русский (Russian)
Suomi (Finnish)
Svenska (Swedish)
Türkçe (Turkish)
Tiếng Việt (Vietnamese)
Українська (Ukrainian)
Report a translation problem
There is no help / faq / documentation for server-side mods so far. I'm sitting here since HOURS trying to figure out how to create a server-sided mod without much luck so far. I have the feeling I'm running circles and didn't get any step further.
The only hints regarding server-sided mods are from Jeed in this thread: https://steamhost.cn/steamcommunity_com/workshop/discussions/-1/594820473985166172/?appid=346110
But his mod is "private", you cannot download it from Mediafire without him allowing you to do so, he doesn't provide a source code and only posted some small code snippets which are not very helpful so far, because the most important parts are missing (hooks, initialization, declaration, used / linked libraries), etc.
I added him in Steam, he accepted the request, but didn't respond to any questions so far, even tho he was "Online" several times.
Thats really really frustrating. :(
At the moment, but we'll be able to do much more once the dev kit is updated.
I respond to everyone and I did respond to quite a few people already explaining many things.
As for the Mediafire links, they were public but I had to take them down because it wasn't supposed to be used on live servers, it was a very early prototype just to show the concept and that it can actually work, I thought I made that clear in my posts but apparently people have been already using it on live servers.
And as for the source, like I've already said, I will share the source once and if I ever finish something more valid for a use on live servers. Right now I'm just messing around with it for the fun of it, not for a practical use.
You made me sound like a douche man, that hurts
I saw you going "Online", "Idle", "Online", "Away", "Online", ... And I was always like "Awww ... Will he respond now? D:" ... "Now?" ... "Now?" ^^
I sent you like 20-30 messages: http://fs1.directupload.net/images/150615/x6u3v5hk.jpg
As I said in Steam chat, I know what to do, but not how to achieve it. Most difficult part for me right now is understanding how I can "hook" a function call and derive it to my own function.
The code snippets you posted look like you used parts of the ARK source, because you obviously could compile with FItemNetInfo, etc. Or did you recreate these structs and typedefs from the PDB?
I maybe go and patch the server .exe, but thats the last thing I want to do because it is brute.
I talked to at least 5 other people about that kind of stuff after my posts have been made. For a few hours with some of them.
I really don't know man, sorry.
Anyways, I didn't use their headers because like you said, they don't exist. I mean, they've never shared them (Oh how easy would it be if they did... One can only dream ;)).
I used IDA to get a pseudo C code and 64dbg to actually debug the server during runtime.
As for the class structures such as FItemNetInfo, I just typedef'ed all these as DWORD64.
When a class structure is being passed as an argument, it's always a reference to the class (a pointer to the class).
Even if you re-construct the constructor to make a copy of the class object (kind of like with structs), it's still a pointer to the copied (new) class object.
So you don't really need the entire structure of the class to be able to just hook most functions.
As for changing stuff, the information is in the PDB and can easily be seen in IDA (or similar tools).
When you hook a function, you don't HAVE to also replicate its logic in your hooked function.
Sometimes it's enough to just edit the values you want to edit and then call the original function (or sometimes call the original function and edit the needed values after). As I've shown in those examples in the other thread.
In the latest example I explained how I managed to increase the value you get on your stats per point you put into it.
Let's break it down a little:
A. Naming convention. Because we have the PDB, we see normal naming convention and just by searching through all the symbols in the debugger (or any PDB viewer I guess, I'm sure you'll find many on Google) we will find most functions eventually.
If we didn't have the naming convention we'd have to backtrace to that function, in online games it's usually done by placing a breakpoint on the "send"/"sendto"/"WSASend"/"WSASentTo" function(s) and then slowly following the stack back to find where the change actually happens. But that's a whole different story as we have the PDB.
So... I've been going through some functions that seemed related to what I was trying to achieve. The first one didn't hit the breakpoint, the second one hit the breakpoint constantly and finally the third one ("UPrimalCharacterStatusComponent::ServerApplyLevelUp") hit the breakpoint only when I've put points into stats. So there we go, I've found the function (or at least a related one, but for the sake of simplifying the breakdown, this was the one).
A. Well, first of all, since stats have different increment value per point there could only be only three ways for them to increase the stats:
- They have an if statement for each stats (or at least for stats that share the same increment value) where inside the if's blocks the increment happens or the increment value is being assigned to a reference/other variable to be used later.
- They have an array of the different increment values and somewhere in the function (or in the parameters) they have an index that points to the specific increment value in the array.
- They have a call to a function that does one of these 2 things.
The 1st is overall very unlikely to be there if done well, if both the 1st and the 2nd cannot be found it's most likely the 3rd.Looking at IDA's pseudo C code: http://pastebin.com/QCMDv2zK we can see right away "EPrimalCharacterStatusValue::Type LevelUpValueType" parameter right away. That means it's the 2nd of that list.
Exploring this we see an enum that looks like this (as posted in that other thread):
Scrolling down in the pseudo code we see that IDA named the stack variable that holds the argument to "v3".
Looking at what is using v3 further down we see all bunch of arrays and if we follow the logical naming convention we can spot our array right away, "AmountMaxGainedPerLevelUpValue".
"AmountMaxGainedPerLevelUpValue" is being pointed to by "v5" at offset 0x218, scrolling back up to see what "v5" is, it's basically "this" (the "UPrimalCharacterStatusComponent" class object).
* "this" is there because of how IDA translates calling convention, I have a suggetion about this for you a little bit down below, about hooking, naming convention, etc.
So now we don't really need to rebuild the entire class structure if that's all we want to change.
All we need to do is to wrap that class, or just use pointers (honestly that depends on what you want to do, it might be better to wrap the class for bigger and complicated things or keep it with pointers for smaller things).
So.. after this huge WoT, we get a very simple pointer and the following is basically it - a pointer to "SpeedMultiplier":
The implementation of this doesn't have to be at "ServerApplyLevelUp" (and it shouldn't, for optimization purposes, since it only needs to be changed once).
But you must change it in a function where you get a pointer to the "UPrimalCharacterStatusComponent" class object. The constructor of that class is a good place.
A. Google is your friend. If you really want I can give you my CHook64 class for 64-bit hooking, but like my note a little bit above said, this is my suggetion:
I really suggest you'll learn this yourself. As it will help you understand the goods and the bads and all of the aspects of hooking, like calling convention while hooking or how stack is being managed (or not managed ;)) with different types of hooks (I use jmp hooks which have different results and aspects from different type of hooks).
* You can also use Windows Detours[research.microsoft.com] but I wouldn't ever touch this when we have many other native ways to achieve hooking without a library dependency.
I strongly suggest you learn this and experience this by yourself, especially if you don't have experience with it like you said. Because sometimes you might not be able to get something to work or get a very strange result/behavior and you wouldn't know why if you don't have that kind of background. But do as you wish of course :)
Once we hook the function it would be like this (in this example we call the original function, sometimes you might not want to, if you want to disable a certain functionality or completely re-write it on your own):
There's a lot more to hooking and it can be a very powerful tool for modding when an official API is not given.
If you ever saw other serverside mods like SourceMod, you probably saw you have pre-call events and post-call event. Wihtout an official API, this is only possible with hooks and it adds a whole new layer of possibilities for server modding functionality.
For example, if you have a "Superhero mod" where someone has a "passive power" that can only be triggered once every 120 seconds where if the player takes lethal damage (enough damage to kill the player), it will leave it at 1 HP instead.
This can only be done without calling the original function at all or with doing some extra logic before (pre-call) the original function is being called (like changing the damage to "CurrentHP - 1").
However, if you have a "Vampire skill" (steals life based on damage dealt) and you don't want/know how to calculate damage yourself, you hook the damage function and then after you call the original function (post-call) you add HP to the attacker based on the damage he/she dealt.
I felt like this was important enough to include because it seems like you want to mod damage on buildings, the concept should be the same :)
WoT? WoT!
(Had to split it because of Steam's limit.. Sorry)
Anyways, good luck!
Oriya.
Wow, thanks for your detailed answer mate!
Problem is really just how to hook the APrimalStructure::TakeDamage function.
I already figured out everything I need. And when patching the code in the debugger it already works great.
I'm already digging through Google since yesterday and there is basically tooooo much information available.
And all that is complete Chinese to me. I never ever had do do something like that in my career. And above that I don't really like C++ either ... I'm a Delphi programmer. :D
I found some Function Route example in a russian forum: {LINK REMOVED}http://cs.rin.ru/forum/viewtopic.php?f=20&t=51705 But thats 32bit.
Would've been great to have some source available to learn from. But nevermind, don't want to bother you much more. You already helped me alot.
I will bite through. Thank you! :)
Once your ureal account has the github email you will get two emails from unreal. one will be for the unrealengine.com successful github associate. the second will be from the unreal github. You need to accept the unreal github email invite (check your junkmail) BEFORE you will have access to github.com/StudioWildcard1/Ark-Dev-Kit
additional corrections/info. github has no checkout feature. at least from our perspective. it's either download, clone, or fork. release 4.8 does not seem to have a unreal4edit.exe.