Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[New G2O][Shared] packetListener
#1
*Introduction:

NOTE! This script allows you to bind ONE function to listen packet with specific id.
NOTE! You have to specify packet id(s) by yourself in messageid.nut file
NOTE! Default packet Id type is Uint16, but you can change this easily by editing packetListener.nut script
NOTE! If you decide to test this script, make sure that you don't have any function(s) bind to onPacket event

Info: This script is stable and propably doesn't have any bugs.

Hi, as you know G2O allows you to communicate with client or server using packets, but if you want to split functions which are reading packets,
you still must have ONLY one onPacket event, in which you are reading packet id. If you have more complex scripts, it's not good to read a code
from file to file, so i've made very simple handler, which allows you to bind ONE function to specific packet id. Feel free to use it.

License

Download



*List of functions:



void addPacketListener(mixed packetId, func callback)
void removePacketListener(mixed packetId)



*Function (addPacketListener, removePacketListener) parameters description:

Info: packetId is "mixed" because it's up to you what packet id type will be (default is Uint16).



// Required parameters for addPacketListener

mixed packetId // The packetId, (it's recommended to specify packet Id's in file messageid.nut)
void callback // The function which will be called, when packet arrived to specific site.

// Required parameters for removePacketListener

mixed packetId // The packetId



*Installation:



1.Download zip archive
2.Unpack archive and place network folder in your G2O server directory wherever you want.
3.Add this line to parsed xml file, (for example: config.xml)

PHP
  1. <import src="network/network.xml" />



4.After that, you've loaded both scripts: (packetListener.nut and messageid.nut) to client-side and server-side.



*Examples:



*Sending client-side statistics to server, which can be later used for building an anti-cheat:



*Client-side:

Squirrel Script
  1. // creating infinite timer which will be called with one second delay
  2. setTimer(function()
  3. {
  4. local packet = Packet() // creating packet
  5.  
  6. packet.writeUint16(PACKET.ID) // writing some id from messageid.nut, you have to define id yourself, it's only a dummy example
  7. packet.writeInt32(getPlayerStrength(heroId)) // writing player strength
  8. packet.writeInt32(getPlayerDexterity(heroId)) // writing player dexterity
  9.  
  10. packet.send(RELIABLE_ORDERED) // sending packet to server
  11.  
  12. }, 1000, -1)



*Server-side:

Squirrel Script
  1. addPacketListener(PACKET.ID, function(pid, packet) // binding function to packet with id PACKET.ID
  2. {
  3. local strength = packet.readInt32() // reading player strength
  4. local dexterity = packet.readInt32() // reading player dexterity
  5.  
  6. if (strength != getPlayerStrength(pid)) // comparing client-side strength with server-side strength
  7. {
  8. ban(pid, -1, "Cheating strength") // givining permanent ban for cheating
  9. }
  10. else if (dexterity != getPlayerDexterity(pid)) // comparing client-side dexterity with server-side dexterity
  11. {
  12. ban(pid, -1, "Cheating dexterity") // givining permanent ban for cheating
  13. }
  14. })





*Sending server-side custom player class to client



*Server-side:

Squirrel Script
  1. local heroClass =
  2. {
  3. health = 1000,
  4. mana = 100,
  5.  
  6. strength = 200,
  7. dexterity = 200
  8. }
  9.  
  10. addEventHandler("onCommand", function(pid, cmd, params)
  11. {
  12. if (cmd == "giveclass") // if player type /giveclass command, then..
  13. {
  14. local packet = Packet() // creating packet
  15.  
  16. packet.writeUint16(PACKET.CLASS) // writing some id from messageid.nut, you have to define id yourself, it's only a dummy example
  17. packet.writeInt32(heroClass.health) // writing class health
  18. packet.writeInt32(heroClass.mana) // writing class mana
  19. packet.writeInt32(heroClass.strength) // writing class strength
  20. packet.writeInt32(heroClass.dexterity) // writing class dexterity
  21.  
  22. packet.send(pid, RELIABLE_ORDERED) // sending packet to client
  23. }
  24. })



*Client-side:

Squirrel Script
  1. addPacketListener(PACKET.ID, function(packet) // binding function to packet with id PACKET.ID
  2. {
  3. local health = packet.readInt32() // reading class health
  4. local mana = packet.readInt32() // reading class mana
  5. local strength = packet.readInt32() // reading class strength
  6. local dexterity = packet.readInt32() // reading class dexterity
  7.  
  8. setPlayerHealth(heroId, health)
  9. setPlayerMaxHealth(heroId, health)
  10.  
  11. setPlayerMana(heroId, mana)
  12. setPlayerMaxMana(heroId, mana)
  13.  
  14. setPlayerStrength(heroId, strength)
  15. setPlayerDexterity(heroId, dexterity)
  16. })





*Examples comment



Example nr 2:

This is only a dummy example, to illustrate how addPacketListener function works.
If you really want to create a script which give some class to player, i recommend you to
giving statistics on server-side, because this example is not safe.
Reply
#2
Good idea, but personally I think that the g2o packages are enough and do not require any improvements, look at the fragment of my code and see that it's enough (I do not want you to treat it as hatred)

Squirrel Script
  1. enum packetList
  2. {
  3.    option_lineChat,
  4.    option_hud,
  5.    option_password,
  6.    option_notifications,
  7.  
  8.    id = 255
  9. };
  10.  
  11. class PlayerOptions
  12. {
  13.    constructor(server){
  14.        SCore = server;
  15.        SPlayer = server.SPlayer;
  16.    }
  17.  
  18.    function changeLine(pid, lines)
  19.    {
  20.        mysql_query(SCore.handler, "UPDATE options SET `chat_lines` = '"+lines+"' WHERE `login` = '"+SPlayer[pid].login+"'");
  21.    }
  22.  
  23.    function changeHud(pid, layout)
  24.    {
  25.        mysql_query(SCore.handler, "UPDATE options SET `hud_layout` = '"+layout+"' WHERE `login` = '"+SPlayer[pid].login+"'");
  26.    }
  27.  
  28.    function changePassword(pid, oldPass, newPass)
  29.    {
  30.        local result = mysql_query(SCore.handler, "SELECT * FROM players WHERE `login` = '"+SPlayer[pid].login+"' AND password = '"+crypt(oldPass)+"'");
  31. if(result)
  32.        {
  33.            local row = mysql_fetch_assoc(result);
  34. if(row)
  35.            {
  36.                mysql_query(SCore.handler, "UPDATE players SET `password` = '"+newPass+"' WHERE `login` = '"+SPlayer[pid].login+"'");
  37.            }
  38.            mysql_free_result(result);
  39.        }
  40.    }
  41.  
  42.    function changeNotifications(pid, notification)
  43.    {
  44.        mysql_query(SCore.handler, "UPDATE options SET `notification` = '"+notification+"' WHERE `login` = '"+SPlayer[pid].login+"'");
  45.    }
  46.  
  47.    function receivedPacket(pid, packet)
  48.    {
  49.        if(packet.readUInt8() == packetList.id)
  50.        {
  51.            switch(packet.readUInt8())
  52.            {
  53.                case packetList.option_lineChat: changeLine(pid, packet.readInt8()); break;
  54.                case packetList.option_hud: changeHud(pid, packet.readInt8()); break;
  55.                case packetList.option_password: changePassword(pid, packet.readString(), packet.readString()); break;
  56.                case packetList.option_notifications: changeNotifications(pid, packet.readBool()); break;
  57.            }
  58.        }
  59.    }
  60.  
  61.    SCore = null;
  62.    SPlayer = null;
  63. }


Reply
#3
Well, your code is pretty simple and readable, but this:
Squirrel Script
  1. function receivedPacket(pid, packet)
  2. {
  3. if(packet.readUInt8() == packetList.id)
  4. {
  5. switch(packet.readUInt8())
  6. {
  7. case packetList.option_lineChat: changeLine(pid, packet.readInt8()); break;
  8. case packetList.option_hud: changeHud(pid, packet.readInt8()); break;
  9. case packetList.option_password: changePassword(pid, packet.readString(), packet.readString()); break;
  10. case packetList.option_notifications: changeNotifications(pid, packet.readBool()); break;
  11. }
  12. }
  13. }



Can cause problems because in this method, you are reading first packet value, I belive that you connect this method to onPacket event.
So, what if you have more similar functions/methods, and trying to read packet id in this way:

Squirrel Script
  1. if(packet.readUInt8() == packetList.id)



Even if this condition won't pass, you still read first value from packet, which was id.

Take a look at this code:
https://www97.zippyshare.com/v/LxAq6iiv/file.html

To simply avoid this problem, you must have ONLY ONE function connected to onPacket event on each side, then ONLY ONCE read packet Id, and check which function should be called based on it's value.

Even if you try to call two diffrent functions and pass them a packet object, it won't work, because this function will be working with an object reference, not it's copy.

In my opinion, this simple script makes it a little bit easier to add some new function(s) to call when packet with specific id arrive to it's location, but it's only my opinion, maybe i'm wrong Big Grin.
Reply
#4
(20.06.2018, 17:26)Patrix Wrote: Well, your code is pretty simple and readable, but this:
Squirrel Script
  1. function receivedPacket(pid, packet)
  2. {
  3. if(packet.readUInt8() == packetList.id)
  4. {
  5. switch(packet.readUInt8())
  6. {
  7. case packetList.option_lineChat: changeLine(pid, packet.readInt8()); break;
  8. case packetList.option_hud: changeHud(pid, packet.readInt8()); break;
  9. case packetList.option_password: changePassword(pid, packet.readString(), packet.readString()); break;
  10. case packetList.option_notifications: changeNotifications(pid, packet.readBool()); break;
  11. }
  12. }
  13. }



Can cause problems because in this method, you are reading first packet value, I belive that you connect this method to onPacket event.
So, what if you have more similar functions/methods, and trying to read packet id in this way:

Squirrel Script
  1. if(packet.readUInt8() == packetList.id)



Even if this condition won't pass, you still read first value from packet, which was id.

Take a look at this code:
https://www97.zippyshare.com/v/LxAq6iiv/file.html

To simply avoid this problem, you must have ONLY ONE function connected to onPacket event on each side, then ONLY ONCE read packet Id, and check which function should be called based on it's value.

Even if you try to call two diffrent functions and pass them a packet object, it won't work, because this function will be working with an object reference, not it's copy.

In my opinion, this simple script makes it a little bit easier to add some new function(s) to call when packet with specific id arrive to it's location, but it's only my opinion, maybe i'm wrong Big Grin.
If you write a structured script, it can be useful, but when it comes to oop, g2o packages are enough in this state and you really have to try to make a mistake(I think so). In any case, it can be useful for someone Smile

Squirrel Script
  1. enum packetList
  2. {
  3.    option_lineChat,
  4.    option_hud,
  5.    option_password,
  6.    option_notifications,
  7.  
  8.    id = 255
  9. };


This is a piece of code from my project. Enum is global (client / server) I have cut out a fragment for an example.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [New G2O][Client-Side] bindKey Patrix 6 8,961 14.11.2018, 02:32
Last Post: Patrix
  [New G2O][Shared] Command Handler Patrix 3 6,169 05.09.2018, 15:42
Last Post: Patrix
  [G2O v.0.1.2][Server-Side] NPC Manager Quarchodron 16 17,471 21.01.2018, 19:59
Last Post: Quarchodron
  [New G2O][Client-Side] Key Combination Patrix 1 3,780 23.12.2017, 13:16
Last Post: Patrix
  [G2O v.0.1.0][Client-Side] Notice Board Quarchodron 0 3,137 27.06.2017, 14:28
Last Post: Quarchodron

Forum Jump:


Users browsing this thread: