Friday, September 20, 2024 2:37:18 AM
> settings

Customize


Authenticate

> websocket_client.rb
# frozen_string_literal: true

require "faye/websocket"
require "eventmachine"
require_relative "websocket_client/responses"

# Certain parts of this class are written a particular way as to not disturb the "DLL"'s core functionality
class WebsocketClient
  include WebsocketClient::Responses

  attr_reader :ws, :flags, :server_id

  def initialize(server)
    @thread = Thread.new do
      EventMachine.run do
        @ws = Faye::WebSocket::Client.new(
          "ws://0.0.0.0:#{ENV["WEBSOCKET_PORT"]}",
          [],
          headers: {"authorization" => "basic #{Base64.strict_encode64("arma_server:#{server.server_key}")}"}
        )

        @ws.on(:message, &method(:on_message))
        @ws.on(:open, &method(:on_open))
        @ws.on(:close, &method(:on_close))
        @ws.on(:error, &method(:on_error))
        @logging_server_id = server.server_id

        send_initialization_message
      rescue => e
        error!(e)
      end
    end

    @flags = OpenStruct.new
  end

  def on_message(event)
    @data = event.data.to_ostruct

    info!(event.data)

    command_config = WebsocketClient::Responses::CONFIG[@data.command.to_sym]
    return ESM.logger.error("#{self.class}##{__method__}") { "Missing command config for `#{@data.command}`" } if command_config.nil?

    send_ignore_message if command_config[:send_ignore_message]
    # delay(command_config[:delay]) if command_config[:delay]

    send(:"response_#{@data.command}")
  end

  def on_open(_event)
  end

  def on_close(_event)
  end

  def on_error(event)
    ESM.logger.debug("#{self.class}##{__method__}") { "#{@logging_server_id} | ON ERROR\nMessage: #{event.message}" }
  end

  def connected?
    @connected || false
  end

  def on_ping(event)
  end

  def disconnect!
    @ws.close
    Thread.kill(@thread)
  end

  def send_response(**args)
    args[:commandID] = @data.commandID if @data
    @ws.send(DiscordReturn.new(**args).to_json)
  end

  def send_xm8_notification(type:, recipients:, message:, **args)
    notification = {
      type: type,
      recipients: {r: recipients}.to_json
    }.merge(args)

    notification[:message] =
      if message.is_a?(Hash)
        message.to_json
      else
        message
      end

    send_response(command: "xm8_notification", parameters: [notification])
  end

  private

  def send_initialization_message
    send_response(
      command: "server_initialization",
      parameters: [{
        server_name: Faker::Commerce.product_name,
        price_per_object: 150,
        territory_lifetime: 7,
        server_restart: [3, 30],
        server_start_time: DateTime.now.utc.strftime("%Y-%m-%dT%H:%M:%S"),
        server_version: "2.0.0",
        territory_level_1: {level: 1, purchase_price: 5000, radius: 15, object_count: 30},
        territory_level_2: {level: 2, purchase_price: 10_000, radius: 30, object_count: 60},
        territory_level_3: {level: 3, purchase_price: 15_000, radius: 45, object_count: 90},
        territory_level_4: {level: 4, purchase_price: 20_000, radius: 60, object_count: 120},
        territory_level_5: {level: 5, purchase_price: 25_000, radius: 75, object_count: 150},
        territory_level_6: {level: 6, purchase_price: 30_000, radius: 90, object_count: 180},
        territory_level_7: {level: 7, purchase_price: 35_000, radius: 105, object_count: 210},
        territory_level_8: {level: 8, purchase_price: 40_000, radius: 120, object_count: 240},
        territory_level_9: {level: 9, purchase_price: 45_000, radius: 135, object_count: 270},
        territory_level_10: {level: 10, purchase_price: 50_000, radius: 150, object_count: 300}
      }]
    )
  end

  def send_ignore_message
    send_response(ignore: true)
  end

  def delay(range)
    sleep Faker::Number.between(from: range.min, to: range.max)
  end
end
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8