~starkingdoms/starkingdoms

3175763ebe33c13ea8b09d698eb36e47d1a2a214 — core 2 years ago 4e12d1b
input support
M Cargo.toml => Cargo.toml +4 -1
@@ 2,4 2,7 @@
members = [
    "server",
    "protocol"
]
\ No newline at end of file
]

[profile.dev.package.rapier2d-f64]
opt-level = 3
\ No newline at end of file

M assets/dist/spritesheet-125.json => assets/dist/spritesheet-125.json +5 -5
@@ 18,7 18,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "hearty.png": {
    "autoplr_error.png": {
      "frame": { "x": 0, "y": 320, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 27,7 27,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "autoplr_error.png": {
    "hearty.png": {
      "frame": { "x": 0, "y": 384, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 90,7 90,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "powerhub_on.png": {
    "hub_on.png": {
      "frame": { "x": 0, "y": 832, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 99,7 99,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "hub_on.png": {
    "autoplr_on.png": {
      "frame": { "x": 0, "y": 896, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,


@@ 108,7 108,7 @@
      "pivot": { "x": 32, "y": 32 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 64, "h": 64 }
    },
    "autoplr_on.png": {
    "powerhub_on.png": {
      "frame": { "x": 0, "y": 960, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-125.png => assets/dist/spritesheet-125.png +0 -0
M assets/dist/spritesheet-375.json => assets/dist/spritesheet-375.json +6 -6
@@ 18,7 18,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "hearty.png": {
    "autoplr_error.png": {
      "frame": { "x": 0, "y": 960, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 27,7 27,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "autoplr_error.png": {
    "hearty.png": {
      "frame": { "x": 0, "y": 1152, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 90,7 90,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "powerhub_on.png": {
    "autoplr_on.png": {
      "frame": { "x": 0, "y": 2496, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 108,7 108,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "autoplr_on.png": {
    "powerhub_on.png": {
      "frame": { "x": 0, "y": 2880, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 162,7 162,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "powerhub_off.png": {
    "hub_off.png": {
      "frame": { "x": 768, "y": 0, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,


@@ 171,7 171,7 @@
      "pivot": { "x": 96, "y": 96 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 192, "h": 192 }
    },
    "hub_off.png": {
    "powerhub_off.png": {
      "frame": { "x": 960, "y": 0, "w": 192, "h": 192 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-375.png => assets/dist/spritesheet-375.png +0 -0
M assets/dist/spritesheet-full.json => assets/dist/spritesheet-full.json +7 -7
@@ 18,7 18,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "hearty.png": {
    "autoplr_error.png": {
      "frame": { "x": 0, "y": 2560, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 27,7 27,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "autoplr_error.png": {
    "hearty.png": {
      "frame": { "x": 0, "y": 3072, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 90,7 90,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "powerhub_on.png": {
    "hub_on.png": {
      "frame": { "x": 512, "y": 2560, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 99,7 99,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "hub_on.png": {
    "autoplr_on.png": {
      "frame": { "x": 512, "y": 3072, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 108,7 108,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "autoplr_on.png": {
    "powerhub_on.png": {
      "frame": { "x": 512, "y": 3584, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 162,7 162,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "powerhub_off.png": {
    "hub_off.png": {
      "frame": { "x": 1024, "y": 2560, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,


@@ 171,7 171,7 @@
      "pivot": { "x": 256, "y": 256 },
      "9slicedFrame": { "x": 0, "y": 0, "w": 512, "h": 512 }
    },
    "hub_off.png": {
    "powerhub_off.png": {
      "frame": { "x": 1024, "y": 3072, "w": 512, "h": 512 },
      "rotated": false,
      "trimmed": false,

M assets/dist/spritesheet-full.png => assets/dist/spritesheet-full.png +0 -0
M client/src/index.ts => client/src/index.ts +59 -2
@@ 5,6 5,8 @@ import {Logger, logSetup} from "./logger";
import {gateway_connect, GatewayClient} from "./gateway";
import {Player} from "./protocol/player";
import {Planet, PlanetType} from "./protocol/planet";
import {MessageC2SInput, MessageC2SInput_packetInfo} from "./protocol/message_c2s";
import {encode} from "./serde";

logSetup();
const logger = new Logger("client");


@@ 17,8 19,17 @@ export interface GlobalData {
    canvas: HTMLCanvasElement,
    spritesheet_img: HTMLImageElement | null,
    spritesheet: object | null,
    context: CanvasRenderingContext2D
    context: CanvasRenderingContext2D,
    keys: Keys
}

export interface Keys {
    up: boolean,
    left: boolean,
    down: boolean,
    right: boolean
}

export const global: GlobalData = {
    client: null,
    players: [],


@@ 27,7 38,13 @@ export const global: GlobalData = {
    canvas: <HTMLCanvasElement>document.getElementById("canvas"),
    spritesheet_img: null,
    spritesheet: null,
    context: <CanvasRenderingContext2D>(<HTMLCanvasElement>document.getElementById("canvas")).getContext("2d")
    context: <CanvasRenderingContext2D>(<HTMLCanvasElement>document.getElementById("canvas")).getContext("2d"),
    keys: {
        up: false,
        down: false,
        left: false,
        right: false
    }
}

async function client_main(server: string, username: string, texture_quality: string) {


@@ 72,6 89,46 @@ async function client_main(server: string, username: string, texture_quality: st

    global.canvas.style.setProperty("background-image", `url("/assets/final/${texture_quality}/starfield.png")`);

    document.onkeydown = (e) => {
        if (e.code == "ArrowLeft") { // arrow-left
            global.keys.left = true;
        } else if (e.code == "ArrowRight") { // arrow-right
            global.keys.right = true;
        } else if (e.code == "ArrowUp") { // arrow-up
            global.keys.up = true;
        } else if (e.code == "ArrowDown") { // arrow-down
            global.keys.down = true;
        }

        let msg = MessageC2SInput.encode({
            upPressed: global.keys.up,
            downPressed: global.keys.down,
            leftPressed: global.keys.left,
            rightPressed: global.keys.right
        }).finish();

        global.client?.socket.send(encode(MessageC2SInput_packetInfo.type, msg));
    }
    document.onkeyup = (e) => {
        if (e.code == "ArrowLeft") { // arrow-left
            global.keys.left = false;
        } else if (e.code == "ArrowRight") { // arrow-right
            global.keys.right = false;
        } else if (e.code == "ArrowUp") { // arrow-up
            global.keys.up = false;
        } else if (e.code == "ArrowDown") { // arrow-down
            global.keys.down = false;
        }

        let msg = MessageC2SInput.encode({
            upPressed: global.keys.up,
            downPressed: global.keys.down,
            leftPressed: global.keys.left,
            rightPressed: global.keys.right
        }).finish();
        global.client?.socket.send(encode(MessageC2SInput_packetInfo.type, msg));
    }

    let last_time = performance.now();
    let render = (now_time: DOMHighResTimeStamp) => {
        const delta_ms = now_time - last_time;

M client/src/protocol/message_c2s.ts => client/src/protocol/message_c2s.ts +137 -0
@@ 159,6 159,46 @@ export function messageC2SPing_packetInfoToJSON(object: MessageC2SPing_packetInf
  }
}

export interface MessageC2SInput {
  upPressed: boolean;
  downPressed: boolean;
  leftPressed: boolean;
  rightPressed: boolean;
}

export enum MessageC2SInput_packetInfo {
  unknown = 0,
  type = 11,
  UNRECOGNIZED = -1,
}

export function messageC2SInput_packetInfoFromJSON(object: any): MessageC2SInput_packetInfo {
  switch (object) {
    case 0:
    case "unknown":
      return MessageC2SInput_packetInfo.unknown;
    case 11:
    case "type":
      return MessageC2SInput_packetInfo.type;
    case -1:
    case "UNRECOGNIZED":
    default:
      return MessageC2SInput_packetInfo.UNRECOGNIZED;
  }
}

export function messageC2SInput_packetInfoToJSON(object: MessageC2SInput_packetInfo): string {
  switch (object) {
    case MessageC2SInput_packetInfo.unknown:
      return "unknown";
    case MessageC2SInput_packetInfo.type:
      return "type";
    case MessageC2SInput_packetInfo.UNRECOGNIZED:
    default:
      return "UNRECOGNIZED";
  }
}

function createBaseMessageC2SHello(): MessageC2SHello {
  return { version: 0, requestedUsername: "", nextState: 0 };
}


@@ 399,6 439,103 @@ export const MessageC2SPing = {
  },
};

function createBaseMessageC2SInput(): MessageC2SInput {
  return { upPressed: false, downPressed: false, leftPressed: false, rightPressed: false };
}

export const MessageC2SInput = {
  encode(message: MessageC2SInput, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
    if (message.upPressed === true) {
      writer.uint32(8).bool(message.upPressed);
    }
    if (message.downPressed === true) {
      writer.uint32(16).bool(message.downPressed);
    }
    if (message.leftPressed === true) {
      writer.uint32(24).bool(message.leftPressed);
    }
    if (message.rightPressed === true) {
      writer.uint32(32).bool(message.rightPressed);
    }
    return writer;
  },

  decode(input: _m0.Reader | Uint8Array, length?: number): MessageC2SInput {
    const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
    let end = length === undefined ? reader.len : reader.pos + length;
    const message = createBaseMessageC2SInput();
    while (reader.pos < end) {
      const tag = reader.uint32();
      switch (tag >>> 3) {
        case 1:
          if (tag != 8) {
            break;
          }

          message.upPressed = reader.bool();
          continue;
        case 2:
          if (tag != 16) {
            break;
          }

          message.downPressed = reader.bool();
          continue;
        case 3:
          if (tag != 24) {
            break;
          }

          message.leftPressed = reader.bool();
          continue;
        case 4:
          if (tag != 32) {
            break;
          }

          message.rightPressed = reader.bool();
          continue;
      }
      if ((tag & 7) == 4 || tag == 0) {
        break;
      }
      reader.skipType(tag & 7);
    }
    return message;
  },

  fromJSON(object: any): MessageC2SInput {
    return {
      upPressed: isSet(object.upPressed) ? Boolean(object.upPressed) : false,
      downPressed: isSet(object.downPressed) ? Boolean(object.downPressed) : false,
      leftPressed: isSet(object.leftPressed) ? Boolean(object.leftPressed) : false,
      rightPressed: isSet(object.rightPressed) ? Boolean(object.rightPressed) : false,
    };
  },

  toJSON(message: MessageC2SInput): unknown {
    const obj: any = {};
    message.upPressed !== undefined && (obj.upPressed = message.upPressed);
    message.downPressed !== undefined && (obj.downPressed = message.downPressed);
    message.leftPressed !== undefined && (obj.leftPressed = message.leftPressed);
    message.rightPressed !== undefined && (obj.rightPressed = message.rightPressed);
    return obj;
  },

  create<I extends Exact<DeepPartial<MessageC2SInput>, I>>(base?: I): MessageC2SInput {
    return MessageC2SInput.fromPartial(base ?? {});
  },

  fromPartial<I extends Exact<DeepPartial<MessageC2SInput>, I>>(object: I): MessageC2SInput {
    const message = createBaseMessageC2SInput();
    message.upPressed = object.upPressed ?? false;
    message.downPressed = object.downPressed ?? false;
    message.leftPressed = object.leftPressed ?? false;
    message.rightPressed = object.rightPressed ?? false;
    return message;
  },
};

type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;

export type DeepPartial<T> = T extends Builtin ? T

M protocol/src/lib.rs => protocol/src/lib.rs +10 -3
@@ 1,6 1,6 @@
use std::error::Error;
use protobuf::{Enum, Message};
use crate::message_c2s::{MessageC2SChat, MessageC2SGoodbye, MessageC2SHello, MessageC2SPing};
use crate::message_c2s::{MessageC2SChat, MessageC2SGoodbye, MessageC2SHello, MessageC2SInput, MessageC2SPing};
use crate::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong};
use crate::planet::PlanetType;
use crate::starkingdoms_protocol::PacketWrapper;


@@ 13,7 13,8 @@ pub enum MessageC2S {
    Hello(MessageC2SHello),
    Goodbye(MessageC2SGoodbye),
    Chat(MessageC2SChat),
    Ping(MessageC2SPing)
    Ping(MessageC2SPing),
    Input(MessageC2SInput)
}

#[derive(Debug)]


@@ 44,8 45,11 @@ impl TryFrom<&[u8]> for MessageC2S {
            },
            _id if _id == message_c2s::message_c2sping::Packet_info::type_.value() as i64 => {
                MessageC2S::Ping(MessageC2SPing::parse_from_bytes(&pkt.packet_data)?)
            },
            _id if _id == message_c2s::message_c2sinput::Packet_info::type_.value() as i64 => {
                MessageC2S::Input(MessageC2SInput::parse_from_bytes(&pkt.packet_data)?)
            }
            _ => { return Err("Not a C2S packet".into()); }
            _id => { return Err(format!("Unrecognized C2S packet {}", _id).into()); }
        };

        Ok(deser_pkt)


@@ 69,6 73,9 @@ impl TryInto<Vec<u8>> for MessageC2S {
            MessageC2S::Ping(p) => {
                (message_c2s::message_c2sping::Packet_info::type_.value(), p.write_to_bytes()?)
            }
            MessageC2S::Input(p) => {
                (message_c2s::message_c2sping::Packet_info::type_.value(), p.write_to_bytes()?)
            }
        };

        let pkt = PacketWrapper {

M protocol/src/pbuf/message_c2s.proto => protocol/src/pbuf/message_c2s.proto +9 -0
@@ 26,4 26,13 @@ message MessageC2SChat {

message MessageC2SPing {
  enum packet_info { unknown = 0; type = 0x04; }
}

message MessageC2SInput {
  enum packet_info { unknown = 0; type = 0x0b; }

  bool up_pressed = 1;
  bool down_pressed = 2;
  bool left_pressed = 3;
  bool right_pressed = 4;
}
\ No newline at end of file

M server/Cargo.toml => server/Cargo.toml +1 -1
@@ 25,4 25,4 @@ rapier2d-f64 = { version = "0.17.2", features = [ "simd-stable" ] }
nalgebra = "0.32.2"

[build-dependencies]
cargo_metadata = "0.15"
cargo_metadata = "0.15"
\ No newline at end of file

M server/src/handler.rs => server/src/handler.rs +11 -2
@@ 5,7 5,7 @@ use std::time::{Duration, SystemTime};
use futures::stream::{SplitSink, SplitStream};
use futures::{FutureExt, SinkExt, StreamExt};
use hyper::upgrade::Upgraded;
use log::{error, info};
use log::{debug, error, info};
use nalgebra::vector;
use rapier2d_f64::prelude::{RigidBodyBuilder, RigidBodyType, ColliderBuilder};
use tokio::sync::RwLock;


@@ 148,7 148,7 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
                                data_handle.rigid_body_set = rigid_body_set;
                                data_handle.collider_set = collider_set;

                                mgr.players.write().await.insert(remote_addr, Player { handle: player_handle });
                                mgr.players.write().await.insert(remote_addr, Player { handle: player_handle, input: Default::default() });
                            }
                        },
                        MessageC2S::Goodbye(pkt) => {


@@ 199,6 199,15 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
                            }).try_into()?;
                            send!(client_tx, msg).await?;
                            ping_timeout = SystemTime::now() + Duration::from_secs(10);
                        },
                        MessageC2S::Input(p) => {
                            let mut players = mgr.players.write().await;
                            let me = players.get_mut(&remote_addr).expect("player disconnected but continued to send packets");
                            me.input.up = p.up_pressed;
                            me.input.down = p.down_pressed;
                            me.input.left = p.left_pressed;
                            me.input.right = p.right_pressed;
                            debug!("{} {} {} {}", me.input.up, me.input.down, me.input.left, me.input.right);
                        }
                    }
                }

M server/src/main.rs => server/src/main.rs +1 -1
@@ 50,7 50,7 @@ async fn handle_request(mut request: Request<Body>, remote_addr: SocketAddr, mgr
                                        //pass the upgraded object
                                        //as the base layer stream of the Websocket
                                        upgraded,
                                        tokio_tungstenite::tungstenite::protocol::Role::Server,
                                        tungstenite::protocol::Role::Server,
                                        None,
                                    ).await;


M server/src/manager.rs => server/src/manager.rs +10 -1
@@ 15,7 15,16 @@ pub struct ClientManager {

#[derive(Default)]
pub struct Player {
    pub handle: RigidBodyHandle
    pub handle: RigidBodyHandle,
    pub input: PlayerInput
}

#[derive(Default)]
pub struct PlayerInput {
    pub up: bool,
    pub left: bool,
    pub right: bool,
    pub down: bool
}

#[derive(Clone)]

M server/src/timer.rs => server/src/timer.rs +34 -3
@@ 1,11 1,14 @@
use std::{time::Duration, sync::Arc};
use log::{error};
use log::{debug, error};
use nalgebra::vector;
use rapier2d_f64::prelude::{PhysicsPipeline};
use tokio::{time::sleep, sync::RwLock};
use starkingdoms_protocol::player::Player;
use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE, planet::Planets};

pub const ROTATIONAL_FORCE: f64 = 100.0;
pub const LATERAL_FORCE: f64 = 100.0;

pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>, world_data: Arc<RwLock<Planets>>) {
    let mut pipeline = PhysicsPipeline::new();
    loop {


@@ 24,8 27,36 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData
                let grav_force = planets.gravity((player_body.translation().x, player_body.translation().y), player_body.mass());
                player_body.add_force(vector![grav_force.0, grav_force.1], true);

                let mut torque = 0.0;

                if player.input.right {
                    torque += ROTATIONAL_FORCE;
                }
                if player.input.left {
                    torque -= ROTATIONAL_FORCE;
                }

                player_body.add_torque(torque, true);

                let mut lateral = vector![0.0, 0.0];

                if player.input.up {
                    lateral -= vector![0.0, LATERAL_FORCE];
                }
                if player.input.down {
                    lateral += vector![0.0, LATERAL_FORCE];
                }

                let rotation = player_body.rotation().clone().angle();

                let lateral_rotated = vector![
                    lateral.x * rotation.cos() - lateral.y * rotation.sin(),
                    lateral.x * rotation.sin() + lateral.y * rotation.cos()
                ];

                player_body.add_force(lateral_rotated, true);

                let translation = player_body.translation();
                let rotation = player_body.rotation();

                let username;
                {


@@ 35,7 66,7 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData

                // TODO: Figure out how to adjust codegen to use f64
                protocol_players.push(Player {
                    rotation: rotation.angle() as f32,
                    rotation: rotation as f32,
                    x: (translation.x * SCALE) as f32,
                    y: (translation.y * SCALE) as f32,
                    username,