Reserved slots

FehaFeha Join Date: 2006-11-16 Member: 58633Members
edited November 2010 in Modding
<div class="IPBDescription">For those admins who want to be sure of playing</div>Ok, I have been messing a little in ns2 lua, and I got a decent result. This is a script that has a table of VIP (Very Important Person), and a number of reserved slots (also requires you type max slots, as I dunno functino to get that). It wont kick people who already play on the server, instead it will kick players joining a reserved slot unless they are VIP.
if a server owner has a 8 player server, he can set to actually be 9 where 1 slot is reserved, so he can join even when its "full", but play with more lag (9 players).

Also, I would be GLaD if you left my name in the VIP list ;).


You will have to edit the VIP list (remember , after each name, except for the last name), the maxSlots and the reservedSlots into what you want it to be.

This is the code, for some reason it requires a Script.Load("lua/filename.lua") in Server.lua.
And yes I use nickname, and I know its lousy security, but some people have dynamic ip (making using ip even more stupid, not to mention I dunno how to get a players ip :P), and ns2 doesnt support steamid yet or something (I really want it!).
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->// ================================================================================
======
//
// lua\ReservedSlots.lua
//
//    Created by:   Feha
//    Mod  which reserves some slots for a list of VIP's
//
// ========= For more information, visit us at http://www.unknownworlds.com =====================

//Table of people with VIP status
local VIP = {
    "Feha",
    "YourOwnName"
}

//Table of people who already joined as the event I listen to run often, and therefor need a check if its the first time it runs.
local alreadyJoined = {}

//Amount of reserved slots and max slots
local reserverSlots = 2
local maxSlots = 8

//Function to get number of players on server
local function numPlayers()
    
    //Cant find a good function for this, so I get the number of players in the playerlist
    local numPlayers = #GetGamerules().playerList
    
    return numPlayers
    
end

//This function check if a table contains a value, table.find returns index which I dont need, aswell as cares for multidimensional tables
local function HasValue(t, value)
    
    for k,v in ipairs(t) do
        if (v == value) then
            return true
        end
    end
    
end

//Function that runs when a player connects
function OnClientConnect(client, name)
    
    //Get the player entity of the client, so we can broadcast
    local player = client:GetControllingPlayer()
    if not player then return end
    
    //Only adds the value into the table if it wasnt there before, and if it doesnt, we dont want to continue.
    //Use client and not player, as everytime you change team, gestate or such, you get a new player instance assigned to your client
    if not table.insertunique(alreadyJoined, client) then return end
    
    name = string.gsub(name, "\"(.*)\"", "%1")
    
    //Broadcast if the player is VIP or not, to make VIP feel important, and others realise they exist
    if HasValue(VIP, name) then
        Server.Broadcast(nil, string.format("%s %s", name, "is VIP!"))
    else
        Server.Broadcast(nil, string.format("%s %s", name, "is not VIP!"))
    end
    
    //ICheck if player tries to join a reserved slot
    if (numPlayers() > (maxSlots-reserverSlots)) then
        if HasValue(VIP, name) then
            Server.Broadcast(nil, string.format("%s %s", name, "joined reserved slot"))
        else
            Server.Broadcast(nil, string.format("%s %s", name, "kicked for joining reserved slot"))
            //Kick client from the server
            Server.DisconnectClient(client)
            //Server.SendCommand( player, "disconnect" ) //Slow on actually making the server drop the client
        end
    end
    
end

//Function that runs when a player disconnects
function OnClientDisconnect(client)
    
    local player = client:GetControllingPlayer()
    
    //If they disconnect and later reconnect, we have to check them again, which requires we remove them from this list
    table.removevalue(alreadyJoined, client)
    
end

//Not used as player doesnt have a name when this runs
//Event.Hook("ClientConnect", OnClientConnect)

//This runs when a player joined, and is the same hook used to set players name, however, it runs quite often...
Event.Hook("Console_name", OnClientConnect)

//This runs when a player disconnects, which we need to listen so we remove them from the "alreadyjoined" player list
Event.Hook("ClientDisconnect", OnClientDisconnect)<!--c2--></div><!--ec2-->

Comments

  • playerplayer Join Date: 2010-09-12 Member: 73982Members
    Very clever use of the limited facilities available to you.

    <!--quoteo--><div class='quotetop'>QUOTE </div><div class='quotemain'><!--quotec-->This is the code, for some reason it requires a Script.Load("lua/filename.lua") in Server.lua.<!--QuoteEnd--></div><!--QuoteEEnd-->
    If for "filename.lua" you mean your script "ReservedSlots.lua", then that is perfectly simple to explain.
    A bit of speculation ahead (I have access to the same documentation as you do after all):
    Lua-scripts aren't loaded based on their presence in the Lua-directory, but rather because of their inclusion in other loaded scripts. This means your script has to be loaded (in this particular case) by "Server.lua", which in turn is loaded by another script (actually it isn't but let's for now assume it is). This continues until a top-level script is reached. With that I mean a script that is explicitely loaded by NS2. So you should imagine the Lua file-structure as a hierarchie that starts out small and broadens as it moves through the Lua-scripts. To my knowledge there are 3 Lua-VMs: Main, Client and Server. Each of these VMs have their own top-level script-file it explicitly loads:
    Main VM: Main.lua
    Client VM: Client.lua
    Server VM: Server.lua (so in that example above "Server.lua" isn't actually included by another file, but already is the top-level script).

    It should also be noted that a direct consequence of this is that whenever an integrity-check is performed on the Lua-files, or a new NS2-build is released, the Script.Load-reference you've added to ensure your scripts is parsed, will be removed and the mod is disabled yet again. Which means you have to re-include that Script.Load every new NS2-build. To avoid having it removed by an integrity-check, you can consider making it a mod (by that I mean put it in a seperate directory, and run it using -game).
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    Nice, running it :)
  • fsfodfsfod uk Join Date: 2004-04-09 Member: 27810Members, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, Squad Five Silver, Squad Five Gold, Subnautica Playtester, NS2 Community Developer, Pistachionauts
    <!--quoteo--><div class='quotetop'>QUOTE </div><div class='quotemain'><!--quotec-->To my knowledge there are 3 Lua-VMs: Main, Client and Server. Each of these VMs have their own top-level script-file it explicitly loads:
    Main VM: Main.lua
    Client VM: Client.lua
    Server VM: Server.lua (so in that example above "Server.lua" isn't actually included by another file, but already is the top-level script).<!--QuoteEnd--></div><!--QuoteEEnd-->

    The Main and Client VMs were merged together about 5 builds ago or so. The Main.lua file is just Script.Load'ed from the Client.lua now
    The names of the top level scripts for the Server and Client VM can be controlled with a custom game_setup.xml in your mods directory
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    I deactivated it again, it worked fine at first but then it became weird bugs (or the server itself became weird, not really sure)..
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    You got any errors in console? If so please post them.
    I would also like an explanation of the bugs, might help me fix it.

    Just saying there may be bugs because of this mod wont really help me :P.
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    edited November 2010
    I know, sorry ;)

    I dont think there were any errors in the logs but not sure. When I connected at some point, the server was only have full and it seemed like players were getting kicked for joining a non-reserved slot. Also, players had their nickname with a (2) and or (3) behind them so Im not sure if it was your mod or some other bug in the server.

    I will try it again on one server and see if I can come up with something more specific.
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    edited November 2010
    the numbers behind names have to do with joining a server you already joined (it adds a number to your nickname), I had that bug on several servers, and it has nothing to do with my mod. Except maybe the fact that it kicks people trough the disconnect concmd, which seem to have a delay serverside, making the server keep an instance of the client for some time until dropping it. If a player rejoins they will just add another useless instance that stays for some time before getting dropped.
    I blame the documentation for not telling me how to drop players serverside (I have to tell server to tell client to disconnect, which as I said is slightly bugged serverside).

    About it kicking players when its half full, maybe you forgot changing the max slots and reserved slots variables? Documentation lacked info on how to get max slots (I found a way clientside tho, but that wont help in this case), so you have to set it manually. Also, the number of reserved slots isnt additional slots, the formula is publicslots = maxslots-reservedslots.
    Could it also be so that it actually were more people on the server than the server browser argued? I noticed such a bug at times.

    If any other modder know a way to kick people in a good way (maybe even with a custom msg in the box that always show up as "disconnected" (or whatever it says)), I would love to know it ;).
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    edited November 2010
    Ok, so I think for some reason your method of getting the playercount was not reliable...

    I've been using the following code now for a little while and it seems to work:

    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->//Function to get number of players on server
    local function numPlayers()
        
        local numPlayers = #GetGamerules().playerList
        
        return numPlayers
        
    end<!--c2--></div><!--ec2-->
  • fsfodfsfod uk Join Date: 2004-04-09 Member: 27810Members, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, Squad Five Silver, Squad Five Gold, Subnautica Playtester, NS2 Community Developer, Pistachionauts
    <!--quoteo--><div class='quotetop'>QUOTE </div><div class='quotemain'><!--quotec-->If any other modder know a way to kick people in a good way (maybe even with a custom msg in the box that always show up as "disconnected" (or whatever it says)), I would love to know it ;).<!--QuoteEnd--></div><!--QuoteEEnd-->

    Server.DisconnectClient does what you want
  • MartinMartin Join Date: 2010-07-27 Member: 73229Members
    edited November 2010
    You need to kick in an intelligent fashion though and not grab the first available person. Reason is the first available person could have been playing for some time. You need to kick the newest client. This is how I have designed ours to work.
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    edited November 2010
    If you havent noticed, it check when a client joins if he can not (if he cant, he gets kicked). It never kick a player who have got to play. Basiclly, either they get in, or they do not.
    I never been a fan of kicking players to let others in, that promotes elitism to much. So I designed this solution to be more like, your server have x slots, but if you really want to play, you can join x 'nonexisting' slots.

    Also, thanks for the help in finding functions, I will try them.
    Altough the way of getting numplayers you use, seem to be very similar to the way I use. I checked gamerules, and it lack the playerlist variable entirely, altough ns2gamerules.lua got it (which is what you get with getgamerules). The playerlist is set with this code:
    <!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1-->function NS2Gamerules:UpdatePlayerList()

        self.playerList = {}
        
        table.adduniquetable(self.worldTeam:GetPlayers(), self.playerList)
        table.adduniquetable(self.team1:GetPlayers(), self.playerList)
        table.adduniquetable(self.team2:GetPlayers(), self.playerList)
        table.adduniquetable(self.spectatorTeam:GetPlayers(), self.playerList)    

    end<!--c2--></div><!--ec2-->
    Which as you see is pretty much exactly the same thing I do, unless someone somehow is in several teams at once.
    I will use your function though, it is better as it has safety check for ppl in 2 teams.

    Bugtesting time! :P

    EDIT:
    Ok, the client kicking function is deffinitelly better, and then numplayer code works atleast as well as my old code (suprise suprise! ;D).
    Updating the code in the first post now.

    EDIT2:
    Also, does anyone know a good way from server to show text on players screen? Broadcast is small text in left corner, which evaporates very fast :P.
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    edited November 2010
    <!--quoteo--><div class='quotetop'>QUOTE </div><div class='quotemain'><!--quotec-->I will use your function though, it is better as it has safety check for ppl in 2 teams.<!--QuoteEnd--></div><!--QuoteEEnd-->

    Yeah, I think this is the critical point, I think at some point due to some bug, a player may be in two teams at a time. Im not 100% sure if this was the bug anyways, but it has worked so far.

    Will try the new kicking method, thanks :)

    edit: You can show a tooltip with AddToolTipOnce (or something like that). But such a tooltip also disappears pretty fast so I dont really know whats better...
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    I rarely read the tooltips myself, and using chat is not very smart yet, as I think the color control only is clientside so far.

    Was thinking more like printing in clients console as a server (and keep the current broadcast aswell).
  • puzlpuzl The Old Firm Join Date: 2003-02-26 Member: 14029Retired Developer, NS1 Playtester, Forum Moderators, Constellation
    Oh please please please stop running this mod on your servers, it is making it so frustrating to find a game of NS2. The 2-3 times I tried to play recently I just quit in frustration after continuously getting kicked for not being a VIP.

    Figure out how to hide the res slot asap and kicking people who are enjoying their game is a terrible solution.
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    edited November 2010
    First, my mod doesnt kick ppl who enjoy their game, not even those who dont enjoy their game, it kicks the person who just joined a reserved slot.
    Second, try joining a server which is not near-full, but instead one that has a few free slots left. Also, if the server stops using this mod, chances are they will also have less slots available (like armorychambers was a 10 slot, but is 11 now, where 1 is a reserved slot (which means there are still 10 slots for non-VIP's).
  • w0dk4w0dk4 Join Date: 2008-04-22 Member: 64129Members, Constellation, Reinforced - Shadow
    Just FYI: I've removed the reserved slot because player numbers died down.
Sign In or Register to comment.