server without SafeWriting, is it possible?

Page: 1 2 3 4 5 6 7 8 9 

  • golden_elite13

    Hi all. I would like to setup a crymp server but I want to know if it is possible to get it on the crymp Network without using the SSM SafeWriting ? I don't say I don't want to use this Mod but i would know if it is possible to appear on the CryMP servers list with others SSM, or if it absolutely needs the SFW dll and lua parts. Thank you :)

    0
  • Zi;

    Well, of course it is possible without SSM SafeWriting, but you are gonna face lot of coding to make it appear on CryMP

    0
  • golden_elite13

    Thank you for reply Zi;
    I know it needs a lot of code to do that, and that's why SafeWriting exists but if I still want to use another SSM, would you explain me how to make the server appear on the list ? Is it possible only in lua ?(so without the sfw dll?) I know it's not smart to ask for that, because SafeWriting already exists but I really would to try others SSM for my server to make it a bit different from Sfw ^^ Could you say quickly the way do to this ?

    0
  • misterSD

    It is possible with Cryfire.

    0
  • Comrade

    Open your CryNetwork.dll in some editor like Notepad++: press Ctrl + F, select Replace and use it to replace "gamespy.com" with "openspy.org" (click on Replace All). After this "patch" you can use any SSM you want or even server without any SSM... but there's big but - your server will be visible only on that classic server list (Crysis main menu > Multiplayer > Internet game). If you want to have your server on console server list and also here /master.php you will have to use SSM SafeWriting or SSM CryFire or as Zi said you can code it for your SSM. Ask Zi for more info about how CryMP master works. :)

    0
  • golden_elite13

    Thank you for reply Comrade, i'll try this ^^

    0
  • Zi;

    Well, that makes you appear only in ingame serverlist, but not at CryMP.net webpage.
    Yes it is possible only with Lua, but first you need to download some external application like cURL to be able to connect HTTP from Lua, then you need to send HTTP requests to CryMP using cURL, for example you could simply do: os.exec("curl.exe http://crymp.net";) in Lua, if you are able to do this already, I can describe further way to make yourself appear on official server list

    0
  • golden_elite13

    Thank you for reply zi;
    I know cURL but never used it ^^ i can try anyway xD ; however it's not a problem If I can't do that, it's simply for fun (and my curiosity). Thank you for your informations Zi; :)

    0
  • golden_elite13

    okay i downloaded curl and it is ready to use, "os.execute("curl.exe http://crymp.net";)" works, but now i don't know lua code to get the server on CryMP ^^

    0
  • Zi;

    So, to get input from curl, you should do it like this:
    os.execute("curl.exe http://crymp.net > output.txt") and read output.txt later
    function http_request(url)
        os.exec("curl.exe \\""..url.."\\" > output.tmp")
        local f,err=io.open("output.tmp","r")
        if f then
            local content=f:read("*all")
            f:close()
            return content
        else return nil end
    end

    Now you need URL encode function, which could work like this:
    function urlencode(str)
        return str:gsub("[^a-zA-Z0-9]",function(chr) return string.format("%%%02X",chr:byte(1,1)) end)
    end


    0
  • Zi;

    Now when this is done, look SafeWritingMain.lua from SafeWriting.pak for further implementation of protocol, you basically need to register server and later update it inside network.
    To find given code, simply search for "reg.php" and "up.php"

    So far you register your server at CryMP by connecting to /api/reg.php and provide details in GET or POST params, it doesn't matter, (GET params are those inside URL, like thread.php?id=123... so GET param "id" equals "123" now), after successfuly registered, you should retrieve token, which will later be used to update your server in the list.

    For example
    --mapPath should look like this: multiplayer/ps/mesa
    function register_server(port, name, numPlayers, maxPlayers, mapPath, mapDownloadLink, timeLeft)
        mapDownloadLink=mapDownloadLink or "" -- http link to map download
        timeLeft=timeLeft or 0 --remaining round time in seconds
        local result = http_request("/api/reg.php?ver=6156&port="..urlencode(port).."&name="..urlencode(name).."&numpl="..numPlayers.."&maxPl="..maxPlayers.."&map="..urlencode(mapPath) ... and so on...)
        local token=string.match(result,"<<Cookie>>([a-z0-9]-)<<")
        return token
    end


    Updating server is similar to this, only you need to pass token as "&cookie=" inside URL to /api/up.php

    0
  • golden_elite13

    Thank you Zi; ^^
    I tried all this and it seems to work.. but not totally, i don't think if the updating is made.. players list don't appear on the list and we cannot see the max players number..
    but that's not all, sfwcl players haven't any valid profileID on my server (all are "0")...
    I'll be happy if you explain me how to get all work^^ Thanks a lot :)

    0
  • golden_elite13

    Or maybe all the answers i'm searching for are in SafeWritingMain.lua but it'a bit messy in this script.. maybe i don't see all necessary informations (and code)

    0
  • Zi;

    Well, here comes the problem, profile ID will always be 0, thing is SSM SafeWriting uses custom profile ID implementation not based on game one, player.profile corresponds to profile ID, so it can be changed anytime by Lua, I don't know how about Phoenix/Patriot though, I think there is function player.actor:GetProfileId(), but no idea how it is implemented.

    About max players, I am sorry, I made a typo in my answer :D it isn't &maxPl, but just &maxpl - all lowercase.

    Now for players list, it works like this:
    Iterate over each player and append to player string in format: @name%rank%kills%deaths%profileId
    Pass the string to server as &players=...

    So code:
    function build_players_string()
    	local players = g_gameRules.game:GetPlayers() or {}
    	local plstring = ""
    	for i,v in pairs(pls) do
    		if v and v.GetName then
    			plstring=plstring.."@";
    			local name=v:GetName();
    			local k,d=GetPlayerScore(v); --change this according to SSM Patriot to get kills and deaths into k,d variables!!!
    			local rank=0;
    			if g_gameRules.class=="PowerStruggle" and g_gameRules.GetPlayerRank and v and v.id then
    				rank=g_gameRules:GetPlayerRank(v.id) or 1;
    			end
    			local id=v.profile;	--change this according to SSM Patriot to pass profile ID of player!!
    			local str=name.."%"..rank.."%"..k.."%"..d.."%"..id;
    			plstring=plstring..str;
    		end
    	end
    	return plstring
    end


    0
  • Zi;

    And now to assign profile IDs accordingly, when player connects, they pass !validate profile uid name to authenticate
    So all you gotta do is validate if it's not spoofed by connecting [b]/api/validate.php?prof=...&uid=...[/b], if you get response "%Validation:Failed%", then it's failed, otherwise change player's profile ID accordingly to command, for further details see ServerFolder/ChatCommands/Validation.lua :D

    Also you should skip checking profile IDs, if user passes ID in range 800000 - 1000000 in !validate command, that means it's temporary unregistered account / not logged in. :D

    0
  • golden_elite13

    Thank you Zi, i will try this^^

    0
  • Zi;

    By the way, if you open latest SafeWritingMain.lua, yeah it is a little bit mess, but all required code is located on lines from 557 to 644

    0
  • golden_elite13

    Yes it's where i was looking to compare with my code, but even after correcting and veryfing the players max numbers doesn't change :/ always and 0, maybe the http request has something false... Is the order important ? ("&port" before "&maxpl" etc..)
    I think the problem is in the updating function because my server appear on the list few seconds after i launched it.. and disappears.
    Mmmh and I don't know on what "frequency" has to be the updating function ? Or what other func calls it ??

    0
  • Zi;

    Order isn't important, just make sure everything is lowercase in names of params (&port=...&maxpl=...), frequency is good when it's around 45 seconds, even 30 seconds is welcome, but that is little overkill :D

    Only important order is to connect reg.php first and then only up.php to update

    0
  • Zi;

    Don't forget to pass &cookie=... token in every up.php request (token you got in reg.php), for example if response was <<Cookie>>blablabla<<, token is "blablabla", so you pass &cookie=blablabla into every next request. Also try passing empty "&pass=" in every up.php request, that's used when server has no password

    0
  • golden_elite13

    Yes i think what i did is corrects, but i don't know why it don't works xD
    I can show you my code : (i didn't make the repeat of the updating function yet)

    Server = {};
    local port = System.GetCVar("sv_port") or 64087
    local name = System.GetCVar("sv_servername")
    local numPlayers = 0
    local maxPlayers = tonumber(System.GetCVar("sv_maxplayers")) or 16
    local mapPath = System.GetCVar("sv_map") or ""
    local mapDownloadLink = ""
    local desc = "Test_noSFW"
    local rank = System.GetCVar("sv_ranked") or 0
    local pass = System.GetCVar("sv_password") or ""
    
    function Server:RequestHTTP(url)
    	os.execute("curl.exe ""..url.."" > output.tmp")
    	local f,err=io.open("output.tmp","r")
    	if f then
    		local content=f:read("*all")
    		f:close()
    		return content
    	else return nil end
    end
    
    function urlencode(str)
    	if type(str)=="string" then return str:gsub("[^a-zA-Z0-9]",function(chr) return string.format("%%%02X",chr:byte(1,1)) end)
    	else return str end
    end
    
    function Server:Register(port, name, numPlayers, maxPlayers, mapPath, mapDownloadLink, timeLeft)
        mapDownloadLink=mapDownloadLink or "" -- http link to map download
        timeLeft=timeLeft or 0 --remaining round time in seconds
    	pass = System.GetCVar("sv_password") or ""
        local result = Server:RequestHTTP("/api/reg.php?ver=6156&port="..urlencode(port).."&name="..urlencode(name).."&desc="..desc.."&pass="..pass.."&numpl="..numPlayers.."&maxpl="..maxPlayers.."&map="..urlencode(mapPath).."&ranked="..rank.."&timel="..timeLeft.."&local=localhost";);
        local token=string.match(result,"<<Cookie>>([a-z0-9]-)<<")
        return token
    end
    
    local cookie = Server:Register(port, name, numPlayers, maxPlayers, mapPath, mapDownloadLink, g_gameRules.game:GetRemainingGameTime())
    
    function Server:Update(token)
    	local result = Server:RequestHTTP("/api/up.php?&port="..urlencode(port).."&numpl="..numPlayers.."&name="..urlencode(name).."&desc="..desc.."&pass=".."&ver=6156".."&cookie="..token.."&map="..urlencode(mapPath).."&ranked="..rank.."&timel="..g_gameRules.game:GetRemainingGameTime().."&local=localhost";)
    	System.LogAlways("-----UPDATING------")	 --not finished but it should at least show max players number at startup.. 	
    end
    
    Server:Update(cookie)


    0
  • Zi;

    Hmm, this seems to work, you call :Update() every 45s, right? :D

    I would change a code little, so it remembers token for later use
    Server = {};
    local port = System.GetCVar("sv_port") or 64087
    local name = System.GetCVar("sv_servername")
    local numPlayers = 0
    local maxPlayers = tonumber(System.GetCVar("sv_maxplayers")) or 16
    local mapPath = System.GetCVar("sv_map") or ""
    local mapDownloadLink = ""
    local desc = "Test_noSFW"
    local rank = System.GetCVar("sv_ranked") or 0
    local pass = System.GetCVar("sv_password") or ""
    
    function Server:RequestHTTP(url)
    	os.execute("curl.exe \\""..url.."\\" > output.tmp")
    	local f,err=io.open("output.tmp","r")
    	if f then
    		local content=f:read("*all")
    		f:close()
    		return content
    	else return nil end
    end
    
    function urlencode(str)
    	if type(str)=="string" then return str:gsub("[^a-zA-Z0-9]",function(chr) return string.format("%%%02X",chr:byte(1,1)) end)
    	else return str end
    end
    
    function Server:Register(port, name, numPlayers, maxPlayers, mapPath, mapDownloadLink, timeLeft)
        mapDownloadLink=mapDownloadLink or "" -- http link to map download
        timeLeft=timeLeft or 0 --remaining round time in seconds
    	pass = System.GetCVar("sv_password") or ""
        local result = Server:RequestHTTP("/api/reg.php?ver=6156&port="..urlencode(port).."&name="..urlencode(name).."&desc="..desc.."&pass="..pass.."&numpl="..numPlayers.."&maxpl="..maxPlayers.."&map="..urlencode(mapPath).."&ranked="..rank.."&timel="..timeLeft.."&local=localhost";);
        local token=string.match(result,"<<Cookie>>([a-z0-9]-)<<")
        self.token=token;
        return token
    end
    
    local cookie = Server:Register(port, name, numPlayers, maxPlayers, mapPath, mapDownloadLink, g_gameRules.game:GetRemainingGameTime())
    
    function Server:Update(token)
            token = token or self.token;
    	local result = Server:RequestHTTP("/api/up.php?port="..urlencode(port).."&numpl="..numPlayers.."&name="..urlencode(name).."&desc="..desc.."&pass=".."&ver=6156".."&cookie="..token.."&map="..urlencode(mapPath).."&ranked="..rank.."&timel="..g_gameRules.game:GetRemainingGameTime().."&local=localhost";)
    	System.LogAlways("-----UPDATING------")	 --not finished but it should at least show max players number at startup.. 	
    end
    
    Server:Update()


    Because if you don't call :Update() frequently, your server will disappear from serverlist after some short time
    Also &local shouldn't be localhost, but local IP of computer, like censored#2b4ea002, but that doesn't matter so much, that's just in case you had more computers at home under same IP and wanted to connect server running on different one :D

    0
  • golden_elite13

    For now Update is called 1 time but i will change it
    Except this, it should work as you say but the max players number stays to 0 :'(
    And i haven't do the players score list yet.
    thank you for your help ^^

    0
  • Zi;

    Yeah, you must call it frequently, not just once, after that it will work 100% :D Ah, you need to pass &maxpl= also in Update call, you forgot to pass it! That's why there is problem. Anyways, it's strange, because there are several records on masterserver which show you successfuly had "32" as maxplayers on your server :D

    0
  • Zi;

    If you want to ease job of those params passing into HTTP, you can just use this function from my SSM

    function urlfmt(fmt,...)
    	local args={};
    	for i,v in pairs({...}) do
    		if type(v)=="string" then
    			args[i]=v:gsub("[^a-zA-Z0-9]",function(c) return string.format("%%%02X",string.byte(c)); end);
    		else args[i]=v; end
    	end
    	return string.format(fmt,unpack(args));
    end


    And just use: urlfmt("/api/up.php?numpl=%d&map=%s...",numPlayers,mapPath)

    0
  • golden_elite13

    32 maxplayers xDD i have set 16 xD yes it's a bit strange
    and yes i forgotten maxpl in update func, thank you ^^

    0
  • golden_elite13

    So I have to write : RequestHTTP(urlfmt("/api/up.php?numpl=%d&map=%s...",numPlayers,mapPath)) right ?

    0
  • Zi;

    Maybe mistake is in tonumber(System.GetCVar("sv_maxplayers")) returning 0 for no reason :D
    Yes, isn't that easier than "..urlencode(...).."? u_u

    0
  • Zi;

    I think it's good idea to actually print full URL that is passed to RequestHTTP just for debug if something doesn't work as expected

    0
  • Zi;

    Ahh, so all of sudden it was little problem on master side :D so I resolved it, it should work alrighty now

    0
  • golden_elite13

    I afk some minutes, let me say if you know where does it bug :/

    0
  • Zi;

    It is fixed already u_u Max players should work normal now, it was just cache error

    0
  • golden_elite13

    Oh okay xD yes it's now "0/16" thank you Zi ^^
    i'm curious to know what was the problem ? xD

    0
  • golden_elite13

    Sorry sometimes i don't see see your messages, the forum doesn't work in real time :P

    0
  • Zi;

    Yeah, it's not facebook to work in real-time... it was just problem in cache, thing is if your server is unactive for < 4 hours, master still keeps it in memory with last data and next time you call reg.php, it will return same token and act like up.php, and because up.php doesn't care about maxpl, it would never update maxpl = cache problem.

    Meaning of this whole thing is that your server will work even if CryMP has shorter service outage, so it restores old token for you. :D

    0
  • golden_elite13

    Oh okay xD
    thank you for your help Zi ^^ Tomorrow i will work for the profile ID problems and then the server will works :D
    See you :p

    0
  • Zi;

    Sure, that is already smallest part :D Easiest one

    0
  • golden_elite13

    Hi Zi, validation on my server don't seem to be the easiest part xD
    I did the !validate command correctly like on your SSM, but the problem is "player.profile" doesn't exist, so it can not take a value. And player.actor:GetProfileId() is a function of phoenix (dll) so we cannot modify it, and this functions always return 0 because it don't care of Sfwcl profiles :/

    0
  • golden_elite13

    Or maybe this is because player.profile doesn't have any value and maybe there is a bug in my my function (with http request etc) so the player.profile stay without any value :\ I don't know

    0
  • golden_elite13

    Here are my validating functions : (Picked in your SSM but simplified)
    function Master:AttemptValidate(player,pid,uid,name,attempt)
    	local req = urlfmt("/api/validate.php?prof=%s&uid=%s",pid,uid);
    	local result = Master.RequestHTTP(req);
    	if result then
    		local err=string.find(result,"%Validation:Failed%",nil,true);
    		if err then
    			printf("Validation error: %s",tostring(err));
    			player.profile=math.random(800000,1000000);
    		else
    			printf("Validation success for %s/%s",name or "<unknown>",player:GetName() or "<unknown>");
    			player.profile=pid;
    			g_gameRules.game:RenamePlayer(player.id, name);
    			_G["ValidIds"]=_G["ValidIds"] or {};
    			_G["ValidIds"][uid]=pid;
    		end
    	else
    		if attempt<4 then
    			printf("Validation warning: %s , attempt: %d",tostring(error),attempt+1);
    			AttemptValidate(player,pid,uid,name,attempt+1);
    		else
    			printf("Validation error: %s",tostring(error));
    			player.profile=math.random(800000,1000000);
    		end
    	end
    end
    
    
    
    AddChatCommand("validate", {args={"pid", "uid", "name"}, info="Used by sfwcl to login"}, function (player, pid, uid, name)
    	Script.SetTimer(1,function()
    		if pid and uid and name then
    			local numpr=tonumber(pid);
    			if numpr and uid=="200000" and numpr>=800000 and numpr<=1000000 then
    				player.profile=pid;
    				g_gameRules.game:RenamePlayer(player.id,name)
    				return;
    			end
    			
    			if _G["ValidIds"] and _G["ValidIds"][uid]==pid then
    				player.profile=pid;
    				g_gameRules.game:RenamePlayer(player.id,name)
    				return;
    			end
    			Master:AttemptValidate(player,pid,uid,name,0);
    		end
    	end);
    end);


    0
  • Zi;

    Well, I think you can edit Phoenix functions though :D

    Like this:
    AddChatCommand("validate", ..., function(player, ...)
    	player.actor.parent=player;
    	player.actor.GetProfileId = function(self)
    		return self.parent.profile;
    	end;
    	-- other your code
    end);


    In Lua you can overwrite existing functions on objects.

    0
  • golden_elite13

    It seems to be good to use but, when others patriot scripts call "player.actor:GetProfileId()", the result will be the same as here ? All the function is overwritten or it's simply here and i will get a profileID=0 on other patriot scripts ?

    0
  • golden_elite13

    The thing i want is : player.actor:GetProfileId() always return player.profile when the result is "0", or return the result of the original function when it is not 0 xD It is that on the all mod ?? (maybe i'm an idiot as well^^')

    0
  • golden_elite13

    Oh and it's not the only problem, i shown you my code because player.profile isn't retrieved with the http request :/ it gives a nil value.
    Maybe it's a problem with _G["ValidIds"], doesn't exist so it doesn't give the value to player.profile

    0
  • Zi;

    Overwriting function once should overwrite it everywhere for Patriot, so it should work. Original function will always return 0 anyway since GameSpy is down. So there is no reason to return old function. _G["ValidIds"] is created automaticaly inside :AttemptValidate, it serves just as cache for old known UIDs, so if player once checked, next time you will just reuse old values.

    0
  • Zi;

    What does your server write in logs, how far does it get? Does it assign player.profile=pid in :AttemptValidate?

    0
  • golden_elite13

    Okay , but for the old function it works for GerCry accounts because it overwrites gamespy profileID ,
    So if one player hasn't sfw and want to play on my server with a valid profileID, he can (it was my case before, i used gercry on crymp servers because sfwcl doesnt work for me (always crashed :/ )
    And for logs i can't tell this now i turned off my computer , go to school tomorrow xD i ´ll see that when i get time
    Thx for answers^^

    0
  • Zi;

    Well, it's really not good idea to trust GerCry IDs, because they can be spoofed, SSM SafeWriting treats them as 0 and overwrites them with random number from 800000 to 1000000, so you should do the same. CryMP IDs can't be spoofed, they are always verified by master in validation process, so you can fully trust them :D You know, it would suck if you have CryMP ID 17000, you set it as admin, then GerCry player comes with ID 17000 and suddenly he is admin?! :D That would be problem!

    0
  • golden_elite13

    Okay Zi ^^ in that case i'll not trust gercry IDs xD

    0
  • golden_elite13

    Or maybe i can verify Them too ? I think all gercry profiles ids are values > 100000000, so if a value is not approved in crymp and not superior to this number => set a random id :D could it works ? ^^'

    0
  • Zi;

    Sure, you can handle them anyway you want. :D

    0
  • golden_elite13

    Thank you Zi; :) however I have to overwrite the function of GetProfileId() out of the command !validate, to make it permanent since patriot startup

    0
  • Zi;

    You can overwrite in OnClientConnect I think, that's ideal

    0
  • golden_elite13

    Okayy so I have added in the patriot gamerules file (which overwrites original gamerules) the function g_gameRules.Server:OnClientConnect(channelId, name, reset.. or some args like that)
    This function equals to the original game function but I added a new line after "local player = self:SpawnPlayer(channelId, name)"
    This line is OverwriteProfileIdFunction(player), who calls the following function when a player connects to server :

    function OverwriteProfileIdFunction(player)
    	player.actor.parent=player;
    	player.actor.GetProfileId = function(self)
    		if (self.parent.profile) then
    			return self.parent.profile
    			-- But the function is not completed,
    			-- I don't only want to return player.profile
    			-- But before, verify if the original "player.actor:GetProfileId()"
    			--  doesn't return a player ID =/= 0
    			-- if yes, return this ID. How to do this ?
    		end
    	end
    end


    0
  • Zi;

    Ummm, that's a really good question, but I think this should work:

    function OverwriteProfileIdFunction(player)
    	player.actor.parent=player;
    	if not player.actor.OriginalGetProfileId then
    		player.actor.OriginalGetProfileId=player.actor.GetProfileId
    	end
    	player.actor.GetProfileId = function(self)
    		if self.parent.profile then
    			local originalId = self:OriginalGetProfileId()
    			if tonumber(originalId)~=0 then
    				--handle this however you want
    				return originalId
    			else
    				return self.parent.profile
    			end
    		end
    	end
    end


    Or just simply do this:

    function OverwriteProfileIdFunction(player)
    	player.actor.parent=player;
    	local originalId=player.actor:GetProfileId()
    	if tonumber(originalId)~=0 then return originalId end --just return it right away, no rewriting needs to be done
    	player.actor.GetProfileId = function(self)
    		if self.parent.profile then
    			return self.parent.profile
    		end
    	end
    end


    But I think first way is better, it's more general :D

    0
  • golden_elite13

    Thank you, i'm going to try this :D

    0
  • golden_elite13

    It would be great if the function work but I can't test it -_-
    The problem is.. the function "OnClientConnect" (at begin this event is not in patriot code but i added it myself and it don't works.. i already renamed it by all functions names i could think : InstantAction:OnClientConnect, g_gameRules:OnClientConnect etc.. but never changed : it is never called. I know it because i added a "System.LogAlways("This function is called") into the function but the message never appear... i tested if others events that already are in patriot gamerules.lua are called and yes , they work.. (they show a console message if i write System.LogAlways("blabla...) so my question is: how to get my function OverwriteProfileIdFunction called with a valid parameter 'player'.

    0
  • Disturbed

    golden_elite13 What do you want to do to create your own server side similar to Crymp.net?

    0
  • golden_elite13

    No such idea xD it's just i don't like safewriting , not too "comfortable" to me to use and program ^^' but There is no problem :)
    And thus i improve some of my "programming" and lua knowledge thx to Zi :)

    0
  • golden_elite13

    I don't need anyone Zi is already helping me for all of this :) but you can tell me what you want sure :)

    0
  • Zi;

    Actually, saying SafeWriting is not "comfortable" is weird, it would ease you all the work, lol, you can hook up functions without rewriting InstantAction.lua etc there, like:

    SafeWriting.FuncContainer:AddFunc(function(player) --gets called when player connects
        printf("%s connected",player:GetName() 
    end,"OnClientConnect")
    AddChatCommand("kick",function(self,player,msg,target)
        if not target then Chat:SendToTarget(player,"Enter valid player") return; end
        Kick(target) --no need for GetPlayerByName, target is automatically player already
    end,{PLAYER},{AdminModOnly=true}); --automatically filling player as param into func

    or
    AccuracyCalc={};
    function AccuracyCalc:OnShoot(hit)
         if hit.shooter then
              hit.shooter.shotsFired = (hit.shooter.shotsFired or 0)+1
         end
    end
    function AccuracyCalc:OnActorHit(hit)
         if hit.shooter then
              hit.shooter.shotsHit = (hit.shooter.shotsHit or 0)+1
         end
    end
    AddChatCommand("accuracy",function(self,player)
         local shot=player.shotsFired or 0
         local hit=player.shotsHit or 0
         local ratio=hit/math.min(1,shot)
         Chat:SendToTarget(player,"You fired %d shots and hit %d times, accuracy: %.2f",shot,hit,100*ratio)
    end);
    SafeWriting.FuncContainer:AddPlugin(AccuracyCalc) --binds all funcs (OnShoot, OnActorHit)


    I think that's nice feature that other SSMs don't have, anyway, try rewriting :RevivePlayer inside InstantAction.lua or some PatriotHooks.lua or whatever there is :D

    0
  • Zi;

    You can call OverwriteProfileIdFunction anywhere in code, it detects if function is overwritten or no, so there is no problem how many times you call it :D Try calling that in :UpdatePings, I think that is effective enough (it's called 30x/s I think)
    Just simply like this:
    if not player.actor.OriginalGetProfileId then OverwriteProfileIdFunction(player) end

    If it's overwritten, it won't do anything already :D

    0
  • golden_elite13

    Thank you i will try that :)
    And Well i don't make critics about your SSM ^^ it's just my choice to not use it ^^'


    0
  • golden_elite13

    Thank you Zi; :DDDD
    All is working now, crymp profiles IDs are valided and permanent GerCry's accounts too :)

    0
  • Zi;

    I am glad to hear that :D

    0
  • Zi;

    Maybe you could share your code here for other Patriot users in future looking for same thing

    0
  • golden_elite13

    Well I think i'm the only one who wants to use Patriot for a crymp server, so it's not useful to set all code here :D others prefer the ease :)
    Anyway if you think about VenomX, tell me that ^^

    0
  • golden_elite13

    And then... the most of code to get all this work is in this thread :P

    0
  • golden_elite13

    I forgot to ask you something Zi, does it change something to register/upload the server on "openspy.org" instead of crymp.net ?

    0
  • golden_elite13

    And... wanted to ask you another thing too xD is it possible to send message to players like in Wars with "TextMessageBig" but with another way ? I know it's possible because Sfwcl does it with the function CryAction.Persistant2Dtext when connecting to a server (It's written "Connecting, please wait.." or something like that in center~bottom of the screen) but i would do it in the server-side code for players I want, but the function "Persistand2Dtext.." is for client-side executed lua scripts, right ?

    0
  • Zi;

    Open CryNetwork.dll in some better editor (Notepad++, definitely simple Notepad), find all occurences of "gamespy.com" and change it to "openspy.org"

    And nah, it's not possible from server side, sfwclient does it only from client side and only when connecting server from website list

    0
  • golden_elite13

    I didn't want to set openspy.org in crynetwork.dll, i simply asked if it changes something to register the server on openspy.org ? Because safewriting is doing it with "sv_master openspy.org" and make the HTTP Connection to this website instead of crymp.net. But why ?

    And for the function of persistand2Dtext, you tell me it's not possible but on MESA Nostalgia server, we sometimes get this type of message from the server, exactly like the sfwclient does. So it could exist a way to do it in the server xD

    0
  • Zi;

    Noo, that's wrong, sv_master doesn't set HTTP master, but GameSpy protocol master = original server browser. Sv_master actually does what editing DLL would do. SafeWriting HTTP master is set only in Settings, not server.cfg :D

    So if you also wanna have server being listed in that nice ingame server list like in old times, just edit DLL and change gamespy.com to openspy.org

    0
  • golden_elite13

    Okay thank you :D it was just to know ^^

    And you didn't answered to my last lines :)

    0
  • Zi;

    I answered, in post before

    "And nah, it's not possible from server side, sfwclient does it only from client side and only when connecting server from website list"

    MESA Nostalgia uses Flowgraphs probably, it's custom map, it's not from server side

    0
  • golden_elite13

    Okay :/ thank you


    I had another question.. (sorry to make you waste time xD) is it possible to get IP Address and host of players in lua code ? I know safewriting does it, phoenix too but the original function doesn't work anymore.. (get nil value or "N/A" like the GetProfileId()) but I think with an external tool we can get it ? (I think that's what "SSMSafeWriting.exe" is used to)

    0
  • Zi;

    Well, take look at SafeWritingMain.lua -> SafeWritingCall / CreateAppCall, it again works like cURL thing, simply "SSMSafeWriting.exe getip google.com"
    So far you can do this
    function SafeWritingCall(method, param)
        os.execute("SSMSafeWriting.exe "..method.." "..param.." > sfw_out.tmp")
        local f,err=io.open("sfw_out.tmp","r")
        if f then
            local content=f:read("*all")
            f:close()
            return content
        end
        return nil
    end
    function getip(host) return SafeWritingCall("getip", host) end
    print("google is at: "..getip("google.com"))


    But I am worried SSMSafeWriting.exe works only when SSM SafeWriting runs also :/

    0
  • golden_elite13

    Thank you but if it only works for SSM Safewriting.. not very useful for me :/ anyway, is there an equivalent function in CURL like getip, gethostbyname or i something don't know.. ? It would be great
    If not, maybe we can get IPs of players via an http request to crymp.net or something like that.. Tell me what you think about it, thanks :)

    0
  • Zi;

    Well did you try that code?

    0
  • Disturbed

    Zi you know how make site with servers master? same how cryserv?

    0
Page: 1 2 3 4 5 6 7 8 9