let the server do the work

Posted By: Scorpion

let the server do the work - 07/17/10 13:27

hello everyone,

I just tried to put my hands on the gamestudio multiplayer engine again. The last time I did that, I ended up nearly exclusively using send_data - only to get something in the direction of client side prediction working. But now I found the new 3rd value for dplay_smooth, which stops the engine predicting the players movement. So I wrote a small code, that lets you control a player with your keyboard.

The only problem is, that I give the client too much power by letting him choose the position he wants to spawn. Whats the best way to avoid that? The greatest problem I see is that you can only use some handy functions like proc_client and everything that is related to checking where the entity belongs to, when you executed that ent_create on a client - what I think is a no go...

How should I rewrite my code to conform with these conditions?

Thank you
Scorpion

Here's the code I hacked together:
Code:
#define rand_area(x) vector(x-2*random(x),x-2*random(x),x-2*random(x))

#define KEYS skill1
#define SPEED skill2
#define ASPEED skill3

#define KEY_FORWARD    (1<<0)
#define KEY_BACKWARD    (1<<1)
#define KEY_LEFT        (1<<2)
#define KEY_RIGHT        (1<<3)
#define KEY_SHOOT        (1<<4)

#define k(x) sign(my.KEYS & (x)) //is key pressed?

//movement code for player - executed on server and client
void player_move(){
    var dirX = k(KEY_FORWARD) - k(KEY_BACKWARD);
    DEBUG_VAR(dirX, 30);
    var dirY = k(KEY_LEFT) - k(KEY_RIGHT);
    
    my.pan += accelerate(my.ASPEED, dirY*10, 0.7);        
    c_move(me, vector(accelerate(my.SPEED, dirX*10, 0.7), 0, 0), nullvector, IGNORE_PASSABLE);
}

//player action on client
void player_main_client(){
    while(1){
        //store keys in skill
        my.KEYS =       key_w            *KEY_FORWARD
                        | key_s            *KEY_BACKWARD
                        | key_a            *KEY_LEFT
                        | key_d            *KEY_RIGHT
                        | mouse_left    *KEY_SHOOT;
        
        send_skill(my.KEYS, SEND_VEC|SEND_UNRELIABLE);
        player_move();
        
        //adapt camera to new position
        vec_set(camera.x, my.x);
        vec_set(camera.pan, my.pan);
        
        wait(1);
    }
}

//player action on server
action player_main(){
    proc_client(me, player_main_client);
    
    while(1){
        player_move();
        wait(1);
    }
}

int main(){
    dplay_smooth = 3;//client side player-entity is not updated
    
    while(1){
        if(key_1){//server
            if(!session_open("ilovecake")){
                sys_exit("Couldn't create session!");
            }
            
            level_load(NULL);
            break;
        }
        if(key_2){//client
            session_connect("ilovecake", "127.0.0.1");
            while(!connection) wait(1);
            level_load(NULL);
            randomize();
            player = ent_create(SPHERE_MDL, vec_add(rand_area(50),vector(0,0,50)), player_main);
            
            break;
        }
        wait(1);
    }    
    return 0;
}


Posted By: Rackscha

Re: let the server do the work - 07/17/10 17:52

For the spawn problem:

Send a request from the client to the server.
The server then sends back a new position.(send_skillto , as far as i know is possible to?!)


GReets
Rackscha
Posted By: SchokoKeks

Re: let the server do the work - 07/17/10 19:41

Not sure if i unterstood you right rackscha, but I wouldn't call this a secure solution. a hacked client could still ignore this skill (or variable) and place his player anywhere he wants.

I know 2 solutions:
1. Let the client place the entity somewhere outside of the level or at the nullvector. Let the server then place the entity at the right position, and use ent_sendnow to update the client. However, you'd have to detach the camera from the player as long as it is not inside the level and waiting for its new position.

2. use ent_create only on the server. you can't use proc_local and such then. The multiplayer plugins (gstnet and anet) don't rely on who the entity created. The native system is limited there.

Additionally, you have to make sure that the clients can only send their input to the server, and not their absolute position. Always let the server's view of the game be the one you transfer.

EDIT: it looks like you're already doing that. Sorry, I can't help you with the code, don't have much time currently..
Posted By: fastlane69

Re: let the server do the work - 07/18/10 03:56

If you use the appropriate "if(connection == 1,2,3)" switches, then the entity will have only one action defined for yet it will be executed one way on the client and another on the server. This way when the server creates the client, everyone acts the way they should without proc'ing a thing.
Posted By: fastlane69

Re: let the server do the work - 07/18/10 03:58

Second problem:

choose one:

Quote:
movement code for player - executed on server and client


You either have the server be responsible for movement and rely results to the client or you can have the client do their own movements and then update the server with the results. You can use either depending on your application, but not both at the same time.
Posted By: Scorpion

Re: let the server do the work - 07/18/10 10:29

@rackscha SchokoKeks is right there. That wouldn't make a difference...

@SchokoKeks The repositioning is probably a great way to do that. I will look into those methods.

@fastlane69 When using branching with 'connection', how can I identify the client, who controls the entity - he needs different code than the other clients ofc.

to my code: it should be like this (If it really does what I want is another thing - maybe you can tell?):

the client gets the players input and moves it on the client, then sends the keys at the same time to the server and there the same movement (not exactly - different time_step...) is done. The server sends the new position and rotation to all the clients, but the owner of the player. (There is the need to synchronize the clients position with the servers one, but first I have to get the absolute basics right)

BUT I just tried the code with a friend over the internet and it's jittering like hell, because somehow the server still corrects the position and rotation of the player. Can you please help me getting such a basic thing to work?
Posted By: SchokoKeks

Re: let the server do the work - 07/18/10 10:44

Originally Posted By: Scorpion
@fastlane69 When using branching with 'connection', how can I identify the client, who controls the entity - he needs different code than the other clients ofc.

For that, I use the following "branch":
Code:
if (me == player) ...


Just make sure that the player pointer is set, and you know that this client can controll the entity.

There is another problem in your code that can lead to lagging or jittering over the internet:
Code:
send_skill(my.KEYS, SEND_VEC|SEND_UNRELIABLE);


This sends the 3 skills every frame, something you may never do.
use a code like this to send the skill only when it has changed:
Code:
if (my.KEYS != my.OLD_KEYS) {my.OLD_KEY = my.KEYS; send_skill(my.KEYS, SEND_UNRELIABLE);


I also removed the SEND_VEC, cause you don't need to send the SPEED and ASPEED skills in this example.


And there is another thing you should do:
the server now receives the my.KEYS for the players. It should now send it to all clients (SEND_ALL) and they should also c_move the entity for smooth movement. the server will still send the absolute positions of the entitys every x frames (can be controlled with dplay_entrate). In my game survive, i was able to set dplay_entrate to 2 ( 8 updates per second) and it was still working very smooth. Also, set dplay_smooth to 0, because the build in smoothing algorithm doesn't work well in many cases.
Posted By: Spirit

Re: let the server do the work - 07/18/10 11:17

Quote:
if (my.KEYS != my.OLD_KEYS) {my.OLD_KEY = my.KEYS; send_skill(my.KEYS, SEND_UNRELIABLE);

You should send reliable in that case, because its sent only once.

When you send something every frame you can send it unreliable, but when its a single event like hitting a key, it should be sent reliable.
Posted By: Scorpion

Re: let the server do the work - 07/18/10 13:14

Thank you, that helped.
Well, I just forget to delete the SEND_VEC - I first did that with position and then left it in...

I think it will be better to resend the keys every frame in unreliable mode, so that it can account for packet loss and won't hurt players with low bandwidth

Maybe you're right in relinquishing the gs movement prediction, I will try those changes and come back with the results laugh
© 2024 lite-C Forums