ledmon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 040e65bfb0510118bea7a5e33794b12a90210645f5fe58f3530596244fb43055
4
+ data.tar.gz: 2acd90b6c3322fc5a0fc9c41a34b31e8f96b1a962064a77b4e45375bd8ca29dc
5
+ SHA512:
6
+ metadata.gz: a349f200a4dec63d515d5a185b8d74a7f8e1eafd103c2b1fdaad046a8a13b262cfda863f4ee518d1b4ca7612f62fb95cbd046c46adc3253989111682b212a5fe
7
+ data.tar.gz: d84ae4b9a22c84728dcd61a4bd6c52429831cbf529c99024c8a39f1742e0be191710f821a8964185f8927dad1696688c159131a9772465eb749c37a92e39b222
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Ahmed Al Hafoudh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,5 @@
1
+ update_protos:
2
+ rsync -avh --delete ../ledmon-engine/app/engine/ledmon/protos/ ./protos/
3
+
4
+ generate: update_protos
5
+ grpc_tools_ruby_protoc -I ./protos --ruby_out=lib/ledmon --grpc_out=lib/ledmon ./protos/world.proto
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Ledmon
2
+
3
+ ## Usage
4
+
5
+ Run `bundle exec exe/ledmon monster local` to run monster locally.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/exe/ledmon ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Thread.report_on_exception = false
4
+
5
+ require "ledmon"
6
+
7
+ Ledmon::CLI::Main.start(ARGV)
@@ -0,0 +1,7 @@
1
+ module Ledmon::CLI
2
+ class Base < Thor
3
+ def self.exit_on_failure?()
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module Ledmon::CLI
2
+ class Config < Base
3
+ def self.config_value(name, description: nil)
4
+ desc "#{name} [VALUE]", description || "Read or set #{name} value"
5
+ define_method(name) do |value = nil|
6
+ if value
7
+ puts Ledmon::Config.public_send(:"#{name}=", value)
8
+ else
9
+ puts Ledmon::Config.public_send(name.to_sym)
10
+ end
11
+ end
12
+ end
13
+
14
+ config_value :host
15
+ config_value :grpc_port
16
+ config_value :http_port
17
+ config_value :auth
18
+ config_value :mode
19
+ config_value :log_level
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Ledmon::CLI
2
+ class Main < Base
3
+ desc 'version', 'Prints the version'
4
+
5
+ def version
6
+ puts Ledmon::VERSION
7
+ end
8
+
9
+ desc 'config', 'Manage config'
10
+ subcommand 'config', Ledmon::CLI::Config
11
+
12
+ desc 'monster', 'Manage monster'
13
+ subcommand 'monster', Ledmon::CLI::Monster
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ module Ledmon::CLI
2
+ class Monster < Base
3
+ desc 'local', 'Run the monster from local machine'
4
+
5
+ def local
6
+ runner = Ledmon::Monster::Runner.new(path: Dir.pwd)
7
+ runner.run!
8
+ rescue Interrupt
9
+ exit 1
10
+ rescue Ledmon::Error => e
11
+ say_error e.message, :yellow
12
+ if Ledmon::Config.log_level.to_sym == :debug
13
+ say_error e.backtrace.join("\n"), :white
14
+ end
15
+ end
16
+
17
+ desc 'deploy', 'Deploy monster code to remote server'
18
+
19
+ def deploy
20
+ packer = Ledmon::Monster::Packer.new(path: Dir.pwd)
21
+ packer.pack! do |bundle_path|
22
+ deployer = Ledmon::Monster::Deployer.new(bundle_path:)
23
+ say "Uploading packed file ...", :yellow
24
+
25
+ deployer.deploy! do |json_data|
26
+ if json_data['message']
27
+ say json_data['message'], :cyan
28
+ elsif json_data['error']
29
+ say_error json_data['error'], :red
30
+ else
31
+ say json_data.to_s, :white
32
+ end
33
+ end
34
+
35
+ say "Successfully deployed monster code!", :green
36
+ end
37
+ rescue Ledmon::Error => e
38
+ say_error e.message, :red
39
+ exit 1
40
+ end
41
+ end
42
+ end
data/lib/ledmon/cli.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Ledmon
2
+ module CLI
3
+ end
4
+ end
@@ -0,0 +1,48 @@
1
+ module Ledmon
2
+ class Configurator
3
+ attr_reader :config
4
+
5
+ def initialize
6
+ @config = TTY::Config.new
7
+ config.filename = '.ledmon'
8
+ config.append_path Dir.pwd
9
+ config.env_prefix = 'ledmon'
10
+
11
+ config.read if config.exist?
12
+ end
13
+
14
+ def self.config_value(name, keys: nil, default: nil)
15
+ keys = Array(keys || name).map(&:to_sym)
16
+
17
+ define_method(name) do
18
+ read_value(keys, default:)
19
+ end
20
+
21
+ define_method("#{name}=") do |value|
22
+ write_value(keys, value:)
23
+ end
24
+ end
25
+
26
+ config_value :host, default: 'localhost'
27
+ config_value :grpc_port, default: 50051
28
+ config_value :http_port, default: 4000
29
+ config_value :auth
30
+
31
+ config_value :mode, default: 'client'
32
+ config_value :log_level, default: 'info'
33
+
34
+ private
35
+
36
+ def read_value(keys, default: nil)
37
+ config.set_from_env(*keys)
38
+ config.fetch(*keys, default:)
39
+ end
40
+
41
+ def write_value(keys, value:)
42
+ config.set(*keys, value:)
43
+ config.write(create: true, force: true)
44
+
45
+ value
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ module Ledmon::Interceptors
2
+ class SleepInterceptor < ::GRPC::ClientInterceptor
3
+ def initialize
4
+ @sleep_until = nil
5
+ end
6
+
7
+ def request_response(request: nil, call: nil, method: nil, metadata: nil, &block)
8
+ if @sleep_until
9
+ remaining_sleep_time = @sleep_until - Time.now.to_f
10
+ if remaining_sleep_time > 0
11
+ micro_sleep remaining_sleep_time
12
+ end
13
+ @sleep_until = nil
14
+ end
15
+
16
+ response = block.call(request:, call:, method:, metadata:)
17
+
18
+ if response.respond_to?(:sleep_time)
19
+ @sleep_until = Time.now.to_f + response.sleep_time
20
+ end
21
+
22
+ response
23
+ end
24
+
25
+ private
26
+
27
+ def micro_sleep(amount)
28
+ IO.select(nil, nil, nil, amount)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ledmon::Monster
4
+ class Deployer
5
+ attr_reader :bundle_path
6
+
7
+ def initialize(bundle_path:)
8
+ @bundle_path = bundle_path
9
+ end
10
+
11
+ def deploy!(&block)
12
+ require 'http'
13
+ require 'json'
14
+
15
+ url = build_upload_url
16
+ headers = {
17
+ 'Authorization' => "Bearer #{Ledmon::Config.auth}",
18
+ }
19
+
20
+ response = HTTP.headers(headers).post(url, form: { file: HTTP::FormData::File.new(bundle_path) })
21
+
22
+ unless response.status.success?
23
+ raise Ledmon::Error, "Deploy failed with status: #{response.status}"
24
+ end
25
+
26
+ buffer = ""
27
+ response.body.each do |chunk|
28
+ buffer += chunk
29
+
30
+ while buffer.include?("\n")
31
+ line, buffer = buffer.split("\n", 2)
32
+ process_json_line(line, &block)
33
+ end
34
+ end
35
+
36
+ # Process any remaining data in buffer
37
+ process_json_line(buffer, &block) unless buffer.strip.empty?
38
+ end
39
+
40
+ private
41
+
42
+ def process_json_line(line, &block)
43
+ line = line.strip
44
+ return if line.empty?
45
+
46
+ begin
47
+ json_data = JSON.parse(line)
48
+ block&.call(json_data)
49
+ rescue JSON::ParserError
50
+ # Skip invalid JSON lines
51
+ end
52
+ end
53
+
54
+ def build_upload_url
55
+ "http://#{Ledmon::Config.host}:#{Ledmon::Config.http_port}/deploys"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,50 @@
1
+ module Ledmon::Monster
2
+ class Executor
3
+ include Session
4
+ include Terminal
5
+ include Interaction
6
+ include Movement
7
+
8
+ attr_reader :mode
9
+ attr_reader :logger
10
+
11
+ def initialize(mode: :client)
12
+ @mode = mode
13
+
14
+ @logger = Logger.new(STDERR)
15
+ logger.level = Ledmon::Config.log_level.to_sym
16
+ end
17
+
18
+ def setup
19
+ session_connect!
20
+ end
21
+
22
+ ###
23
+
24
+ def avatar
25
+ raise Ledmon::Error, "#{__method__} is not implemented!"
26
+ end
27
+
28
+ def brain
29
+ raise Ledmon::Error, "#{__method__} is not implemented!"
30
+ end
31
+
32
+ def algo(id, input)
33
+ raise Ledmon::Error, "#{__method__} is not implemented!"
34
+ end
35
+
36
+ def algo_result(result, id, input, output)
37
+ raise Ledmon::Error, "#{__method__} is not implemented!"
38
+ end
39
+
40
+ ###
41
+
42
+ def server?
43
+ mode == :server
44
+ end
45
+
46
+ def client?
47
+ mode == :client
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,80 @@
1
+ module Ledmon::Monster
2
+ module Interaction
3
+ extend ActiveSupport::Concern
4
+
5
+ def interact
6
+ queue = Queue.new
7
+ requests = Enumerator.new do |yielder|
8
+ loop do
9
+ message = queue.pop
10
+ yielder << message
11
+ end
12
+ end
13
+
14
+ queue << Ledmon::InteractionRequest.new(
15
+ action: Ledmon::InteractionRequestAction::START,
16
+ )
17
+
18
+ last_challenge_response = nil
19
+ last_challenge_algo_output = nil
20
+
21
+ client.interact(requests).map do |response|
22
+ logger.debug("Got response: #{response}")
23
+
24
+ if response.action == :CHALLENGE
25
+ logger.debug("Challenge ID: #{response.challenge_id}")
26
+ logger.debug("Challenge Input: #{response.challenge_input}")
27
+
28
+ algo_output = algo(response.challenge_id, response.challenge_input)
29
+
30
+ last_challenge_response = response
31
+ last_challenge_algo_output = algo_output
32
+
33
+ queue << Ledmon::InteractionRequest.new(
34
+ action: Ledmon::InteractionRequestAction::SUBMIT_CHALLENGE,
35
+ challenge_response: algo_output.to_s,
36
+ )
37
+
38
+ elsif response.action == :SUCCESS
39
+ logger.debug("Challenge succeeded!")
40
+ return true, last_challenge_response.challenge_id, last_challenge_response.challenge_input, last_challenge_algo_output
41
+ elsif response.action == :FAILURE
42
+ logger.debug("Challenge failed!")
43
+ return false, last_challenge_response.challenge_id, last_challenge_response.challenge_input, last_challenge_algo_output
44
+ end
45
+ end
46
+ end
47
+
48
+ def craft(recipe)
49
+ client.craft(Ledmon::CraftData.new(recipe:))
50
+ end
51
+
52
+ def research(item)
53
+ client.research(Ledmon::ItemInfo.new(item:))
54
+ end
55
+
56
+ def equip_item(item, slot)
57
+ client.equip_item(Ledmon::EquipInfo.new(item:, slot:))
58
+ end
59
+
60
+ def unequip_item(slot)
61
+ client.unequip_item(Ledmon::UnequipInfo.new(slot:))
62
+ end
63
+
64
+ def get_inventory
65
+ client.get_inventory(Ledmon::Empty.new)
66
+ end
67
+
68
+ def get_health
69
+ client.get_health(Ledmon::Empty.new).health
70
+ end
71
+
72
+ def attack
73
+ client.attack(Ledmon::Empty.new)
74
+ end
75
+
76
+ def look
77
+ client.look(Ledmon::Empty.new).entities
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,21 @@
1
+ module Ledmon::Monster
2
+ module Movement
3
+ extend ActiveSupport::Concern
4
+
5
+ def move_forward
6
+ client.move_forward(Ledmon::Empty.new)
7
+ end
8
+
9
+ def move_backward
10
+ client.move_backward(Ledmon::Empty.new)
11
+ end
12
+
13
+ def turn_left
14
+ client.turn_left(Ledmon::Empty.new)
15
+ end
16
+
17
+ def turn_right
18
+ client.turn_right(Ledmon::Empty.new)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,74 @@
1
+ require 'zlib'
2
+ require 'rubygems/package'
3
+ require 'active_support/core_ext/numeric/bytes'
4
+ require 'tempfile'
5
+
6
+ module Ledmon
7
+ module Monster
8
+ class Packer
9
+ MAX_FILE_SIZE = 100.kilobytes
10
+ MAX_PACK_SIZE = 10.megabytes
11
+
12
+ class FileTooLargeError < StandardError; end
13
+
14
+ class PackTooLargeError < StandardError; end
15
+
16
+ def initialize(path:)
17
+ @path = path
18
+ @current_pack_size = 0
19
+ end
20
+
21
+ def pack!
22
+ raise ArgumentError, "Block required" unless block_given?
23
+
24
+ Tempfile.create(%w[ledmon_pack .tar.gz]) do |tempfile|
25
+ tempfile.binmode
26
+
27
+ Zlib::GzipWriter.wrap(tempfile) do |gz|
28
+ Gem::Package::TarWriter.new(gz) do |tar|
29
+ pack_directory(tar, @path)
30
+ end
31
+ end
32
+
33
+ yield tempfile.path
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def pack_directory(tar, dir_path, relative_path = '')
40
+ Dir.foreach(dir_path) do |entry|
41
+ next if entry == '.' || entry == '..'
42
+
43
+ full_path = File.join(dir_path, entry)
44
+ entry_relative_path = relative_path.empty? ? entry : File.join(relative_path, entry)
45
+
46
+ if File.directory?(full_path)
47
+ pack_directory(tar, full_path, entry_relative_path)
48
+ else
49
+ pack_file(tar, full_path, entry_relative_path)
50
+ end
51
+ end
52
+ end
53
+
54
+ def pack_file(tar, file_path, relative_path)
55
+ file_size = File.size(file_path)
56
+
57
+ raise FileTooLargeError, "File #{relative_path} (#{file_size} bytes) exceeds maximum size of #{MAX_FILE_SIZE} bytes" if file_size > MAX_FILE_SIZE
58
+
59
+ if @current_pack_size + file_size > MAX_PACK_SIZE
60
+ raise PackTooLargeError, "Adding file #{relative_path} would exceed maximum pack size of #{MAX_PACK_SIZE} bytes"
61
+ end
62
+
63
+ file_stat = File.stat(file_path)
64
+ tar.add_file_simple(relative_path, file_stat.mode, file_stat.size) do |io|
65
+ File.open(file_path, 'rb') do |file|
66
+ IO.copy_stream(file, io)
67
+ end
68
+ end
69
+
70
+ @current_pack_size += file_size
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,44 @@
1
+ module Ledmon::Monster
2
+ class Runner
3
+ class Error < StandardError; end
4
+ class ScriptNotFoundError < Error; end
5
+
6
+ attr_reader :path
7
+ attr_reader :script_path
8
+ attr_reader :script
9
+ attr_reader :executor
10
+
11
+ def initialize(path:)
12
+ @path = path
13
+ @script_path = File.join(path, 'monster.rb')
14
+ @executor = Executor.new(mode:)
15
+ end
16
+
17
+ def run!
18
+ load_script!
19
+ setup!
20
+ execute!
21
+ end
22
+
23
+ private
24
+
25
+ def setup!
26
+ executor.instance_eval(script, script_path)
27
+ executor.setup
28
+ end
29
+
30
+ def execute!
31
+ executor.brain
32
+ end
33
+
34
+ def load_script!
35
+ raise ScriptNotFoundError.new("Monster script not found at #{script_path}") unless File.exist?(script_path)
36
+
37
+ @script = File.read(script_path)
38
+ end
39
+
40
+ def mode
41
+ Ledmon::Config.mode.to_sym
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,70 @@
1
+ module Ledmon::Monster
2
+ module Session
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attr_reader :client
7
+ attr_reader :name
8
+ end
9
+
10
+ def session_connect!
11
+ @client = Ledmon::World::Stub.new(
12
+ session_grpc_host,
13
+ :this_channel_is_insecure,
14
+ interceptors: [
15
+ Ledmon::Interceptors::SleepInterceptor.new,
16
+ ],
17
+ )
18
+
19
+ session_responses = client.session(Ledmon::SessionRequest.new(token: Ledmon::Config.auth, avatar:,))
20
+
21
+ start_response = session_responses.next
22
+
23
+ @name = start_response.name
24
+
25
+ logger.debug("Got response: #{start_response.inspect}")
26
+
27
+ if start_response.status == :STARTED
28
+ logger.debug("Session started. Welcome, #{name}!")
29
+ else
30
+ raise Ledmon::Error, "Failed to start session: #{start_response.status}"
31
+ end
32
+
33
+ Thread.new do
34
+ loop do
35
+ session_responses.map do |response|
36
+ case response.status
37
+ when :FINISHED
38
+ logger.debug("Session finished.")
39
+ throw :finished
40
+ else
41
+ logger.debug("Received unknown response: #{response.inspect}")
42
+ end
43
+ end
44
+ end
45
+ rescue => ex
46
+ logger.error("An error occurred: #{ex.message}")
47
+ logger.error(ex.backtrace.join("\n"))
48
+ end
49
+
50
+ Thread.new do
51
+ loop do
52
+ client.keep_alive(Ledmon::Empty.new)
53
+ sleep 1
54
+ end
55
+ rescue GRPC::Unavailable => ex
56
+ logger.debug("Server is unavailable: #{ex.message}")
57
+ error "Server disconnected."
58
+ exit 1
59
+ end
60
+
61
+ ok "Connected to the monster server as #{name}"
62
+ rescue GRPC::Unavailable => ex
63
+ raise Ledmon::Error, "Server is unavailable: #{ex.message}"
64
+ end
65
+
66
+ def session_grpc_host
67
+ "#{Ledmon::Config.host}:#{Ledmon::Config.grpc_port}"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,35 @@
1
+ module Ledmon::Monster
2
+ module Terminal
3
+ extend ActiveSupport::Concern
4
+ extend Forwardable
5
+
6
+ def prompt
7
+ @prompt ||= TTY::Prompt.new
8
+ end
9
+
10
+ def safe_prompt
11
+ if client?
12
+ prompt
13
+ else
14
+ @safe_prompt ||= Class.new do
15
+ attr_reader :logger
16
+
17
+ def initialize(logger)
18
+ @logger = logger
19
+ end
20
+
21
+ def keypress
22
+ sleep 1
23
+ end
24
+
25
+ def method_missing(method_name, *args, &block)
26
+ logger.warn "Attempted to call terminal prompt method '#{method_name}' in a non-client context. This is not supported."
27
+ end
28
+ end.new(logger)
29
+ end
30
+ end
31
+
32
+ def_delegators :prompt, :say, :ok, :error, :warn
33
+ def_delegators :safe_prompt, :keypress, :ask, :select, :multiselect, :yes?, :no?, :slider
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ledmon
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: world.proto
4
+
5
+ require 'google/protobuf'
6
+
7
+
8
+ descriptor_data = "\n\x0bworld.proto\x12\x06ledmon\"\x07\n\x05\x45mpty\"\'\n\tEquipInfo\x12\x0c\n\x04item\x18\x01 \x01(\t\x12\x0c\n\x04slot\x18\x02 \x01(\t\"\x1b\n\x0bUnequipInfo\x12\x0c\n\x04slot\x18\x01 \x01(\t\"\x1c\n\tPingReply\x12\x0f\n\x07message\x18\x01 \x01(\t\"/\n\x0eSessionRequest\x12\r\n\x05token\x18\x01 \x01(\t\x12\x0e\n\x06\x61vatar\x18\x02 \x01(\t\"C\n\x0cSessionReply\x12%\n\x06status\x18\x01 \x01(\x0e\x32\x15.ledmon.SessionStatus\x12\x0c\n\x04name\x18\x02 \x01(\t\"F\n\nStateReply\x12\x12\n\x05state\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\x04\x64iff\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_stateB\x07\n\x05_diff\" \n\x08Position\x12\t\n\x01x\x18\x01 \x01(\x05\x12\t\n\x01y\x18\x02 \x01(\x05\"\x84\x01\n\x10MovementResponse\x12&\n\x06result\x18\x01 \x01(\x0e\x32\x16.ledmon.MovementResult\x12\'\n\x08position\x18\x02 \x01(\x0b\x32\x10.ledmon.PositionH\x00\x88\x01\x01\x12\x12\n\nsleep_time\x18\x03 \x01(\x02\x42\x0b\n\t_position\"~\n\x12InteractionRequest\x12\x30\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32 .ledmon.InteractionRequestAction\x12\x1f\n\x12\x63hallenge_response\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x15\n\x13_challenge_response\"\xa6\x01\n\x13InteractionResponse\x12\x31\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32!.ledmon.InteractionResponseAction\x12\x19\n\x0c\x63hallenge_id\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x63hallenge_input\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x0f\n\r_challenge_idB\x12\n\x10_challenge_input\"\x89\x01\n\rInventoryData\x12\r\n\x05items\x18\x01 \x03(\t\x12\x37\n\tequipment\x18\x02 \x03(\x0b\x32$.ledmon.InventoryData.EquipmentEntry\x1a\x30\n\x0e\x45quipmentEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1b\n\tCraftData\x12\x0e\n\x06recipe\x18\x01 \x01(\t\"\x18\n\x08ItemInfo\x12\x0c\n\x04item\x18\x01 \x01(\t\"\x1d\n\x0bHealthCount\x12\x0e\n\x06health\x18\x01 \x01(\x02\"J\n\x0e\x41\x63tionResponse\x12$\n\x06result\x18\x01 \x01(\x0e\x32\x14.ledmon.ActionResult\x12\x12\n\nsleep_time\x18\x02 \x01(\x02\"H\n\x0cLookResponse\x12$\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x12.ledmon.LookEntity\x12\x12\n\nsleep_time\x18\x02 \x01(\x02\"O\n\nLookEntity\x12\n\n\x02id\x18\x01 \x01(\t\x12\"\n\x08position\x18\x02 \x01(\x0b\x32\x10.ledmon.Position\x12\x11\n\tequipment\x18\x03 \x03(\t\"G\n\x13StorageTransferData\x12\x0c\n\x04item\x18\x01 \x01(\t\x12\"\n\x04mode\x18\x02 \x01(\x0e\x32\x14.ledmon.TransferMode\"\x1c\n\x0bStorageData\x12\r\n\x05items\x18\x01 \x03(\t\"}\n\x10ResearchProgress\x12\x38\n\x08progress\x18\x01 \x03(\x0b\x32&.ledmon.ResearchProgress.ProgressEntry\x1a/\n\rProgressEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\x94\x01\n\x0eTradeOfferList\x12\x32\n\x06offers\x18\x01 \x03(\x0b\x32\".ledmon.TradeOfferList.OffersEntry\x12\x0b\n\x03own\x18\x02 \x03(\t\x1a\x41\n\x0bOffersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.ledmon.TradeOffer:\x02\x38\x01\"@\n\nTradeOffer\x12\x0e\n\x06inputs\x18\x01 \x03(\t\x12\x0f\n\x07outputs\x18\x02 \x03(\t\x12\x11\n\tremaining\x18\x03 \x01(\x05\"\x1a\n\x0cTradeOfferId\x12\n\n\x02id\x18\x01 \x01(\t\"\"\n\x12\x43onsumableDuration\x12\x0c\n\x04time\x18\x01 \x01(\x02*=\n\rSessionStatus\x12\x0b\n\x07STARTED\x10\x00\x12\x0c\n\x08\x46INISHED\x10\x01\x12\x11\n\rINVALID_TOKEN\x10\x02*%\n\x0eMovementResult\x12\x06\n\x02OK\x10\x00\x12\x0b\n\x07\x42LOCKED\x10\x01*;\n\x18InteractionRequestAction\x12\t\n\x05START\x10\x00\x12\x14\n\x10SUBMIT_CHALLENGE\x10\x01*D\n\x19InteractionResponseAction\x12\x0b\n\x07SUCCESS\x10\x00\x12\x0b\n\x07\x46\x41ILURE\x10\x01\x12\r\n\tCHALLENGE\x10\x02**\n\x0c\x41\x63tionResult\x12\x0e\n\nSUCCESSFUL\x10\x00\x12\n\n\x06\x46\x41ILED\x10\x01*%\n\x0cTransferMode\x12\x08\n\x04TAKE\x10\x00\x12\x0b\n\x07\x44\x45POSIT\x10\x01\x32\xd9\r\n\x05World\x12*\n\x04Ping\x12\r.ledmon.Empty\x1a\x11.ledmon.PingReply\"\x00\x12\x32\n\nPingStream\x12\r.ledmon.Empty\x1a\x11.ledmon.PingReply\"\x00\x30\x01\x12;\n\x07Session\x12\x16.ledmon.SessionRequest\x1a\x14.ledmon.SessionReply\"\x00\x30\x01\x12+\n\tKeepAlive\x12\r.ledmon.Empty\x1a\r.ledmon.Empty\"\x00\x12/\n\x08GetState\x12\r.ledmon.Empty\x1a\x12.ledmon.StateReply\"\x00\x12\x37\n\x0eGetStateStream\x12\r.ledmon.Empty\x1a\x12.ledmon.StateReply\"\x00\x30\x01\x12\x38\n\x0bMoveForward\x12\r.ledmon.Empty\x1a\x18.ledmon.MovementResponse\"\x00\x12\x39\n\x0cMoveBackward\x12\r.ledmon.Empty\x1a\x18.ledmon.MovementResponse\"\x00\x12\x35\n\x08TurnLeft\x12\r.ledmon.Empty\x1a\x18.ledmon.MovementResponse\"\x00\x12\x36\n\tTurnRight\x12\r.ledmon.Empty\x1a\x18.ledmon.MovementResponse\"\x00\x12\x37\n\nTurnAround\x12\r.ledmon.Empty\x1a\x18.ledmon.MovementResponse\"\x00\x12I\n\x08Interact\x12\x1a.ledmon.InteractionRequest\x1a\x1b.ledmon.InteractionResponse\"\x00(\x01\x30\x01\x12\x34\n\x05\x43raft\x12\x11.ledmon.CraftData\x1a\x16.ledmon.ActionResponse\"\x00\x12H\n\x0fStorageTransfer\x12\x1b.ledmon.StorageTransferData\x1a\x16.ledmon.ActionResponse\"\x00\x12\x33\n\x0bStorageList\x12\r.ledmon.Empty\x1a\x13.ledmon.StorageData\"\x00\x12\x36\n\x08Research\x12\x10.ledmon.ItemInfo\x1a\x16.ledmon.ActionResponse\"\x00\x12;\n\rScrapResearch\x12\x10.ledmon.ItemInfo\x1a\x16.ledmon.ActionResponse\"\x00\x12@\n\x13GetResearchProgress\x12\r.ledmon.Empty\x1a\x18.ledmon.ResearchProgress\"\x00\x12:\n\x0fListTradeOffers\x12\r.ledmon.Empty\x1a\x16.ledmon.TradeOfferList\"\x00\x12>\n\x10\x43reateTradeOffer\x12\x12.ledmon.TradeOffer\x1a\x14.ledmon.TradeOfferId\"\x00\x12\x42\n\x10\x41\x63\x63\x65ptTradeOffer\x12\x14.ledmon.TradeOfferId\x1a\x16.ledmon.ActionResponse\"\x00\x12\x39\n\x10\x43\x61ncelTradeOffer\x12\x14.ledmon.TradeOfferId\x1a\r.ledmon.Empty\"\x00\x12\x36\n\x0cGetInventory\x12\r.ledmon.Empty\x1a\x15.ledmon.InventoryData\"\x00\x12\x38\n\tEquipItem\x12\x11.ledmon.EquipInfo\x1a\x16.ledmon.ActionResponse\"\x00\x12<\n\x0bUnequipItem\x12\x13.ledmon.UnequipInfo\x1a\x16.ledmon.ActionResponse\"\x00\x12\x31\n\tGetHealth\x12\r.ledmon.Empty\x1a\x13.ledmon.HealthCount\"\x00\x12\x31\n\x06\x41ttack\x12\r.ledmon.Empty\x1a\x16.ledmon.ActionResponse\"\x00\x12\x39\n\x0b\x43onsumeItem\x12\x10.ledmon.ItemInfo\x1a\x16.ledmon.ActionResponse\"\x00\x12M\n\x1eGetRemainingConsumableDuration\x12\r.ledmon.Empty\x1a\x1a.ledmon.ConsumableDuration\"\x00\x12-\n\x04Look\x12\r.ledmon.Empty\x1a\x14.ledmon.LookResponse\"\x00\x62\x06proto3"
9
+
10
+ pool = Google::Protobuf::DescriptorPool.generated_pool
11
+ pool.add_serialized_file(descriptor_data)
12
+
13
+ module Ledmon
14
+ Empty = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.Empty").msgclass
15
+ EquipInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.EquipInfo").msgclass
16
+ UnequipInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.UnequipInfo").msgclass
17
+ PingReply = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.PingReply").msgclass
18
+ SessionRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.SessionRequest").msgclass
19
+ SessionReply = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.SessionReply").msgclass
20
+ StateReply = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.StateReply").msgclass
21
+ Position = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.Position").msgclass
22
+ MovementResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.MovementResponse").msgclass
23
+ InteractionRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.InteractionRequest").msgclass
24
+ InteractionResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.InteractionResponse").msgclass
25
+ InventoryData = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.InventoryData").msgclass
26
+ CraftData = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.CraftData").msgclass
27
+ ItemInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.ItemInfo").msgclass
28
+ HealthCount = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.HealthCount").msgclass
29
+ ActionResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.ActionResponse").msgclass
30
+ LookResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.LookResponse").msgclass
31
+ LookEntity = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.LookEntity").msgclass
32
+ StorageTransferData = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.StorageTransferData").msgclass
33
+ StorageData = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.StorageData").msgclass
34
+ ResearchProgress = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.ResearchProgress").msgclass
35
+ TradeOfferList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.TradeOfferList").msgclass
36
+ TradeOffer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.TradeOffer").msgclass
37
+ TradeOfferId = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.TradeOfferId").msgclass
38
+ ConsumableDuration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.ConsumableDuration").msgclass
39
+ SessionStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.SessionStatus").enummodule
40
+ MovementResult = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.MovementResult").enummodule
41
+ InteractionRequestAction = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.InteractionRequestAction").enummodule
42
+ InteractionResponseAction = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.InteractionResponseAction").enummodule
43
+ ActionResult = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.ActionResult").enummodule
44
+ TransferMode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ledmon.TransferMode").enummodule
45
+ end
@@ -0,0 +1,51 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: world.proto for package 'ledmon'
3
+
4
+ require 'grpc'
5
+ require 'world_pb'
6
+
7
+ module Ledmon
8
+ module World
9
+ class Service
10
+
11
+ include ::GRPC::GenericService
12
+
13
+ self.marshal_class_method = :encode
14
+ self.unmarshal_class_method = :decode
15
+ self.service_name = 'ledmon.World'
16
+
17
+ rpc :Ping, ::Ledmon::Empty, ::Ledmon::PingReply
18
+ rpc :PingStream, ::Ledmon::Empty, stream(::Ledmon::PingReply)
19
+ rpc :Session, ::Ledmon::SessionRequest, stream(::Ledmon::SessionReply)
20
+ rpc :KeepAlive, ::Ledmon::Empty, ::Ledmon::Empty
21
+ rpc :GetState, ::Ledmon::Empty, ::Ledmon::StateReply
22
+ rpc :GetStateStream, ::Ledmon::Empty, stream(::Ledmon::StateReply)
23
+ rpc :MoveForward, ::Ledmon::Empty, ::Ledmon::MovementResponse
24
+ rpc :MoveBackward, ::Ledmon::Empty, ::Ledmon::MovementResponse
25
+ rpc :TurnLeft, ::Ledmon::Empty, ::Ledmon::MovementResponse
26
+ rpc :TurnRight, ::Ledmon::Empty, ::Ledmon::MovementResponse
27
+ rpc :TurnAround, ::Ledmon::Empty, ::Ledmon::MovementResponse
28
+ rpc :Interact, stream(::Ledmon::InteractionRequest), stream(::Ledmon::InteractionResponse)
29
+ rpc :Craft, ::Ledmon::CraftData, ::Ledmon::ActionResponse
30
+ rpc :StorageTransfer, ::Ledmon::StorageTransferData, ::Ledmon::ActionResponse
31
+ rpc :StorageList, ::Ledmon::Empty, ::Ledmon::StorageData
32
+ rpc :Research, ::Ledmon::ItemInfo, ::Ledmon::ActionResponse
33
+ rpc :ScrapResearch, ::Ledmon::ItemInfo, ::Ledmon::ActionResponse
34
+ rpc :GetResearchProgress, ::Ledmon::Empty, ::Ledmon::ResearchProgress
35
+ rpc :ListTradeOffers, ::Ledmon::Empty, ::Ledmon::TradeOfferList
36
+ rpc :CreateTradeOffer, ::Ledmon::TradeOffer, ::Ledmon::TradeOfferId
37
+ rpc :AcceptTradeOffer, ::Ledmon::TradeOfferId, ::Ledmon::ActionResponse
38
+ rpc :CancelTradeOffer, ::Ledmon::TradeOfferId, ::Ledmon::Empty
39
+ rpc :GetInventory, ::Ledmon::Empty, ::Ledmon::InventoryData
40
+ rpc :EquipItem, ::Ledmon::EquipInfo, ::Ledmon::ActionResponse
41
+ rpc :UnequipItem, ::Ledmon::UnequipInfo, ::Ledmon::ActionResponse
42
+ rpc :GetHealth, ::Ledmon::Empty, ::Ledmon::HealthCount
43
+ rpc :Attack, ::Ledmon::Empty, ::Ledmon::ActionResponse
44
+ rpc :ConsumeItem, ::Ledmon::ItemInfo, ::Ledmon::ActionResponse
45
+ rpc :GetRemainingConsumableDuration, ::Ledmon::Empty, ::Ledmon::ConsumableDuration
46
+ rpc :Look, ::Ledmon::Empty, ::Ledmon::LookResponse
47
+ end
48
+
49
+ Stub = Service.rpc_stub_class
50
+ end
51
+ end
data/lib/ledmon.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require 'http'
5
+ require 'active_support/concern'
6
+ require 'active_support/delegation'
7
+ require 'tty-config'
8
+ require 'tty-reader'
9
+ require 'tty-prompt'
10
+ require 'logger'
11
+
12
+
13
+ begin
14
+ require 'pry'
15
+ rescue LoadError
16
+ nil
17
+ end
18
+
19
+ this_dir = File.expand_path(File.dirname(__FILE__))
20
+
21
+ require 'zeitwerk'
22
+ loader = Zeitwerk::Loader.for_gem
23
+ loader.ignore(File.join(this_dir, '**/*_pb.rb'))
24
+ loader.inflector.inflect(
25
+ 'cli' => 'CLI',
26
+ )
27
+ loader.setup
28
+ loader.eager_load_namespace(Ledmon::CLI)
29
+
30
+ lib_dir = File.join(this_dir, 'ledmon')
31
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
32
+
33
+ require 'ledmon/world_pb'
34
+ require 'ledmon/world_services_pb'
35
+
36
+ module Ledmon
37
+ Config = Configurator.new
38
+
39
+ class Error < StandardError; end
40
+
41
+ # Your code goes here...
42
+ end
data/monster.rb.sample ADDED
@@ -0,0 +1,60 @@
1
+ def name
2
+ 'ahmed'
3
+ end
4
+
5
+ def avatar
6
+ "@@@@@
7
+ @)))@
8
+ @)?)@
9
+ @)?)@
10
+ @)<)@"
11
+ end
12
+
13
+ def brain
14
+ loop do
15
+ key = keypress
16
+
17
+ case key
18
+ when 'w' then move_forward
19
+ when 's' then move_backward
20
+ when 'a' then turn_left
21
+ when 'd' then turn_right
22
+ when 'e' then say interact.inspect
23
+ when 'c' then
24
+ recipe = ask("recipe: ")
25
+ craft(recipe)
26
+ when 'r' then
27
+ item = ask("research item: ")
28
+ research(item)
29
+ when 'o' then
30
+ item = ask("item: ")
31
+ slot = ask("slot: ")
32
+ equip_item(item, slot)
33
+ when 'p' then
34
+ slot = ask("slot: ")
35
+ unequip_item(slot)
36
+ when 'i' then
37
+ inventory = get_inventory
38
+ say "items: #{inventory.items.inspect}"
39
+ say "equipment: #{inventory.equipment.inspect}"
40
+ when 'u' then
41
+ say "health: #{get_health}"
42
+ when 'j' then
43
+ attack
44
+ when 'l' then
45
+ entities = look
46
+ say "look: #{entities.inspect}"
47
+ else
48
+ nil
49
+ end
50
+ end
51
+ end
52
+
53
+ def algo(id, input)
54
+ case id
55
+ when 'abc'
56
+ input.chars.map(&:to_i).sum
57
+ else
58
+ nil
59
+ end
60
+ end
@@ -0,0 +1,185 @@
1
+ syntax = "proto3";
2
+
3
+ package ledmon;
4
+
5
+ service World {
6
+ rpc Ping (Empty) returns (PingReply) {}
7
+ rpc PingStream (Empty) returns (stream PingReply) {}
8
+
9
+ rpc Session (SessionRequest) returns (stream SessionReply) {}
10
+ rpc KeepAlive (Empty) returns (Empty) {}
11
+
12
+ rpc GetState (Empty) returns (StateReply) {}
13
+ rpc GetStateStream (Empty) returns (stream StateReply) {}
14
+
15
+ rpc MoveForward (Empty) returns (MovementResponse) {}
16
+ rpc MoveBackward (Empty) returns (MovementResponse) {}
17
+ rpc TurnLeft (Empty) returns (MovementResponse) {}
18
+ rpc TurnRight (Empty) returns (MovementResponse) {}
19
+ rpc TurnAround (Empty) returns (MovementResponse) {}
20
+
21
+ rpc Interact (stream InteractionRequest) returns (stream InteractionResponse) {}
22
+ rpc Craft (CraftData) returns (ActionResponse) {}
23
+ rpc StorageTransfer (StorageTransferData) returns (ActionResponse) {}
24
+ rpc StorageList (Empty) returns (StorageData) {}
25
+ rpc Research (ItemInfo) returns (ActionResponse) {}
26
+ rpc ScrapResearch (ItemInfo) returns (ActionResponse) {}
27
+ rpc GetResearchProgress (Empty) returns (ResearchProgress) {}
28
+ rpc ListTradeOffers (Empty) returns (TradeOfferList) {}
29
+ rpc CreateTradeOffer (TradeOffer) returns (TradeOfferId) {}
30
+ rpc AcceptTradeOffer (TradeOfferId) returns (ActionResponse) {}
31
+ rpc CancelTradeOffer (TradeOfferId) returns (Empty) {}
32
+
33
+ rpc GetInventory (Empty) returns (InventoryData) {}
34
+ rpc EquipItem (EquipInfo) returns (ActionResponse) {}
35
+ rpc UnequipItem (UnequipInfo) returns (ActionResponse) {}
36
+
37
+ rpc GetHealth (Empty) returns (HealthCount) {}
38
+ rpc Attack (Empty) returns (ActionResponse) {}
39
+ rpc ConsumeItem (ItemInfo) returns (ActionResponse) {}
40
+ rpc GetRemainingConsumableDuration (Empty) returns (ConsumableDuration) {}
41
+
42
+ rpc Look (Empty) returns (LookResponse) {}
43
+ }
44
+
45
+ message Empty {
46
+
47
+ }
48
+
49
+ message EquipInfo{
50
+ string item = 1;
51
+ string slot = 2;
52
+ }
53
+ message UnequipInfo{
54
+ string slot = 1;
55
+ }
56
+
57
+ message PingReply {
58
+ string message = 1;
59
+ }
60
+
61
+ message SessionRequest {
62
+ string token = 1;
63
+ string avatar = 2;
64
+ }
65
+
66
+ message SessionReply {
67
+ SessionStatus status = 1;
68
+ string name = 2;
69
+ }
70
+
71
+ enum SessionStatus {
72
+ STARTED = 0;
73
+ FINISHED = 1;
74
+ INVALID_TOKEN = 2;
75
+ }
76
+
77
+ message StateReply {
78
+ optional string state = 1;
79
+ optional string diff = 2;
80
+ }
81
+
82
+ enum MovementResult {
83
+ OK = 0;
84
+ BLOCKED = 1;
85
+ }
86
+
87
+ message Position {
88
+ int32 x = 1;
89
+ int32 y = 2;
90
+ }
91
+
92
+ message MovementResponse {
93
+ MovementResult result = 1;
94
+ optional Position position = 2;
95
+ float sleep_time = 3;
96
+ }
97
+
98
+ enum InteractionRequestAction {
99
+ START = 0;
100
+ SUBMIT_CHALLENGE = 1;
101
+ }
102
+
103
+ enum InteractionResponseAction {
104
+ SUCCESS = 0;
105
+ FAILURE = 1;
106
+ CHALLENGE = 2;
107
+ }
108
+
109
+ message InteractionRequest {
110
+ InteractionRequestAction action = 1;
111
+ optional string challenge_response = 2;
112
+ }
113
+
114
+ message InteractionResponse {
115
+ InteractionResponseAction action = 1;
116
+
117
+ optional string challenge_id = 2;
118
+ optional string challenge_input = 3;
119
+ }
120
+
121
+ message InventoryData{
122
+ repeated string items = 1;
123
+ map<string, string> equipment = 2;
124
+ }
125
+
126
+ message CraftData{
127
+ string recipe = 1;
128
+ }
129
+
130
+ message ItemInfo{
131
+ string item = 1;
132
+ }
133
+
134
+ message HealthCount{
135
+ float health = 1;
136
+ }
137
+
138
+ enum ActionResult {
139
+ SUCCESSFUL = 0;
140
+ FAILED = 1;
141
+ }
142
+
143
+ message ActionResponse {
144
+ ActionResult result = 1;
145
+ float sleep_time = 2;
146
+ }
147
+
148
+ message LookResponse{
149
+ repeated LookEntity entities = 1;
150
+ float sleep_time = 2;
151
+ }
152
+ message LookEntity{
153
+ string id = 1;
154
+ Position position = 2;
155
+ repeated string equipment = 3;
156
+ }
157
+ enum TransferMode{
158
+ TAKE = 0;
159
+ DEPOSIT = 1;
160
+ }
161
+ message StorageTransferData{
162
+ string item = 1;
163
+ TransferMode mode = 2;
164
+ }
165
+ message StorageData{
166
+ repeated string items = 1;
167
+ }
168
+ message ResearchProgress{
169
+ map<string, int32> progress = 1;
170
+ }
171
+ message TradeOfferList{
172
+ map<string, TradeOffer> offers = 1;
173
+ repeated string own = 2;
174
+ }
175
+ message TradeOffer{
176
+ repeated string inputs = 1;
177
+ repeated string outputs = 2;
178
+ int32 remaining = 3;
179
+ }
180
+ message TradeOfferId{
181
+ string id = 1;
182
+ }
183
+ message ConsumableDuration{
184
+ float time = 1;
185
+ }
data/sig/ledmon.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Ledmon
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,230 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ledmon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ahmed Al Hafoudh
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: zeitwerk
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.7'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.7'
26
+ - !ruby/object:Gem::Dependency
27
+ name: pry
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.15.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.15.2
40
+ - !ruby/object:Gem::Dependency
41
+ name: grpc
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.74'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.74'
54
+ - !ruby/object:Gem::Dependency
55
+ name: thor
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.3'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.3'
68
+ - !ruby/object:Gem::Dependency
69
+ name: logger
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.7'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.7'
82
+ - !ruby/object:Gem::Dependency
83
+ name: activesupport
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '8.0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '8.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rack
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 2.2.3
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 2.2.3
110
+ - !ruby/object:Gem::Dependency
111
+ name: http
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '5.3'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '5.3'
124
+ - !ruby/object:Gem::Dependency
125
+ name: tty-config
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.6.0
131
+ type: :runtime
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.6.0
138
+ - !ruby/object:Gem::Dependency
139
+ name: tty-prompt
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 0.23.1
145
+ type: :runtime
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: 0.23.1
152
+ - !ruby/object:Gem::Dependency
153
+ name: grpc-tools
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '1.71'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '1.71'
166
+ description: Ledmon is a Ruby gem that provides tools for managing and deploying monsters
167
+ in the Ledmon ecosystem. It includes features for session management, deployment,
168
+ and interaction with Ledmon's monster server.
169
+ email:
170
+ - alhafoudh@freevision.sk
171
+ executables:
172
+ - ledmon
173
+ extensions: []
174
+ extra_rdoc_files: []
175
+ files:
176
+ - ".rspec"
177
+ - ".ruby-version"
178
+ - LICENSE.txt
179
+ - Makefile
180
+ - README.md
181
+ - Rakefile
182
+ - exe/ledmon
183
+ - lib/ledmon.rb
184
+ - lib/ledmon/cli.rb
185
+ - lib/ledmon/cli/base.rb
186
+ - lib/ledmon/cli/config.rb
187
+ - lib/ledmon/cli/main.rb
188
+ - lib/ledmon/cli/monster.rb
189
+ - lib/ledmon/configurator.rb
190
+ - lib/ledmon/interceptors/sleep_interceptor.rb
191
+ - lib/ledmon/monster/deployer.rb
192
+ - lib/ledmon/monster/executor.rb
193
+ - lib/ledmon/monster/interaction.rb
194
+ - lib/ledmon/monster/movement.rb
195
+ - lib/ledmon/monster/packer.rb
196
+ - lib/ledmon/monster/runner.rb
197
+ - lib/ledmon/monster/session.rb
198
+ - lib/ledmon/monster/terminal.rb
199
+ - lib/ledmon/version.rb
200
+ - lib/ledmon/world_pb.rb
201
+ - lib/ledmon/world_services_pb.rb
202
+ - monster.rb.sample
203
+ - protos/world.proto
204
+ - sig/ledmon.rbs
205
+ homepage: https://www.lstme.sk
206
+ licenses:
207
+ - MIT
208
+ metadata:
209
+ allowed_push_host: https://rubygems.org
210
+ homepage_uri: https://www.lstme.sk
211
+ source_code_uri: https://gitlab.com/lstme/ledmon
212
+ changelog_uri: https://gitlab.com/lstme/ledmon
213
+ rdoc_options: []
214
+ require_paths:
215
+ - lib
216
+ required_ruby_version: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: 3.1.0
221
+ required_rubygems_version: !ruby/object:Gem::Requirement
222
+ requirements:
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ version: '0'
226
+ requirements: []
227
+ rubygems_version: 3.6.9
228
+ specification_version: 4
229
+ summary: ledmon - A Ruby gem for managing and deploying Ledmon monsters.
230
+ test_files: []