Simulate Controller on [GlobalBehaviour]?

Hi :smiley: How would it be a Simulate Controller void, which affects all entities in an array, hosted on a GlobalBehaviour script? Thanks :)

Answers

  • The simulate controller function is entity specific and wouldn't really make sense to be called from a global class. What exactly are you trying to do?
  • From the tutorial.

    public class PlayerController : Bolt.EntityEventListener
    {
    public override void SimulateOwner ()
    {
    if ((BoltNetwork.frame % 5) == 0 && (state.Dead == false)) {
    state.Health = (byte)Mathf.Clamp (state.Health + 1, 0, 100);
    }
    }
    }
  • Manmax75 said:

    The simulate controller function is entity specific and wouldn't really make sense to be called from a global class. What exactly are you trying to do?

    To run this script on the server:

    using UnityEngine;


    [BoltGlobalBehaviour(BoltNetworkModes.Server)]
    public class PlayerAuth : Bolt.EntityBehaviour {
    const float MOUSE_SENSITIVITY = 4f;

    bool _forward;
    bool _backward;
    bool _left;
    bool _right;
    bool _jump;

    float _yaw;
    float _pitch;

    PlayerMotor _motor;

    void Awake() {
    _motor = GetComponent();
    }

    public override void Attached() {
    state.Transform.SetTransforms(transform);
    }

    void PollKeys(bool mouse) {
    _forward = Input.GetKey(KeyCode.W);
    _backward = Input.GetKey(KeyCode.S);
    _left = Input.GetKey(KeyCode.A);
    _right = Input.GetKey(KeyCode.D);
    _jump = Input.GetKeyDown(KeyCode.Space);

    if (mouse) {
    _yaw += (Input.GetAxisRaw("Mouse X") * MOUSE_SENSITIVITY);
    _yaw %= 360f;

    _pitch += (-Input.GetAxisRaw("Mouse Y") * MOUSE_SENSITIVITY);
    _pitch = Mathf.Clamp(_pitch, -85f, +85f);
    }
    }

    void Update() {
    PollKeys(true);
    }

    public override void SimulateController() {
    PollKeys(false);

    IPlayerCommandInput input = PlayerCommand.Create();

    input.Forward = _forward;
    input.Backward = _backward;
    input.Left = _left;
    input.Right = _right;
    input.Jump = _jump;
    input.Yaw = _yaw;
    input.Pitch = _pitch;

    entity.QueueInput(input);
    }

    public override void ExecuteCommand(Bolt.Command command, bool resetState) {
    PlayerCommand cmd = (PlayerCommand)command;

    if (resetState) {
    // we got a correction from the server, reset (this only runs on the client)
    _motor.SetState(cmd.Result.Position, cmd.Result.Velocity, cmd.Result.IsGrounded, cmd.Result.JumpFrames);
    }
    else {
    // apply movement (this runs on both server and client)
    PlayerMotor.State motorState = _motor.Move(cmd.Input.Forward, cmd.Input.Backward, cmd.Input.Left, cmd.Input.Right, cmd.Input.Jump, cmd.Input.Yaw);

    // copy the motor state to the commands result (this gets sent back to the client)
    cmd.Result.Position = motorState.position;
    cmd.Result.Velocity = motorState.velocity;
    cmd.Result.IsGrounded = motorState.isGrounded;
    cmd.Result.JumpFrames = motorState.jumpFrames;
    }
    }
    }
  • Manmax75
    Manmax75
    edited July 2015
    Ah see that script wouldn't run in a global class, instead you attach it to an entity. You're on the right track, as this codes from the tutorial and it explains more. But simply put this in a script, attach it to your gameobject that has the BoltEntitity on it and then set its "state" to the one you defined.

    This class also needs to be declared as
    public class PlayerAuth : Bolt.EntityBehaviour<WhateverYourStateIs>

    And remove the top line [BoltGlobalBehaviour(BoltNetworkModes.Server)]

    Then SimulateController is only called on the connection that actually controls the entity and from memory that's (automatically?) the owner
  • on the connection that actually controls the entity and from memory that's (automatically?) the owner
    The controller is not automatically set. As described in the tutorial, the owner can take control of the entity with entity.TakeControl() or it can assign control to a client with entity.AssignControl(connection). I assign controls in a BoltGlobalBehaviour class after instantiating the entities.

    There's a SimulateOwner analog to the SimulateController method.
  • I dont want this script to been run on clients. Im using it as Anti-Speedhack (prevent using motion hacks). If I run this on a client with no hacks, this script is executes x times per second, and if the user is speedhacking, that is multiplied. I need to check on the server how many frames passed since last movement to prevent this. And my question/problem is, how can I manage inputs?
  • I'm not sure what you are trying to do. Since you are using commands, you are using server authoritative movement. In this case, the server has authority over movement. The client can try all the movement hacks he wants, the server doesn't care and will just correct it. No other proxies will see the movement hacks since the server, and not the client, is the authority, and the client will gain no advantage to trying to do so (other than getting crazy movement on his own machine that has no effect on the server's simulation).

    If you are trying to detect the client is doing this anyway in order to boot him (I don't really understand why, since it doesn't affect anything), but if you are, I'm not sure how you can do so without a client side detection mecanism, since the server is just receiving commands. And if the client tries to mess with the command queue (inserting extra commands, etc, bolt will just disconnect him).