class Rsrb::World::Instance
Attributes
door_manager[R]
event_manager[R]
items[R]
loader[R]
npcs[R]
object_manager[R]
object_tick[R]
objects[R]
player_tick[R]
players[R]
region_manager[R]
settings[R]
shop_manager[R]
Public Class Methods
new(label = 'Default')
click to toggle source
# File lib/rsrb/world/world.rb, line 20 def initialize(label = 'Default') init_loggers load_settings @label = label @players = [] @npcs = [] @items = [] @objects = [] @player_tick = generate_player_tick_task @object_tick = generate_object_tick_task @item_tick = generate_item_tick_task ## # Bad ideas inc. @tick_executor = Concurrent::CachedThreadPool.new @region_manager = Rsrb::Model::RegionManager.new @loader = Rsrb::World::PlayerFileLoader.new @shop_manager = Rsrb::Shops::ShopManager.new #@door_manager = Rsrb::Doors::DoorManager.new log "Initialized world: #{@label}" rescue StandardError => e err!'A fatal error occurred while initializing the world' err! e end
Public Instance Methods
full?()
click to toggle source
Is the world full?
# File lib/rsrb/world/world.rb, line 51 def full? @players.size >= @settings[:max_players] end
launch()
click to toggle source
# File lib/rsrb/world/world.rb, line 86 def launch Rsrb::Item::ItemDefinition.load Rsrb::Model::Equipment.load shop_manager.load_shops #door_manager.load_single_doors #door_manager.load_double_doors npc = XmlSimple.xml_in('assets/npc_spawns.xml') npc['npc'].each_with_index do |row, _idx| spawn_npc(row) if @settings[:debug_world] log("Spawned #{row}") if @settings[:debug_world] end items = XmlSimple.xml_in('assets/item_spawns.xml') items['item'].each_with_index do |row, _idx| @items << Rsrb::Item::Spawn.new(row) log("Spawned #{row}") if @settings[:debug_world] end log 'Launched World!!' rescue StandardError => e err! "A fatal error occurred while launching world: #{self} !" err! e end
receive(session)
click to toggle source
Adds a session to the login queue @param session [Rsrb::Net::Session] the session to add
# File lib/rsrb/world/world.rb, line 58 def receive(session) begin log "Receiving session: #{session}" if @players.any? { |player| player.name == session.credentials[:username] } log! 'Found duplicate player' bldr = Rsrb::Net::PacketBuilder.new(-1, :RAW) bldr.add_byte response session.connection.send_data bldr.to_packet session.connection.close_connection true end ## # TODO: Temp. send bad credentials code if bad return unless @loader.validate_credentials(session.credentials) player = Rsrb::Model::Player.new(session) log "Made player #{player}" if @settings[:debug_world] session.player = @loader.load_profile(player) log "Registering #{session.player}" register(session.player) rescue StandardError => e err "An error occurred while receiving session for #{session.name}!" err e return end end
register(player)
click to toggle source
# File lib/rsrb/world/world.rb, line 112 def register(player) # Register player.index = (@players << player).index(player) + 1 log "Setting #{player} index to #{player.index}" if @settings[:debug_world] # Send Login player.io.send_login player.varp.friends ||= [] player.varp.ignores ||= [] #player.var.pm = Rsrb::Content::PM::Presence.new(player) HOOKS[:player_login].each do |k, v| begin log "Running hook #{v}" if @settings[:debug_world] v.call(player) rescue StandardError => e err "Unable to run login hook #{k} for player #{player.name}", e end end log "Registered player #{player.name}!" end
register_npc(npc)
click to toggle source
# File lib/rsrb/world/world.rb, line 156 def register_npc(npc) log "Registering npc #{npc.id}" if @settings[:debug_world] npc.index = (@npcs << npc).index(npc) + 1 end
reset_ticks()
click to toggle source
Attempts to gracefully shutdown the world
# File lib/rsrb/world/world.rb, line 203 def reset_ticks log! 'Resetting Ticks!' @object_tick.shutdown @item_tick.shutdown @player_tick.shutdown @object_tick = generate_object_tick_task @player_tick = generate_player_tick_task @item_tick = generate_item_tick_task log 'Reset & Regenerated tick tasks.' end
spawn_npc(data)
click to toggle source
# File lib/rsrb/world/world.rb, line 176 def spawn_npc(data) npc = Rsrb::NPC::NPC.new(Rsrb::NPC::NPCDefinition.for_id(data['id'].to_i)) npc.location = Rsrb::Model::Location.new(data['x'].to_i, data['y'].to_i, data['z'].to_i) register_npc(npc) if data.include?('face') npc.direction = data['face'].to_sym offsets = DIRECTIONS[npc.direction] npc.face(npc.location.transform(offsets[0], offsets[1], 0)) end # Add shop hook if NPC owns a shop return unless data.include?('shop') handler = HOOKS[:npc_option2][data['id'].to_i] return unless handler.instance_of?(Proc) on_npc_option2(data['id'].to_i) do |player, mob| Rsrb::Shops::ShopManager.open(data['shop'].to_i, player) player.interacting_entity = mob end end
submit_task(opts = { count: 1, delay: 0}, &task)
click to toggle source
# File lib/rsrb/world/world.rb, line 161 def submit_task(opts = { count: 1, delay: 0}, &task) log! "Submitting task #{task}" if @settings[:debug_world] Rsrb::World::Task.new(opts) { task.call } rescue StandardError => e err 'An error occurred while submitting a task!', e end
unregister(player, single = true)
click to toggle source
# File lib/rsrb/world/world.rb, line 135 def unregister(player, single = true) submit_task do return unless @players.include?(player) log "Unregistering #{player.name}." HOOKS[:player_logout].each do |k, v| begin log "Running logout hook #{v} for #{player.name}" if @settings[:debug_world] v.call(player) rescue StandardError => e err "Unable to run logout hook #{k} for player #{player.name}", e end end player.destroy player.connection.close_connection_after_writing @players.delete(player) if single @loader.save_profile(player) end end
update(time, result, ex)
click to toggle source
# File lib/rsrb/world/world.rb, line 168 def update(time, result, ex) if result log"(#{result}) Executed successfully." if @settings[:tick_debug] else err "(#{time}) Execution failed with error #{ex}", ex end end
Private Instance Methods
generate_item_tick_task()
click to toggle source
Sets up the item/ground_item respawn/reset tick task. @return [Concurrent::TimerTask] the item tick task.
# File lib/rsrb/world/world.rb, line 290 def generate_item_tick_task t = Concurrent::TimerTask.execute(execution_interval: 1) do @tick_executor.post do @items.each do |item| item.respawn -= 1 if item.picked_up item.spawn if item.picked_up && item.respawn <= 0 end end end t.add_observer(self) log "Generated & scheduled Item tick task #{t}" t end
generate_object_tick_task()
click to toggle source
Sets up the object respawn/reset tick task. @return [Concurrent::TimerTask] the object tick task.
# File lib/rsrb/world/world.rb, line 270 def generate_object_tick_task t = Concurrent::TimerTask.execute(execution_interval: 1) do @tick_executor.post do @objects.each do |object| object.delay -= 1 next unless object.delay <= 0 object.reset @objects.delete(object) end end end t.add_observer(self) log "Generated & scheduled Object tick task #{t}" t end
generate_player_tick_task()
click to toggle source
Sets up the player tick task @return [Concurrent::TimerTask] the player tick task
# File lib/rsrb/world/world.rb, line 231 def generate_player_tick_task t = Concurrent::TimerTask.execute(execution_interval: 0.600) do @tick_executor.post do ticks = [] updates = [] resets = [] @players.each do |p| next unless p.index ticks << Rsrb::Tasks::PlayerTickTask.new(p) resets << Rsrb::Tasks::PlayerResetTask.new(p) updates << Rsrb::Tasks::PlayerUpdateTask.new(p) updates << Rsrb::Tasks::NPCUpdateTask.new(p) end @npcs.each do |npc| ticks << Rsrb::Tasks::NPCTickTask.new(npc) resets << Rsrb::Tasks::NPCResetTask.new(npc) end ## # Tick @tick_executor.post { ticks.each(&:execute) } ## # Update @tick_executor.post { updates.each(&:execute) } ## # Reset @tick_executor.post { resets.each(&:execute) } end end t.add_observer(self) log "Generated & scheduled Player tick task #{t}" t end
load_settings()
click to toggle source
Loads the settings for the world. Settings are expected to be stored at `$WORKING_DIR/assets/config/.world.env`
# File lib/rsrb/world/world.rb, line 218 def load_settings Dotenv.load('assets/config/.world.env') @settings = { debug_task: ENV['TASK_DEBUG'].to_i.positive?, debug_tick: ENV['TICK_DEBUG'].to_i.positive?, debug_world: ENV['WORLD_DEBUG'].to_i.positive?, max_players: ENV['MAX_PLAYERS'].to_i, max_npcs: ENV['MAX_NPCS'].to_i }.freeze log "Read Settings: #{@settings}" end