Jump to content

Full working and robust networking code


Nbacon

Recommended Posts

Hello,

I hope this code helps you.  [edited 06072020]

Over heads is about 10-20mb of ram but is worth it becuase of how flexable it is.

How to use

 new Packets 

Packets are usefull because you can send data and both sides know what is being sent and how to use it. Examples of packets I have made mouse packet that takes an x and a y and a mouse button and when executed will click on the screen. The example below is from my login packet takes a name, password and a world. The server will send this to a client and using code in the script will log in.

  • Goto src/com/bacon/eco/server/shared/packets
  • Make a new Packet that "implements IPacket"
  • Go to PacketType enum add this line 
        ClassName(last number ++ , com.bacon.eco.server.shared.packets.ClassName.class),

     

  • You will see 4 override methods echo, send, receive, execute in the new Class you just made
  • Make 2 constructors like This.  One needs to have 0 args taken, other can take what ever you want.
        public LoginPacket() {
    
        }
        public LoginPacket(final String username,
                           final String password,
                           final int world){
            this.username = username;
            this.password = password;
            this.world = world;
        }

     

  • echo -has a boolean and if the server ever gets this packet it will send the info to everone- good for pking and ge merching.
  • send - Inside send you need to use connection.writeString,  connection.writeInt, ... and others in the order that  you want to send them
        @Override
        public void send(ActiveConnection connection) {
            connection.writeString(  this.username);
            connection.writeString(  this.password);
            connection.writeInt(  this.world );
        }

     

  • receive - Inside receive use connection.readString,connection.writeInt  in the same order as above.
        @Override
        public void receive(ActiveConnection connection) {
            this.username =connection.readString();
            this.password=connection.readString();
            this.world =connection.readInt();
        }

     

  • execute - put what you want your bot to do here
        @Override
        public void execute(ActiveConnection connection)
        {
            if ( Client.mp !=null) Client.mp.loginToAccount( username,password  );
     		if ( Client.mp !=null) Client.mp.hopto( world );
        }

     

  • This will does the same this as excute inside the packet (just rember to leave execute blank or it will do both). make getters and  inside Client   ->   handlePacket   -> add code like this
               if (clazz == LoginPacket.class) {
                    final LoginPacket packet = (LoginPacket)Ipacket;
     			    if ( Client.mp !=null) Client.mp.loginToAccount( packet.username() ,packet.password()  );
     	         	if ( Client.mp !=null) Client.mp.hopto( packet.world() );
                    return;
                } 

     

 

 

How to add P2P messages

Make a new Class 

Quote

package com.bacon.eco.server.shared.packets;

import com.bacon.eco.server.shared.ActiveConnection;

public class P2PMessagesPacket implements IPacket{

    public P2PMessagesPacket(){ }
    Long time ;
    String senderName,receiversName,message;
    public P2PMessagesPacket(String senderName,String receiversName,String message){
        this.time =System.nanoTime();
        this.senderName=senderName;
        this.receiversName=receiversName;
        this.message=message;
    }
    @Override
    public boolean broadCast() {
        return false;
    }
    @Override
    public void send(ActiveConnection connection) {
        connection.writeLong(time);
        connection.writeString(senderName);
        connection.writeString(receiversName);
        connection.writeString(message);
    }
    @Override
    public void receive(ActiveConnection connection) {
        this.time = connection.readLong();
        this.senderName = connection.readString();
        this.receiversName = connection.readString();
        this.message = connection.readString();
    }
    @Override
    public void execute(ActiveConnection connection) {
        System.out.println(time+":"+senderName+" :"+message);
        //does something
    }

    public String getReceiversName() {
        return receiversName;
    }

    public Long getTime() {
        return time;
    }
}

 

Add it to the Enum PacketType

Quote

 Information(1, InformationPacket.class),
    Ping(2, PingPacket.class),
    LogoutPacket(3, com.bacon.eco.server.shared.packets.LogoutPacket.class),
    ExamplePacket(4, com.bacon.eco.server.shared.packets.ExamplePacket.class),
    P2PMessagesPacket(5, com.bacon.eco.server.shared.packets.P2PMessagesPacket.class)//new 
      

 

Goto com.bacon.eco.server.server.network.Controller 

under handlePacket make code like this

Quote

     if (clazz == P2PMessagesPacket.class) {
           final P2PMessagesPacket packet = (P2PMessagesPacket)iPacket;
           sendToOnePerson( packet.getReceiversName(),packet);
           return true;
       }

 

 

Test your code (example P2PMessagePacket)

go to TestClient write some code like this. compile and run 

Quote

   public static void startClient(final String address, final int port)  {
....
        Example.Username ="test1";
        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            connection.addPacket(new P2PMessagesPacket("test2","hi"));

        }

    }

 

Change the code to un comment to see them talk to each other.

Quote

  public static void startClient(final String address, final int port)  {
    .....
        while (true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //connection.addPacket(new P2PMessagesPacket("test1","hi"));

        }

    }

 

out put shoud look like 

Quote

278887291440685:test1 :hi
278888291729010:test1 :hi
278889292070128:test1 :hi
278890292315712:test1 :hi

 

Adding useful info

AbstractPingPongPacket these send a request for data [Advance]

PingPacket this updates the server ever 3 seconds.

 info that could go in here

  • userloged in
  • username [example script you need write this your self]
  • current script runnign
  • User location
  • much,much more 

Sever-side Tuning

Basicly you can make methods that can be controlled by a gui or CLA with a scanner :

Example

Quote

        while (true) {

            String command = sc.nextLine();

            if (command.equals("-lo")) {
                mainserver.controller.sendlogouts(-1);
            }

        }

 

This tells all accounts to log out or just some amount.

   public void sendlogouts(int logoutAmount) {
        final Set<ActiveConnection> clientSet = clients.keySet();
        int count = 0;

        for (final ActiveConnection connection : clientSet) {

            if (connection.getType() == 1 && (count < logoutAmount || logoutAmount == -1)) {
                count++;
                connection.addPacket(new LogoutPacket());
            }
        }
    }

Adding it to your scripts

Examples from my scripts

Quote

Inside a banking class


if(productAmount()>3000){
 	connection.addPacket(new MulePacket( this.getWorlds().getCurrentWorld() , 1));
}

if(suppliesAmount()<500){
	 connection.addPacket(new MulePacket( this.getWorlds().getCurrentWorld() ,2));
}
if(suppliesAmount()==0){
	 connection.addPacket(new MulePacket( this.getWorlds().getCurrentWorld() ,3));
}

 

Quote

simple multi-boxer


    getBot().addKeyListener(new BotKeyListener() {

            @Override
            public void checkKeyEvent(KeyEvent keyEvent) {

                if (holdkeys.contains(keyEvent.getKeyCode())) {


                    if (keyEvent.toString().contains("KEY_RELEASED")) {

                        connection.addPacket(
                                new HoldPacket(keyEvent.getKeyCode(), 1));

                    }
                    if (keyEvent.toString().contains("KEY_PRESSED")) {

                        connection.addPacket(
                                new HoldPacket(keyEvent.getKeyCode(), 0));

                    }

                }
                if (keyEvent.toString().contains("KEY_TYPED")&&keyEvent.getKeyChar()!=32) {

                    connection.addPacket(
                            new TypePacket(keyEvent.getKeyChar()));

                }


            }


        });

        getBot().addMouseListener(new BotMouseListener() {


            @Override
            public void checkMouseEvent(MouseEvent mouseEvent) {

                if (mouseEvent.toString().contains("MOUSE_CLICKED")) {

                    if (mouseEvent.getButton() == 1) {
                        log("" + mouseEvent);
                        connection.addPacket(
                                new ClickPacket(
                                        mouseEvent.getX(),
                                        mouseEvent.getY(), 1));

                    }

                    if (mouseEvent.getButton() == 3) {

                        log("" + mouseEvent);
                        connection.addPacket(
                                new ClickPacket(
                                        mouseEvent.getX(),
                                        mouseEvent.getY(), 3));

                    }

                }
            }
        });

 

 

 

This is code was my frist draft on networking.Code update to add change in How to use [06072020]

Things that can be added:

if your connection drops out then try to reconnect.

Better way to drop old conections- at the moment if you get sent 10 null messages in a row the connetion is droped.

Things that can be ran

  • TestClient
  • Mainserver
  • Example (script)

Any questions or help just ask.

update [06072020] 

Username is example script needs to be defined in some way by you.

code_06072020.zip

Edited by Nbacon
  • Like 4
Link to comment
Share on other sites

6 hours ago, dreameo said:

I think there's a bit of over complication here. Instead of defining a 'packet' for every kind of message, just define a protocol.

I don't think I under stand this fully explain more. Becuase to me they are protocol becuase both sides agree on info that is sent over the sockets. You dont need packets to be mono taskers. But they can keeping a theme in a packet, this is usefull for expandability (for me at least). For my bot at least I have never needed more then 5 "packet",  The bots are kept in the dark about the 30 other packets they cant see but the server can handle all 35.

6 hours ago, dreameo said:

This way, you have a single send and receive. Internally, you decide how you make sense of the data. 

This sounds like what it is doing.(I don't Know how you would do this externally)

 

Link to comment
Share on other sites

41 minutes ago, Nbacon said:

I don't think I under stand this fully explain more. Becuase to me they are protocol becuase both sides agree on info that is sent over the sockets. You dont need packets to be mono taskers. But they can keeping a theme in a packet, this is usefull for expandability (for me at least). For my bot at least I have never needed more then 5 "packet",  The bots are kept in the dark about the 30 other packets they cant see but the server can handle all 35.

This sounds like what it is doing.(I don't Know how you would do this externally)

 

Both sides don't agree, you have to manually go in and define a new packet for every type of message.

Link to comment
Share on other sites

2 hours ago, dreameo said:

Both sides don't agree

I don't know what you mean

  • I have packet x with  String i, int  j, long  k
  • I make an x packet.
  • I give you an packet with only the info. 
  • You read the packet and see id, oh its an x packet so you know it has a string i, int j and a long k. 
  • We both agree that all x packets need string i, int j, and a long k but we dont care what the others dose with info.
2 hours ago, dreameo said:

you have to manually go in and define a new packet for every type of message.

There only so much you can do and having molds for the grabage in and garbage out is usefull.

 

Link to comment
Share on other sites

37 minutes ago, Nbacon said:

I don't know what you mean

  • I have packet x with  String i, int  j, long  k
  • I make an x packet.
  • I give you an packet with only the info. 
  • You read the packet and see id, oh its an x packet so you know it has a string i, int j and a long k. 
  • We both agree that all x packets need string i, int j, and a long k but we dont care what the others dose with info.

There only so much you can do and having molds for the grabage in and garbage out is usefull.

 

Wouldnt it be easier for a 'Packet' to only contain one String which senders and receivers can parse accordingly? That way, the protocal can know even less about the data being sent and theres no need to define multiple 'Packets'

Link to comment
Share on other sites

1 hour ago, Camaro said:

Wouldnt it be easier for a 'Packet' to only contain one String which senders and receivers can parse accordingly? That way, the protocal can know even less about the data being sent and theres no need to define multiple 'Packets'

You could do that, there is nothing wrong with that.

Its almost the same amount or more work(When i used that method it seemed like 3 times more work)  as what this code does. This code is just Id10t proofing the sending, resiving  and execution of data. No need to encode and decode data, No need to cast Strings to objects, and No need to make a parsing tree that only you can use because you made it. All you have to do is connection.addPacket(new YourPacket(info , info, info....));

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...