procon_bypass_man 0.1.21 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -0
  3. data/.github/workflows/gitleacks.yml +11 -0
  4. data/.gitignore +1 -0
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile.lock +4 -4
  7. data/README.md +4 -1
  8. data/docs/getting_started.md +70 -5
  9. data/docs/setting/left-analogstick-cap.md +1 -1
  10. data/docs/setting/splatoon2_macro_dasei_cancel.md +4 -0
  11. data/docs/setting/splatoon2_macro_sokuwari_bubble.md +4 -0
  12. data/docs/setting/splatoon2_shake_tansan.md +47 -0
  13. data/docs/setup_raspi.md +0 -1
  14. data/lib/procon_bypass_man/background/jobs/post_completed_remote_macro_job.rb +17 -0
  15. data/lib/procon_bypass_man/background.rb +1 -0
  16. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +142 -80
  17. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +3 -1
  18. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button.rb +28 -0
  19. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button_list.rb +31 -0
  20. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/disable_macro_if_pressed.rb +28 -0
  21. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/flip_if_pressed.rb +31 -0
  22. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/force_neutral.rb +28 -0
  23. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed.rb +26 -0
  24. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed_allows_nil.rb +28 -0
  25. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/open_macro_steps.rb +26 -0
  26. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer.rb +17 -0
  27. data/lib/procon_bypass_man/buttons_setting_configuration.rb +5 -4
  28. data/lib/procon_bypass_man/{commands → bypass}/bypass_command.rb +36 -24
  29. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +4 -0
  30. data/lib/procon_bypass_man/bypass.rb +43 -23
  31. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +2 -3
  32. data/lib/procon_bypass_man/commands/send_error_command.rb +2 -2
  33. data/lib/procon_bypass_man/commands.rb +0 -3
  34. data/lib/procon_bypass_man/configuration.rb +29 -3
  35. data/lib/procon_bypass_man/device_connection/command.rb +28 -0
  36. data/lib/procon_bypass_man/device_connection/executor.rb +190 -0
  37. data/lib/procon_bypass_man/device_connection/output_report_generator.rb +42 -0
  38. data/lib/procon_bypass_man/device_connection/output_report_markerable.rb +28 -0
  39. data/lib/procon_bypass_man/device_connection/output_report_sub_command_table.rb +133 -0
  40. data/lib/procon_bypass_man/device_connection/output_report_watcher.rb +41 -0
  41. data/lib/procon_bypass_man/device_connection/pre_bypass.rb +67 -0
  42. data/lib/procon_bypass_man/device_connection/procon_setting_overrider.rb +78 -0
  43. data/lib/procon_bypass_man/device_connection/spoofing_output_report_watcher.rb +39 -0
  44. data/lib/procon_bypass_man/device_connection.rb +16 -0
  45. data/lib/procon_bypass_man/device_model.rb +17 -0
  46. data/lib/procon_bypass_man/io_monitor.rb +20 -1
  47. data/lib/procon_bypass_man/plugin/splatoon2/macro/charge_tansan_bomb.rb +21 -0
  48. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +1 -1
  49. data/lib/procon_bypass_man/plugins.rb +1 -0
  50. data/lib/procon_bypass_man/procon/analog_stick_cap.rb +4 -23
  51. data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +36 -0
  52. data/lib/procon_bypass_man/procon/layer_changer.rb +4 -1
  53. data/lib/procon_bypass_man/procon/macro.rb +5 -2
  54. data/lib/procon_bypass_man/procon/macro_builder.rb +20 -20
  55. data/lib/procon_bypass_man/procon/macro_plugin_map.rb +23 -0
  56. data/lib/procon_bypass_man/procon/macro_registry.rb +21 -10
  57. data/lib/procon_bypass_man/procon/suppress_rumble.rb +13 -0
  58. data/lib/procon_bypass_man/procon/user_operation.rb +29 -15
  59. data/lib/procon_bypass_man/procon/value_objects/analog_stick_position.rb +18 -0
  60. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/base.rb +0 -0
  61. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_immutable_binary.rb +0 -0
  62. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_mutable_binary.rb +0 -0
  63. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/inbound_procon_binary.rb +5 -0
  64. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/processing_procon_binary.rb +6 -1
  65. data/lib/procon_bypass_man/procon/value_objects/binary.rb +11 -0
  66. data/lib/procon_bypass_man/{domains → procon/value_objects}/bypass_mode.rb +0 -0
  67. data/lib/procon_bypass_man/procon/value_objects/rumble_binary.rb +18 -0
  68. data/lib/procon_bypass_man/procon.rb +27 -5
  69. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +62 -0
  70. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +30 -0
  71. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +37 -0
  72. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +8 -0
  73. data/lib/procon_bypass_man/remote_macro/task.rb +6 -0
  74. data/lib/procon_bypass_man/remote_macro/task_queue.rb +13 -0
  75. data/lib/procon_bypass_man/remote_macro.rb +14 -0
  76. data/lib/procon_bypass_man/{commands → remote_pbm_action/commands}/run_remote_pbm_action_dispatch_command.rb +0 -0
  77. data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +7 -1
  78. data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +1 -1
  79. data/lib/procon_bypass_man/remote_pbm_action.rb +2 -0
  80. data/lib/procon_bypass_man/runner.rb +13 -13
  81. data/lib/procon_bypass_man/support/cycle_sleep.rb +22 -0
  82. data/lib/procon_bypass_man/support/device_mouse_finder.rb +60 -0
  83. data/lib/procon_bypass_man/{device_procon_finder.rb → support/device_procon_finder.rb} +0 -2
  84. data/lib/procon_bypass_man/support/never_exit_accidentally.rb +3 -3
  85. data/lib/procon_bypass_man/support/remote_macro_http_client.rb +9 -0
  86. data/lib/procon_bypass_man/support/safe_timeout.rb +7 -1
  87. data/lib/procon_bypass_man/{usb_device_controller.rb → support/usb_device_controller.rb} +9 -6
  88. data/lib/procon_bypass_man/support/yaml_loader.rb +12 -0
  89. data/lib/procon_bypass_man/version.rb +1 -1
  90. data/lib/procon_bypass_man/websocket/{pbm_job_client.rb → client.rb} +32 -10
  91. data/lib/procon_bypass_man.rb +69 -46
  92. data/procon_bypass_man.gemspec +1 -1
  93. data/project_template/app.rb +19 -4
  94. data/sig/main.rbs +4 -16
  95. metadata +55 -17
  96. data/lib/procon_bypass_man/commands/connect_device_command.rb +0 -18
  97. data/lib/procon_bypass_man/device_connector.rb +0 -296
  98. data/lib/procon_bypass_man/domains.rb +0 -12
@@ -1,4 +1,15 @@
1
1
  module ProconBypassMan
2
+ class NullCounter
3
+ def initialize(label: )
4
+ end
5
+
6
+ def record(_)
7
+ end
8
+
9
+ def shutdown
10
+ end
11
+ end
12
+
2
13
  class Counter
3
14
  attr_accessor :label, :table, :previous_table, :active
4
15
 
@@ -40,7 +51,11 @@ module ProconBypassMan
40
51
  end
41
52
 
42
53
  module IOMonitor
54
+ @@thread = nil
55
+
43
56
  def self.new(label: )
57
+ return NullCounter.new(label: label) if not started?
58
+
44
59
  counter = Counter.new(label: label)
45
60
  @@list << counter
46
61
  counter
@@ -51,9 +66,13 @@ module ProconBypassMan
51
66
  @@list
52
67
  end
53
68
 
69
+ def self.started?
70
+ !!@@thread
71
+ end
72
+
54
73
  # ここで集計する
55
74
  def self.start!
56
- Thread.start do
75
+ @@thread = Thread.start do
57
76
  max_output_length = 0
58
77
  loop do
59
78
  list = @@list.select(&:active).dup
@@ -0,0 +1,21 @@
1
+ module ProconBypassMan
2
+ module Plugin
3
+ module Splatoon2
4
+ module Macro
5
+ module ChargeTansanBomb
6
+ def self.display_name
7
+ :charge_tansan_bomb
8
+ end
9
+
10
+ def self.steps
11
+ [:shake_left_stick_and_toggle_b_for_0_1sec].freeze
12
+ end
13
+
14
+ def self.description
15
+ 'タンサンボムのチャージ'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,7 +3,7 @@
3
3
  module ProconBypassMan
4
4
  module Plugin
5
5
  module Splatoon2
6
- VERSION = "0.1.3"
6
+ VERSION = "0.1.5"
7
7
  end
8
8
  end
9
9
  end
@@ -5,6 +5,7 @@ require_relative "plugin/splatoon2/macro/jump_to_up_key"
5
5
  require_relative "plugin/splatoon2/macro/jump_to_left_key"
6
6
  require_relative "plugin/splatoon2/macro/sokuwari_for_splash_bomb"
7
7
  require_relative "plugin/splatoon2/macro/dasei_cancel"
8
+ require_relative "plugin/splatoon2/macro/charge_tansan_bomb"
8
9
  require_relative "plugin/splatoon2/mode/guruguru"
9
10
 
10
11
  module ProconBypassMan
@@ -1,36 +1,17 @@
1
1
  class ProconBypassMan::Procon::AnalogStickCap
2
- class Position
3
- attr_accessor :x, :y
4
-
5
- def initialize(x:, y:)
6
- @x = x.to_i
7
- @y = y.to_i
8
- end
9
-
10
- def to_binary
11
- analog_stick_data = [
12
- (@x & "0xff".to_i(16)),
13
- ((@y << 4) & "0xf0".to_i(16)) | ((@x >> 8) & "0x0f".to_i(16)),
14
- (@y >> 4) & "0xff".to_i(16),
15
- ]
16
- hex = analog_stick_data.map{ |x| x.to_s(16).rjust(2, "0") }.join
17
- [hex].pack("H*")
18
- end
19
- end
20
-
21
2
  def initialize(binary)
22
3
  @binary = binary
23
4
  @analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
24
5
  end
25
6
 
26
- # @return [ProconBypassMan::Procon::AnalogStickCap::Position]
7
+ # @return [ProconBypassMan::AnalogStickPosition]
27
8
  def capped_position(cap_hypotenuse: )
28
9
  if hypotenuse > cap_hypotenuse
29
10
  relative_capped_x = cap_hypotenuse * Math.cos(rad * Math::PI / 180).abs
30
11
  relative_capped_y = cap_hypotenuse * Math.sin(rad * Math::PI / 180).abs
31
12
  relative_capped_x = -(relative_capped_x.abs) if relative_x.negative?
32
13
  relative_capped_y = -(relative_capped_y.abs) if relative_y.negative?
33
- return Position.new(
14
+ return ProconBypassMan::AnalogStickPosition.new(
34
15
  x: relative_capped_x + @analog_stick.neutral_position.x,
35
16
  y: relative_capped_y + @analog_stick.neutral_position.y,
36
17
  )
@@ -39,9 +20,9 @@ class ProconBypassMan::Procon::AnalogStickCap
39
20
  end
40
21
  end
41
22
 
42
- # @return [ProconBypassMan::Procon::AnalogStickCap::Position]
23
+ # @return [ProconBypassMan::AnalogStickPosition]
43
24
  def position
44
- Position.new(x: abs_x, y: abs_y)
25
+ ProconBypassMan::AnalogStickPosition.new(x: abs_x, y: abs_y)
45
26
  end
46
27
 
47
28
  def abs_x; @analog_stick.abs_x; end # 0, 0からのx
@@ -0,0 +1,36 @@
1
+ class ProconBypassMan::Procon::AnalogStickManipulator
2
+ attr_accessor :manipulated_abs_x, :manipulated_abs_y
3
+
4
+ def initialize(binary, method: )
5
+ analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
6
+
7
+ if method =~ /tilt_left_stick_(completely)_to_(left|right)/
8
+ power_level = $1
9
+ direction = $2
10
+
11
+ case direction
12
+ when 'left'
13
+ self.manipulated_abs_x = 400
14
+ # yを引き継ぐとタンサンボムの溜まりが悪くなったので固定値を入れる
15
+ self.manipulated_abs_y = analog_stick.abs_y
16
+ # self.manipulated_abs_y = 1808
17
+ when 'right'
18
+ self.manipulated_abs_x = 3400
19
+ self.manipulated_abs_y = 1808
20
+ end
21
+ else
22
+ warn "error stick manipulator"
23
+ self.manipulated_abs_x = analog_stick.abs_x
24
+ self.manipulated_abs_y = analog_stick.abs_y
25
+ end
26
+ end
27
+
28
+
29
+ # @return [String]
30
+ def to_binary
31
+ ProconBypassMan::AnalogStickPosition.new(
32
+ x: self.manipulated_abs_x,
33
+ y: self.manipulated_abs_y,
34
+ ).to_binary
35
+ end
36
+ end
@@ -24,7 +24,10 @@ class ProconBypassMan::Procon::LayerChanger
24
24
  # @return [Boolean]
25
25
  def change_layer?
26
26
  if ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.empty?
27
- raise "prefix_keysが未設定です"
27
+ ProconBypassMan.cache.fetch key: 'unknown prefix_keys', expires_in: 60 do
28
+ warn "prefix_keysが未設定です"
29
+ end
30
+ return false
28
31
  end
29
32
  ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.map { |b| pressed?(button: b) }.all?
30
33
  end
@@ -74,11 +74,13 @@ class ProconBypassMan::Procon::Macro
74
74
  end
75
75
  end
76
76
 
77
- attr_accessor :name, :steps
77
+ attr_accessor :name, :steps, :after_callback_block, :force_neutral_buttons
78
78
 
79
- def initialize(name: , steps: )
79
+ def initialize(name: , steps: , force_neutral_buttons: [], &after_callback_block)
80
80
  self.name = name
81
81
  self.steps = steps
82
+ self.after_callback_block = after_callback_block
83
+ self.force_neutral_buttons = force_neutral_buttons # 外部から呼ばれるだけ
82
84
  end
83
85
 
84
86
  def next_step
@@ -97,6 +99,7 @@ class ProconBypassMan::Procon::Macro
97
99
 
98
100
  if nested_step.over?
99
101
  steps.shift # NestedStepを破棄する
102
+ self.after_callback_block.call if self.after_callback_block
100
103
  return next_step
101
104
  else
102
105
  return nested_step.next_step
@@ -5,42 +5,42 @@ class ProconBypassMan::Procon::MacroBuilder
5
5
  return subjects.first.to_steps
6
6
  end
7
7
 
8
- base = subjects.first
9
- remain = subjects[1..-1]
10
- remain.map { |x| base.to_steps.zip(x.to_steps) }.first
8
+ subjects.inject([[], []]) do |acc, item|
9
+ acc[0] << item.to_steps[0]
10
+ acc[1] << item.to_steps[1]
11
+ acc
12
+ end
11
13
  end
12
14
  end
13
15
 
14
16
  class Subject
15
17
  def initialize(value)
16
- @button =
17
- if match = value.match(/_(\w+)\z/)
18
- match[1]
19
- else
20
- :unknown
21
- end
18
+ if not /^shake_/ =~ value
19
+ @button =
20
+ if match = value.match(/_(\w+)\z/)
21
+ match[1]
22
+ else
23
+ :unknown
24
+ end
25
+ end
22
26
  @type =
23
27
  if value.start_with?("toggle_")
24
28
  :toggle
29
+ elsif value.start_with?("shake_left_stick")
30
+ :shake_left_stick
25
31
  else
26
32
  :pressing
27
33
  end
28
34
  end
29
35
 
30
- def toggle?
31
- @type == :toggle
32
- end
33
-
34
- def pressing?
35
- not toggle?
36
- end
37
-
38
36
  def to_steps
39
37
  case @type
40
38
  when :toggle
41
39
  [@button.to_sym, :none]
42
40
  when :pressing
43
41
  [@button.to_sym, @button.to_sym]
42
+ when :shake_left_stick
43
+ [:tilt_left_stick_completely_to_left, :tilt_left_stick_completely_to_right]
44
44
  end
45
45
  end
46
46
  end
@@ -92,7 +92,7 @@ class ProconBypassMan::Procon::MacroBuilder
92
92
  ]
93
93
  end
94
94
 
95
- if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
95
+ if %r!^(pressing_|toggle_|shake_left_stick_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|shake_left_stick|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
96
96
  if sec = match[1]
97
97
  return {
98
98
  continue_for: to_f(sec),
@@ -100,14 +100,14 @@ class ProconBypassMan::Procon::MacroBuilder
100
100
  if x.is_a?(Array)
101
101
  x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
102
102
  else
103
- is_button(x) || RESERVED_WORD_NONE == x
103
+ is_button(x) || RESERVED_WORD_NONE == x || :tilt_left_stick_completely_to_left == x || :tilt_left_stick_completely_to_right == x
104
104
  end
105
105
  },
106
106
  }
107
107
  end
108
108
  end
109
109
 
110
- if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!))
110
+ if %r!^(pressing_|toggle_|shake_left_stick_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|shake_left_stick|toggle_[^_]+!))
111
111
  return SubjectMerger.merge(subjects.map { |x| Subject.new(x) }).select { |x|
112
112
  if x.is_a?(Array)
113
113
  x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
@@ -0,0 +1,23 @@
1
+ module ProconBypassMan
2
+ class Procon
3
+ # macroキーにメタデータを埋め込んでいる. 通常の処理ではメタデータを露出したくないので露出しないためのクラス
4
+ class MacroPluginMap < ::Hash
5
+ def [](value)
6
+ self.fetch([value, :normal], nil)
7
+ end
8
+
9
+ def each
10
+ transform_keys(&:first).each { |x| yield(x[0], x[1]) }
11
+ end
12
+
13
+ alias_method :original_keys, :keys
14
+ def keys
15
+ super.map(&:first)
16
+ end
17
+
18
+ def raw_keys
19
+ self.original_keys
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,20 +3,23 @@ class ProconBypassMan::Procon::MacroRegistry
3
3
  null: [],
4
4
  }
5
5
 
6
- def self.install_plugin(klass, steps: nil)
7
- if plugins[klass.to_s.to_sym]
8
- raise "#{klass} macro is already registered"
6
+ def self.install_plugin(klass, steps: nil, macro_type: :normal)
7
+ if plugins.fetch([klass.to_s.to_sym, macro_type], nil)
8
+ Kernel.warn "#{klass} macro is already registered"
9
+ return
9
10
  end
10
11
 
11
- plugins[klass.to_s.to_sym] = ->{
12
- ProconBypassMan::Procon::MacroBuilder.new(steps || klass.steps).build
13
- }
12
+ plugins.store(
13
+ [klass.to_s.to_sym, macro_type], ->{
14
+ ProconBypassMan::Procon::MacroBuilder.new(steps || klass.steps).build
15
+ }
16
+ )
14
17
  end
15
18
 
16
19
  # @return [ProconBypassMan::Procon::Macro]
17
- def self.load(name)
18
- if(steps = PRESETS[name] || plugins[name]&.call)
19
- return ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup)
20
+ def self.load(name, macro_type: :normal, force_neutral_buttons: [], &after_callback_block)
21
+ if(steps = PRESETS[name] || plugins.fetch([name.to_s.to_sym, macro_type], nil)&.call)
22
+ return ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup, force_neutral_buttons: force_neutral_buttons, &after_callback_block)
20
23
  else
21
24
  warn "installされていないマクロ(#{name})を使うことはできません"
22
25
  return self.load(:null)
@@ -24,12 +27,20 @@ class ProconBypassMan::Procon::MacroRegistry
24
27
  end
25
28
 
26
29
  def self.reset!
27
- ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = {}
30
+ ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = ProconBypassMan::Procon::MacroPluginMap.new
28
31
  end
29
32
 
30
33
  def self.plugins
31
34
  ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins
32
35
  end
33
36
 
37
+ def self.cleanup_remote_macros!
38
+ remote_keys = ProconBypassMan::Procon::MacroRegistry.plugins.original_keys.select { |_, y| y == :remote }
39
+ remote_keys.each do |remote_key|
40
+ ProconBypassMan::Procon::MacroRegistry.plugins.delete(remote_key)
41
+ end
42
+ ProconBypassMan::Procon::MacroRegistry.plugins
43
+ end
44
+
34
45
  reset!
35
46
  end
@@ -0,0 +1,13 @@
1
+ class ProconBypassMan::SuppressRumble
2
+ # @param [String] binary
3
+ def initialize(binary: )
4
+ @binary = binary
5
+ end
6
+
7
+ # @return [String]
8
+ def execute
9
+ new_raw = ["100c0001404000014040"].pack("H*")
10
+ new_raw[1] = @binary[1]
11
+ new_raw
12
+ end
13
+ end
@@ -33,22 +33,22 @@ class ProconBypassMan::Procon::UserOperation
33
33
  binary.write_as_press_button(button)
34
34
  end
35
35
 
36
- # @param [Symbol, Array<Symbol>] button
37
- def press_button_only(button)
38
- if button.is_a?(Array)
39
- binary.set_no_action!
40
- button.uniq.each do |b|
41
- unless ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == b
42
- binary.write_as_press_button(b)
43
- end
44
- end
45
- return
46
- end
36
+ # @param [Symbol, Array<Symbol>] macro_step
37
+ def press_button_only_or_tilt_sticks(macro_step)
38
+ macro_step = [macro_step] if not macro_step.is_a?(Array)
39
+ # スティック操作の時はボタン入力を通す
40
+ binary.set_no_action! if is_button?(macro_step)
41
+
42
+ macro_step.uniq.each do |ms|
43
+ next if ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == ms
47
44
 
48
- if ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE == button
49
- binary.set_no_action!
50
- else
51
- binary.write_as_press_button_only(button)
45
+ if is_button?(ms)
46
+ binary.write_as_press_button(ms)
47
+ elsif is_stick?(ms)
48
+ binary.write_as_tilt_left_stick(ms)
49
+ else
50
+ warn "知らないmacro stepです"
51
+ end
52
52
  end
53
53
  end
54
54
 
@@ -71,4 +71,18 @@ class ProconBypassMan::Procon::UserOperation
71
71
  aware = ProconBypassMan::PressButtonAware.new(@binary.raw)
72
72
  buttons.all? { |b| aware.pressing_button?(b) }
73
73
  end
74
+
75
+ # @return [Boolean]
76
+ def is_button?(button)
77
+ button = [button] if not button.is_a?(Array)
78
+
79
+ button.all? do |b|
80
+ !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[b.to_sym] || b.to_sym == ProconBypassMan::Procon::MacroBuilder::RESERVED_WORD_NONE
81
+ end
82
+ end
83
+
84
+ # @return [Boolean]
85
+ def is_stick?(step)
86
+ !!(step =~ /\Atilt_/)
87
+ end
74
88
  end
@@ -0,0 +1,18 @@
1
+ class ProconBypassMan::AnalogStickPosition
2
+ attr_accessor :x, :y
3
+
4
+ def initialize(x:, y:)
5
+ @x = x.to_i
6
+ @y = y.to_i
7
+ end
8
+
9
+ def to_binary
10
+ analog_stick_data = [
11
+ (@x & "0xff".to_i(16)),
12
+ ((@y << 4) & "0xf0".to_i(16)) | ((@x >> 8) & "0x0f".to_i(16)),
13
+ (@y >> 4) & "0xff".to_i(16),
14
+ ]
15
+ hex = analog_stick_data.map{ |x| x.to_s(16).rjust(2, "0") }.join
16
+ [hex].pack("H*")
17
+ end
18
+ end
@@ -6,4 +6,9 @@ class ProconBypassMan::Domains::InboundProconBinary < ProconBypassMan::Domains::
6
6
  def user_operation_data?
7
7
  binary[0] == "\x30".b
8
8
  end
9
+
10
+ # @return [Boolean]
11
+ def rumble_data?
12
+ binary[0] == "\x10".b
13
+ end
9
14
  end
@@ -36,13 +36,18 @@ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domain
36
36
 
37
37
  # @param [Symbol] button
38
38
  def write_as_press_button(button)
39
- raise "already pressing button(#{button})" if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
39
+ return if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
40
40
 
41
41
  button_obj = ProconBypassMan::Procon::Button.new(button)
42
42
  value = binary[button_obj.byte_position].unpack("C").first + (2**button_obj.bit_position)
43
43
  binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
44
44
  end
45
45
 
46
+ # @param [Symbol] stick method
47
+ def write_as_tilt_left_stick(step)
48
+ binary[6..8] = ProconBypassMan::Procon::AnalogStickManipulator.new(binary, method: step).to_binary
49
+ end
50
+
46
51
  # @param [Symbol] button
47
52
  def write_as_unpress_button(button)
48
53
  raise "do not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
@@ -0,0 +1,11 @@
1
+ module ProconBypassMan
2
+ module Domains
3
+ module Binary; end
4
+ end
5
+ end
6
+
7
+ require "procon_bypass_man/procon/value_objects/binary/base"
8
+ require "procon_bypass_man/procon/value_objects/binary/has_immutable_binary"
9
+ require "procon_bypass_man/procon/value_objects/binary/has_mutable_binary"
10
+ require "procon_bypass_man/procon/value_objects/binary/inbound_procon_binary"
11
+ require "procon_bypass_man/procon/value_objects/binary/processing_procon_binary"
@@ -0,0 +1,18 @@
1
+ class ProconBypassMan::RumbleBinary
2
+ # @param [String] binary
3
+ def initialize(binary: )
4
+ @binary = binary
5
+ end
6
+
7
+ def unpack
8
+ @binary.unpack("H*")
9
+ end
10
+
11
+ def noop!
12
+ @binary = ProconBypassMan::SuppressRumble.new(binary: @binary).execute
13
+ end
14
+
15
+ def raw
16
+ @binary
17
+ end
18
+ end
@@ -1,4 +1,13 @@
1
+ require "procon_bypass_man/procon/macro_plugin_map"
2
+
1
3
  class ProconBypassMan::Procon
4
+ require "procon_bypass_man/procon/value_objects/analog_stick"
5
+ require "procon_bypass_man/procon/value_objects/analog_stick_position"
6
+ require "procon_bypass_man/procon/value_objects/procon_reader"
7
+ require "procon_bypass_man/procon/value_objects/rumble_binary"
8
+ require "procon_bypass_man/procon/value_objects/binary"
9
+ require "procon_bypass_man/procon/value_objects/bypass_mode"
10
+
2
11
  require "procon_bypass_man/procon/consts"
3
12
  require "procon_bypass_man/procon/mode_registry"
4
13
  require "procon_bypass_man/procon/macro"
@@ -9,6 +18,7 @@ class ProconBypassMan::Procon
9
18
  require "procon_bypass_man/procon/user_operation"
10
19
  require "procon_bypass_man/procon/flip_cache"
11
20
  require "procon_bypass_man/procon/press_button_aware"
21
+ require "procon_bypass_man/procon/suppress_rumble"
12
22
 
13
23
  attr_accessor :user_operation
14
24
 
@@ -78,12 +88,22 @@ class ProconBypassMan::Procon
78
88
  end
79
89
 
80
90
  if user_operation.pressing_all_buttons?(options[:if_pressed])
81
- @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
91
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name, force_neutral_buttons: options[:force_neutral])
82
92
  break
83
93
  end
84
94
  end
85
95
  end
86
96
 
97
+ # remote macro
98
+ if task = ProconBypassMan::RemoteMacro::TaskQueueInProcess.non_blocking_shift
99
+ ProconBypassMan::Procon::MacroRegistry.cleanup_remote_macros!
100
+ macro_name = task.name || "RemoteMacro-#{task.steps.join}".to_sym
101
+ ProconBypassMan::Procon::MacroRegistry.install_plugin(macro_name, steps: task.steps, macro_type: :remote)
102
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name, macro_type: :remote) do
103
+ ProconBypassMan::PostCompletedRemoteMacroJob.perform_async(task.uuid)
104
+ end
105
+ end
106
+
87
107
  case current_layer.mode
88
108
  when :manual
89
109
  @@status[:ongoing_mode] = ModeRegistry.load(:manual)
@@ -124,9 +144,11 @@ class ProconBypassMan::Procon
124
144
  return user_operation.binary.raw
125
145
  end
126
146
 
127
- if ongoing_macro.ongoing?
128
- step = ongoing_macro.next_step or return(user_operation.binary.raw)
129
- user_operation.press_button_only(step)
147
+ if ongoing_macro.ongoing? && (step = ongoing_macro.next_step)
148
+ ongoing_macro.force_neutral_buttons&.each do |force_neutral_button|
149
+ user_operation.unpress_button(force_neutral_button)
150
+ end
151
+ user_operation.press_button_only_or_tilt_sticks(step)
130
152
  return user_operation.binary.raw
131
153
  end
132
154
 
@@ -135,7 +157,7 @@ class ProconBypassMan::Procon
135
157
  end
136
158
 
137
159
  current_layer.left_analog_stick_caps.each do |config|
138
- if config[:if_pressed].nil? || user_operation.pressing_all_buttons?(config[:if_pressed])
160
+ if !config[:if_pressed] || user_operation.pressing_all_buttons?(config[:if_pressed])
139
161
  config[:force_neutral]&.each do |force_neutral_button|
140
162
  user_operation.unpress_button(force_neutral_button)
141
163
  end
@@ -0,0 +1,62 @@
1
+ class ProconBypassMan::QueueOverProcess
2
+ attr_reader :drb
3
+
4
+ @@drb_server = nil
5
+ @@drb_server_thread = nil
6
+
7
+ def self.start!
8
+ return unless ProconBypassMan.config.enable_remote_macro?
9
+ require 'drb/drb'
10
+
11
+ FileUtils.rm_rf(file_path) if File.exist?(file_path)
12
+ begin
13
+ @@drb_server = DRb.start_service(url, Queue.new, safe_level: 1)
14
+ rescue Errno::EADDRINUSE => e
15
+ ProconBypassMan.logger.error e
16
+ raise
17
+ end
18
+
19
+ @@drb_server_thread =
20
+ Thread.new do
21
+ DRb.thread.join
22
+ end
23
+ end
24
+
25
+ def self.shutdown
26
+ if @@drb_server
27
+ @@drb_server_thread.kill
28
+ @@drb_server.stop_service
29
+ end
30
+ end
31
+
32
+ def self.push(value)
33
+ return unless ProconBypassMan.config.enable_remote_macro?
34
+
35
+ drb.push(value)
36
+ end
37
+
38
+ def self.pop
39
+ return unless ProconBypassMan.config.enable_remote_macro?
40
+
41
+ drb.pop
42
+ end
43
+
44
+ def self.drb
45
+ return unless ProconBypassMan.config.enable_remote_macro?
46
+
47
+ @@drb ||= new.drb
48
+ end
49
+
50
+ PROTOCOL = "drbunix"
51
+ def self.url
52
+ "#{PROTOCOL}:/tmp/procon_bypass_man_queue"
53
+ end
54
+
55
+ def self.file_path
56
+ url.gsub("#{PROTOCOL}:", "")
57
+ end
58
+
59
+ def initialize
60
+ @drb = DRbObject.new_with_uri(self.class.url)
61
+ end
62
+ end