Fixed some issues related to threading in game clock by using a queue

This commit is contained in:
2021-09-30 10:51:49 -05:00
parent 7bfc404413
commit fd6eb64232
10 changed files with 139 additions and 80 deletions

View File

@@ -7,4 +7,5 @@ gem "clipboard"
group :packaging do group :packaging do
gem "ocra" gem "ocra"
gem "releasy"
end end

View File

@@ -2,18 +2,24 @@ GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
clipboard (1.3.6) clipboard (1.3.6)
cri (2.1.0)
cyberarm_engine (0.19.1) cyberarm_engine (0.19.1)
clipboard (~> 1.3.5) clipboard (~> 1.3.5)
excon (~> 0.78.0) excon (~> 0.78.0)
gosu (~> 1.1) gosu (~> 1.1)
gosu_more_drawables (~> 0.3) gosu_more_drawables (~> 0.3)
excon (0.78.1) excon (0.78.1)
ffi (1.15.4)
ffi (1.15.4-x64-mingw32) ffi (1.15.4-x64-mingw32)
gosu (1.2.0) gosu (1.2.0)
gosu_more_drawables (0.3.1) gosu_more_drawables (0.3.1)
gosu_notifications (0.1.0) gosu_notifications (0.1.0)
ocra (1.3.11) ocra (1.3.11)
rake (13.0.6)
releasy (0.2.3)
bundler (>= 1.2.1)
cri (~> 2.1.0)
ocra (~> 1.3.0)
rake (>= 0.9.2.2)
PLATFORMS PLATFORMS
x64-mingw32 x64-mingw32
@@ -25,6 +31,7 @@ DEPENDENCIES
ffi ffi
gosu_notifications gosu_notifications
ocra ocra
releasy
BUNDLED WITH BUNDLED WITH
2.2.28 2.2.28

View File

@@ -7,13 +7,23 @@ Releasy::Project.new do
version TAC::VERSION version TAC::VERSION
executable "timecrafters_configuration_tool.rb" executable "timecrafters_configuration_tool.rb"
files ["lib/**/*.*", "media/**/*.*", "data/.gitkeep", "data/configs/.gitkeep"] files [
"lib/**/*.*",
"data/.gitkeep",
"data/configs/.gitkeep",
"media/*.*",
"media/icons/*.*",
"media/fonts/*.*",
"media/sounds/.gitkeep",
"media/music/.gitkeep",
"media/particles/.gitkeep"
]
exclude_encoding # Applications that don't use advanced encoding (e.g. Japanese characters) can save build size with this. exclude_encoding # Applications that don't use advanced encoding (e.g. Japanese characters) can save build size with this.
verbose verbose
add_build :windows_folder do add_build :windows_folder do
icon "media/icon.ico" icon "media/icon.ico"
executable_type :windows # Assuming you don't want it to run with a console window. executable_type :console # Assuming you don't want it to run with a console window.
add_package :exe # Windows self-extracting archive. add_package :exe # Windows self-extracting archive.
end end
end end

View File

@@ -1,13 +1,20 @@
module TAC module TAC
class PracticeGameClock class PracticeGameClock
class ClockProxy class ClockProxy
attr_reader :queue, :clock
def initialize(clock, jukebox) def initialize(clock, jukebox)
@clock = clock @clock = clock
@jukebox = jukebox @jukebox = jukebox
@queue = []
@callbacks = {} @callbacks = {}
end end
def enqueue(&block)
@queue << block
end
def register(callback, method) def register(callback, method)
@callbacks[callback] = method @callbacks[callback] = method
end end

View File

@@ -83,127 +83,143 @@ module TAC
end end
def handle_start_clock(packet) def handle_start_clock(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.enqueue do
@proxy_object.start_clock(packet.body.to_sym) @proxy_object.start_clock(packet.body.to_sym)
end end
end end
def handle_abort_clock(packet) def handle_abort_clock(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.abort_clock
end @proxy_object.abort_clock
end end
def handle_set_clock_title(packet) def handle_set_clock_title(packet)
unless @host_is_a_connection return if @host_is_a_connection
title = packet.body
title = packet.body
@proxy_object.enqueue do
@proxy_object.set_clock_title(title) @proxy_object.set_clock_title(title)
end end
end end
def handle_get_clock_title(packet) def handle_get_clock_title(packet)
unless @host_is_a_connection return if @host_is_a_connection
RemoteControl.server.active_client.puts(Packet.clock_title(@proxy_object.clock.title))
end RemoteControl.server.active_client.puts(Packet.clock_title(@proxy_object.clock.title))
end end
def handle_jukebox_previous_track(packet) def handle_jukebox_previous_track(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.jukebox_previous_track
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track)) @proxy_object.jukebox_previous_track
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track))
end end
def handle_jukebox_next_track(packet) def handle_jukebox_next_track(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.jukebox_next_track
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track)) @proxy_object.jukebox_next_track
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track))
end end
def handle_jukebox_play(packet) def handle_jukebox_play(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.jukebox_play
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track)) @proxy_object.jukebox_play
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track))
end end
def handle_jukebox_pause(packet) def handle_jukebox_pause(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.jukebox_pause
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track)) @proxy_object.jukebox_pause
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track))
end end
def handle_jukebox_stop(packet) def handle_jukebox_stop(packet)
unless @host_is_a_connection return if @host_is_a_connection
@proxy_object.jukebox_stop
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track)) @proxy_object.jukebox_stop
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_current_track(@proxy_object.jukebox_current_track))
end end
def handle_jukebox_set_volume(packet) def handle_jukebox_set_volume(packet)
unless @host_is_a_connection return if @host_is_a_connection
float = packet.body.to_f
float = float.clamp(0.0, 1.0)
@proxy_object.jukebox_set_volume(float) float = packet.body.to_f
float = float.clamp(0.0, 1.0)
float = @proxy_object.jukebox_volume @proxy_object.jukebox_set_volume(float)
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_volume(float))
end float = @proxy_object.jukebox_volume
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_volume(float))
end end
def handle_jukebox_get_volume(packet) def handle_jukebox_get_volume(packet)
unless @host_is_a_connection return if @host_is_a_connection
float = @proxy_object.jukebox_volume
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_volume(float)) float = @proxy_object.jukebox_volume
end
RemoteControl.server.active_client.puts(PacketHandler.packet_jukebox_volume(float))
end end
def handle_jukebox_volume(packet) def handle_jukebox_volume(packet)
if @host_is_a_connection return unless @host_is_a_connection
float = packet.body.to_f
float = packet.body.to_f
@proxy_object.enqueue do
@proxy_object.volume_changed(float) @proxy_object.volume_changed(float)
end end
end end
def handle_jukebox_set_sound_effects(packet) def handle_jukebox_set_sound_effects(packet)
unless @host_is_a_connection return if @host_is_a_connection
boolean = packet.body == "true"
boolean = packet.body == "true"
@proxy_object.enqueue do
@proxy_object.jukebox_set_sound_effects(boolean) @proxy_object.jukebox_set_sound_effects(boolean)
end end
end end
def handle_jukebox_current_track(packet) def handle_jukebox_current_track(packet)
if @host_is_a_connection return unless @host_is_a_connection
@proxy_object.enqueue do
@proxy_object.track_changed(packet.body) @proxy_object.track_changed(packet.body)
end end
end end
def handle_clock_time(packet) def handle_clock_time(packet)
if @host_is_a_connection return unless @host_is_a_connection
@proxy_object.enqueue do
@proxy_object.clock_changed(packet.body) @proxy_object.clock_changed(packet.body)
end end
end end
def handle_randomizer_visible(packet) def handle_randomizer_visible(packet)
boolean = packet.body == "true" boolean = packet.body == "true"
boolean = false if @proxy_object.is_a?(ClockProxy) && @proxy_object.clock.active?
@proxy_object.randomizer_changed(boolean) @proxy_object.enqueue do
@proxy_object.randomizer_changed(boolean)
unless @host_is_a_connection
# Send confirmation to client
RemoteControl.server.active_client.puts(PacketHandler.packet_randomizer_visible(boolean))
end end
return if @host_is_a_connection
# Send confirmation to client
RemoteControl.server.active_client.puts(PacketHandler.packet_randomizer_visible(boolean))
end end
def handle_shutdown(packet) def handle_shutdown(packet)

View File

@@ -5,7 +5,8 @@ module TAC
TAG = "ClockNet|Server" TAG = "ClockNet|Server"
attr_reader :active_client, attr_reader :active_client,
:packets_sent, :packets_received, :data_sent, :data_received, :packets_sent, :packets_received, :data_sent, :data_received,
:client_last_packets_sent, :client_last_packets_received, :client_last_data_sent, :client_last_data_received :client_last_packets_sent, :client_last_packets_received, :client_last_data_sent, :client_last_data_received,
:proxy_object
def initialize(hostname: "localhost", port: 4567, proxy_object: ) def initialize(hostname: "localhost", port: 4567, proxy_object: )
$server = self $server = self

View File

@@ -18,19 +18,19 @@ module TAC
# Blue: Right # Blue: Right
# Red: Left # Red: Left
@ducks << Ducky.new(alliance: :blue, slot: 3, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :blue, slot: 3, speed: 512, die_size: @size)
@ducks << Ducky.new(alliance: :red, slot: 1, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :red, slot: 1, speed: 512, die_size: @size)
when 2, 5 when 2, 5
#Blue and Red: Center #Blue and Red: Center
@ducks << Ducky.new(alliance: :blue, slot: 2, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :blue, slot: 2, speed: 512, die_size: @size)
@ducks << Ducky.new(alliance: :red, slot: 2, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :red, slot: 2, speed: 512, die_size: @size)
when 3, 6 when 3, 6
# Blue: Left # Blue: Left
# Red: Right # Red: Right
@ducks << Ducky.new(alliance: :blue, slot: 1, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :blue, slot: 1, speed: 512, die_size: @size)
@ducks << Ducky.new(alliance: :red, slot: 3, speed: 512, die_size: @size) @ducks << Ducky.new(window: window, alliance: :red, slot: 3, speed: 512, die_size: @size)
end end
end end
@@ -58,7 +58,7 @@ module TAC
def update def update
window.previous_state&.update_non_gui window.previous_state&.update_non_gui
@ducks.each { |o| o.update(window, @size) } @ducks.each { |o| o.update(@size) }
@size = [window.width, window.height].min / 2.0 @size = [window.width, window.height].min / 2.0
end end
@@ -113,15 +113,17 @@ module TAC
SIZE = 0.20 SIZE = 0.20
HALF_SIZE = SIZE * 0.5 HALF_SIZE = SIZE * 0.5
def initialize(alliance:, slot:, speed:, die_size:) def initialize(window:, alliance:, slot:, speed:, die_size:)
@window = window
@alliance = alliance @alliance = alliance
@slot = slot @slot = slot
@speed = speed @speed = speed
@image = $window.get_image("#{ROOT_PATH}/media/openclipart_ducky.png") @image = @window.get_image("#{ROOT_PATH}/media/openclipart_ducky.png")
@debug_text = Gosu::Font.new(28)
if @alliance == :blue if @alliance == :blue
@position = CyberarmEngine::Vector.new($window.width, die_size) @position = CyberarmEngine::Vector.new(@window.width, die_size)
else else
@position = CyberarmEngine::Vector.new(-die_size, die_size + die_size * 0.40) @position = CyberarmEngine::Vector.new(-die_size, die_size + die_size * 0.40)
end end
@@ -139,14 +141,14 @@ module TAC
end end
end end
def update(window, size) def update(size)
center = window.width * 0.5 - size * 0.5 center = @window.width * 0.5 - size * 0.5
if @position.x > center if @position.x > center
@position.x -= @speed * window.dt @position.x -= @speed * @window.dt
@position.x = center if @position.x < center @position.x = center if @position.x < center
elsif @position.x < center elsif @position.x < center
@position.x += @speed * window.dt @position.x += @speed * @window.dt
@position.x = center if @position.x > center @position.x = center if @position.x > center
end end
end end

View File

@@ -178,7 +178,7 @@ module TAC
button get_image("#{ROOT_PATH}/media/icons/plus.png") do button get_image("#{ROOT_PATH}/media/icons/plus.png") do
@jukebox_volume += 0.1 @jukebox_volume += 0.1
@jukebox_volume = 0.1 if @jukebox_volume < 0.1 @jukebox_volume = 1.0 if @jukebox_volume > 1.0
RemoteControl.connection.puts(ClockNet::PacketHandler.packet_jukebox_set_volume(@jukebox_volume)) RemoteControl.connection.puts(ClockNet::PacketHandler.packet_jukebox_set_volume(@jukebox_volume))
end end
@@ -211,9 +211,7 @@ module TAC
stack width: 0.9, margin_left: 50, margin_top: 20 do stack width: 0.9, margin_left: 50, margin_top: 20 do
flow width: 1.0 do flow width: 1.0 do
title "Clock: " title "Clock: "
@clock_label = title "0:123456789" @clock_label = title "0:00"
@clock_label.width
@clock_label.value = "0:00"
end end
flow width: 1.0 do flow width: 1.0 do
@@ -234,6 +232,10 @@ module TAC
def update def update
super super
while (o = RemoteControl.connection.proxy_object.queue.shift)
o.call
end
return if RemoteControl.connection.connected? return if RemoteControl.connection.connected?
# We've lost connection, unset window's connection object # We've lost connection, unset window's connection object
@@ -252,7 +254,7 @@ module TAC
end end
def volume_changed(float) def volume_changed(float)
@volume.value = "#{float.round(1) * 100.0}%" @volume.value = "#{(float.round(1) * 100.0).round}%"
end end
def clock_changed(string) def clock_changed(string)
@@ -260,7 +262,6 @@ module TAC
end end
def randomizer_changed(boolean) def randomizer_changed(boolean)
puts "Randomizer is visable? #{boolean}"
@randomizer_label.value = "Visible" if boolean @randomizer_label.value = "Visible" if boolean
@randomizer_label.value = "Not Visible" unless boolean @randomizer_label.value = "Not Visible" unless boolean
end end

View File

@@ -1,12 +1,19 @@
module TAC module TAC
class PracticeGameClock class PracticeGameClock
class RemoteProxy class RemoteProxy
attr_reader :queue
def initialize(window) def initialize(window)
@window = window @window = window
@queue = []
@callbacks = {} @callbacks = {}
end end
def enqueue(&block)
@queue << block
end
def register(callback, method) def register(callback, method)
@callbacks[callback] = method @callbacks[callback] = method
end end

View File

@@ -5,12 +5,13 @@ module TAC
attr_reader :clock attr_reader :clock
def setup def setup
window.show_cursor = true
@remote_control_mode = @options[:remote_control_mode] @remote_control_mode = @options[:remote_control_mode]
window.show_cursor = !@remote_control_mode
@escape_counter = 0 @escape_counter = 0
@background_image = get_image("#{ROOT_PATH}/media/background.png") @background_image = get_image("#{ROOT_PATH}/media/background.png")
# Preload duck image since Gosu and windows threads don't get along with OpenGL (image is blank if loaded in a threaded context)
get_image("#{ROOT_PATH}/media/openclipart_ducky.png")
@menu_background = 0xaa004000 @menu_background = 0xaa004000
@mouse = Mouse.new(window) @mouse = Mouse.new(window)
@clock = Clock.new @clock = Clock.new
@@ -61,6 +62,7 @@ module TAC
else else
@server&.close @server&.close
@jukebox.stop
window.fullscreen = false window.fullscreen = false
window.pop_state window.pop_state
end end
@@ -172,8 +174,7 @@ module TAC
super super
@clock.update @clock.update
@mouse.update @mouse.update
@jukebox.update update_non_gui
@particle_emitters.each(&:update)
if @last_clock_state != @clock.active? if @last_clock_state != @clock.active?
@particle_emitters.each { |emitter| @clock.active? ? emitter.clock_active! : emitter.clock_inactive! } @particle_emitters.each { |emitter| @clock.active? ? emitter.clock_active! : emitter.clock_inactive! }
@@ -213,6 +214,12 @@ module TAC
end end
def update_non_gui def update_non_gui
if @remote_control_mode
while (o = RemoteControl.server.proxy_object.queue.shift)
o.call
end
end
@particle_emitters.each(&:update) @particle_emitters.each(&:update)
@jukebox.update @jukebox.update
end end
@@ -251,7 +258,7 @@ module TAC
def randomizer_changed(boolean) def randomizer_changed(boolean)
if boolean if boolean
push_state(Randomizer) push_state(Randomizer) unless @clock.active?
else else
pop_state if current_state.is_a?(Randomizer) pop_state if current_state.is_a?(Randomizer)
end end