class SDTD_Server

Attributes

connected[R]
port[R]
server[R]

Public Class Methods

new(params = {}) click to toggle source
# File lib/sdtd_server.rb, line 409
def initialize(params = {})
  #
  @server     = params.fetch(:server, 'localhost')
  @port       = params.fetch(:port, '8081')
  @password   = params.fetch(:password, 'CHANGEME')
  @connection = Net::Telnet.new('Host' => @server, 'Port' => @port, 'Telnetmode' => false)
  @connected  = false
  #
  console_login
  loglevel 'ALL', false
  #
end

Public Instance Methods

admin() click to toggle source
# File lib/sdtd_server.rb, line 11
def admin
  placeholder
end
ban(subcommand, user_id=nil, time=nil, units=nil, reason=nil) click to toggle source
# File lib/sdtd_server.rb, line 167
def ban(subcommand, user_id=nil, time=nil, units=nil, reason=nil)
  case subcommand
    when 'list'
      return ban_list
    when 'remove'
      raise MissingCommandOptionError unless user_id
      return ban_remove user_id
    when 'add'
      raise MissingCommandOptionError unless user_id and time and units
      return ban_add user_id, time, units, reason
  else
    raise UnknownBanSubCommandError
  end

  return nil
end
close() click to toggle source
# File lib/sdtd_server.rb, line 304
def close
  close_telnet_connection
end
commandpermission() click to toggle source
# File lib/sdtd_server.rb, line 15
def commandpermission
  placeholder
end
cp() click to toggle source
# File lib/sdtd_server.rb, line 19
def cp
  commandpermission
end
getgamepref(pref_name=nil) click to toggle source
# File lib/sdtd_server.rb, line 184
def getgamepref(pref_name=nil)
  return get_all_game_prefs unless pref_name

  gamepref = telnet_command "getgamepref #{pref_name}", /GamePref\./, /GamePref\.[^=]+=\s+(.*)/
  gamepref = gamepref.first

  return gamepref.first
end
gettime() click to toggle source
# File lib/sdtd_server.rb, line 246
def gettime
  get_time_results = telnet_command 'gettime', /Day/, /Day\s+(\d+),\s+(\d+):(\d+)/
  get_time_results = get_time_results.first

  return {:day => get_time_results.shift, :hour => get_time_results.shift, :minute => get_time_results.shift}
end
gg(pref_name=nil) click to toggle source
# File lib/sdtd_server.rb, line 193
def gg(pref_name=nil)
  getgamepref pref_name
end
gt() click to toggle source
# File lib/sdtd_server.rb, line 253
def gt
  gettime
end
kick(user, reason=nil) click to toggle source
# File lib/sdtd_server.rb, line 157
def kick(user, reason=nil)
  user = user.to_s

  kick_command = reason == nil ? "kick #{user}" : "kick #{user} \"#{reason}\""
  kick_results = telnet_command kick_command, /not a valid|Kicking/

  raise InvalidUserError unless kick_results.include? 'Kicking'
  return nil
end
kickall(reason="Everyone has been kicked from the server.") click to toggle source
# File lib/sdtd_server.rb, line 216
def kickall(reason="Everyone has been kicked from the server.")
  telnet_command "kickall \"#{reason}\""
  return nil
end
kill(ent_id) click to toggle source
# File lib/sdtd_server.rb, line 149
def kill(ent_id)
  kill_results = telnet_command "kill #{ent_id.to_s}", /not found\.|damage to entity/

  raise InvalidEntIDError unless kill_results.include? 'damage to'

  return nil
end
killall() click to toggle source
# File lib/sdtd_server.rb, line 144
def killall
  telnet_command 'killall'
  return nil
end
le() click to toggle source
# File lib/sdtd_server.rb, line 132
def le
  listents
end
lgo() click to toggle source
# File lib/sdtd_server.rb, line 140
def lgo
  listgameobjects
end
lgs(message) click to toggle source
# File lib/sdtd_server.rb, line 70
def lgs(message)
  loggamestate message
end
listents() click to toggle source
# File lib/sdtd_server.rb, line 108
def listents
  # Regex Example: http://regexr.com/3cgok
  listents_results = telnet_command 'listents', /in the game/, /\d\. id=(\d+), \[type=(\w+), name=(\w+), id=\d+\], pos=\(([^\)]+)\), rot=\(([^\)]+)\), lifetime=([^,]+), remote=(True|False), dead=(True|False), health=(\d+)/

  ent_keys = [
    'type', 'name', 'position',
    'rotation', 'lifetime', 'remote',
    'dead', 'health']

  ents = Hash.new

  listents_results.each do |ent|

    ent_id = ent.shift.to_sym
    ents[ent_id] = Hash.new

    ent_keys.each do |key|
      ents[ent_id][key.to_sym] = ent.shift
    end
  end

  return ents
end
listgameobjects() click to toggle source
# File lib/sdtd_server.rb, line 136
def listgameobjects
  return telnet_command('listgameobjects', /took/, /GOs: (\d+),/).first
end
listplayerids() click to toggle source
# File lib/sdtd_server.rb, line 285
def listplayerids
  console_output = telnet_command 'listplayerids', /Total of/

  players = Hash.new

  console_output.scan( /\d+\.\s+id=(\d+),\s+(.+)/ ).each do |current_player|
    user_id   = current_player[0].to_sym
    user_name = current_player[1]

    players[user_id] = user_name
  end

  return players
end
listplayers() click to toggle source
# File lib/sdtd_server.rb, line 74
def listplayers
  # Regex Exampple: http://regexr.com/3cgoe
  begin
    player_list_output = telnet_command 'listplayers', /in the game/, /\d+\.\sid=(\d+),\s([^,]+), pos=\(([^\)]+)\), rot=\(([^\)]+)\), remote=(True|False), health=(\d+), deaths=(\d+), zombies=(\d+), players=(\d+), score=(\d+), level=(\d+), steamid=(\d+), ip=([^,]+), ping=(\d+)/
  rescue NoMethodError
    return {}
  end

  player_data = Hash.new

  player_keys = [
    'name', 'position', 'rotation',
    'is_remote', 'health', 'deaths',
    'zombies', 'players', 'score',
    'level', 'steamid', 'ip',
    'ping']

  player_list_output.each do |player|

    player_id = player.shift
    player_data[player_id] = Hash.new

    player_keys.each do |key|
      player_data[player_id][key.to_sym] = player.shift
    end
  end

  return player_data
end
loggamestate(message) click to toggle source
# File lib/sdtd_server.rb, line 65
def loggamestate(message)
  telnet_command "loggamestate \"#{message}\"", /Wrote game state/
  return nil
end
lp() click to toggle source
# File lib/sdtd_server.rb, line 104
def lp
  listplayers
end
lpi() click to toggle source
# File lib/sdtd_server.rb, line 300
def lpi
  listplayerids
end
mem() click to toggle source
# File lib/sdtd_server.rb, line 266
def mem
  # Regex extract example: http://regexr.com/3cglt
  mem_results = telnet_command 'mem', /Time:/, /Time:\s+([^\s]+)\s+FPS:\s+([\d\.]+)\s+Heap:\s+([^\s]+)\s+Max:\s+([^\s]+)\s+Chunks:\s+(\d+)\s+CGO:\s+(\d+)\s+Ply:\s+(\d+)\s+Zom:\s+(\d+)\s+Ent:\s+([^\)]+\))\s+Items:\s+(\d+)\s+CO:\s+(\d+)/
  mem_results = mem_results.first

  keys = [
    'time', 'fps', 'heap',
    'max', 'chunks', 'cgo',
    'ply', 'zom', 'ent',
    'items', 'co'
  ]

  result_hash = Hash.new

  keys.each { |key| result_hash[key]=mem_results.shift }

  return result_hash
end
sa() click to toggle source
# File lib/sdtd_server.rb, line 262
def sa
  saveworld
end
saveworld() click to toggle source
# File lib/sdtd_server.rb, line 257
def saveworld
  telnet_command 'saveworld', /World saved/
  return nil
end
say(message) click to toggle source
# File lib/sdtd_server.rb, line 211
def say(message)
  telnet_command "say \"#{message}\""
  return nil
end
se(player_id, ent_id) click to toggle source
# File lib/sdtd_server.rb, line 56
def se(player_id, ent_id)
  spawnentity player_id, ent_id
end
setgamepref(pref_name, new_value) click to toggle source
# File lib/sdtd_server.rb, line 221
def setgamepref(pref_name, new_value)
  set_game_pref_output = telnet_command "setgamepref #{pref_name} #{new_value}", /set|Error parsing parameter/

  raise UnknownGamePrefError if set_game_pref_output.include? 'Error parsing parameter'

  return nil
end
settime(params = {}) click to toggle source
# File lib/sdtd_server.rb, line 233
def settime(params = {})
  # TODO: Add the ability to accept only 1 or 3 inputs to the function, just like the console command.
  day    = params.fetch(:day, '1')
  hour   = params.fetch(:hour, '08')
  minute = params.fetch(:minute, '00')

  telnet_command "settime #{day} #{hour} #{minute}", /Set time to/
end
sg(pref_name, new_value) click to toggle source
# File lib/sdtd_server.rb, line 229
def sg(pref_name, new_value)
  setgamepref pref_name, new_value
end
shutdown() click to toggle source
# File lib/sdtd_server.rb, line 205
def shutdown
  kickall 'The server is shutting down soon...'
  telnet_command 'shutdown'
  return nil
end
spawnairdrop() click to toggle source
# File lib/sdtd_server.rb, line 60
def spawnairdrop
  telnet_command 'spawnairdrop'
  return nil
end
spawnentity(player_id, ent_id) click to toggle source
# File lib/sdtd_server.rb, line 39
def spawnentity(player_id, ent_id)
  spawn_results = telnet_command "spawnentity #{player_id.to_s} #{ent_id.to_s}", /^No spawn point|^Spawned|^Player with|Entity/

  return nil if spawn_results.include? 'Spawned'

  if spawn_results.include? 'No spawn point'
    raise NoSpawnPointError
  elsif spawn_results.include? 'Player with id'
    raise InvalidSpawnUserError
  elsif spawn_results.include? 'Entity'
    raise InvalidEntIDError
  else
    # This should never happen as telnet will raise a timeout error...
    raise UnexpectedResultsError
  end
end
spawnwanderinghorde() click to toggle source
# File lib/sdtd_server.rb, line 33
def spawnwanderinghorde
  # I don't think this really does anything...
  telnet_command 'spawnwanderinghorde'
  return nil
end
st(params = {}) click to toggle source
# File lib/sdtd_server.rb, line 242
def st(params = {})
  settime params
end
version() click to toggle source
# File lib/sdtd_server.rb, line 197
def version
  # Regex example: http://regexr.com/3cgo5
  version_output = telnet_command 'version', /version/, /Game version:\s+(.+)Compatibility Version:\s+(.+)$/
  version_output = version_output.first

  return {:version => version_output.first, :compatibility_version => version_output.last}
end
weathersurvival(correct_state = nil) click to toggle source
# File lib/sdtd_server.rb, line 23
def weathersurvival(correct_state = nil)
  raise InvalidFunctionInputError unless ['on', 'off', nil].include? correct_state

  command = correct_state == nil ? 'weathersurvival' : "weathersurvival #{correct_state}"

  console_output = telnet_command command, /Weather survival/, /Weather survival is (on|off)/

  return correct_state == nil ? console_output.first : nil
end
whitelist() click to toggle source
# File lib/sdtd_server.rb, line 7
def whitelist
  placeholder
end

Private Instance Methods

ban_add(user_id, time, units, reason) click to toggle source
# File lib/sdtd_server.rb, line 309
def ban_add(user_id, time, units, reason)
  ban_add_command = "ban add #{user_id} #{time} #{units}"
  ban_add_command += " \"#{reason}\"" unless reason == nil

  ban_add_results = telnet_command ban_add_command, /banned|not a valid entity id|valid integer|duration unit/

  return nil if ban_add_results.include? 'banned'

  if ban_add_results.include? 'not a valid entity id'
    raise InvalidUserError
  elsif ban_add_results.include? 'valid integer'
    raise InvalidBanTimeError
  elsif ban_add_results.include? 'duration unit'
    raise InvalidBanUnitError
  else
    raise UnexpectedResultsError
  end

  return nil
end
ban_list() click to toggle source
# File lib/sdtd_server.rb, line 342
def ban_list
  # Regex Example: http://regexr.com/3cgp3
  ban_data = telnet_command 'ban list', /-/, /\s([\d\/]{8,10})\s([\d:]+\s(?:AM|PM))\s-\s(\d+)\s-\s?(.*)/

  return {} unless ban_data.length > 0

  ban_keys = ['expire_date', 'expire_time', 'reason']

  bans = Hash.new

  ban_data.each do |this_ban|
    player_id = this_ban.delete_at 2

    bans[player_id] = Hash.new

    ban_keys.each { |key| bans[player_id][key.to_sym] = this_ban.shift }
  end

  return bans
end
ban_remove(steam_id) click to toggle source
# File lib/sdtd_server.rb, line 330
def ban_remove(steam_id)
  remove_results = telnet_command "ban remove #{steam_id}", /not a valid steam id\.|removed/

  return nil if remove_results.include? 'removed from'

  if remove_results.include? 'is not a valid steam id.'
    raise InvalidUserError
  end

  return nil
end
close_telnet_connection() click to toggle source
# File lib/sdtd_server.rb, line 398
def close_telnet_connection
  @connection.cmd('exit')
  @connection.close
end
console_login() click to toggle source
# File lib/sdtd_server.rb, line 392
def console_login
  login_response = telnet_command @password, /Logon successful.|Password incorrect/
  raise InvalidConsolePasswordError unless login_response.include? 'Logon successful.'
  @connected = true
end
get_all_game_prefs() click to toggle source
# File lib/sdtd_server.rb, line 363
def get_all_game_prefs
  game_pref_results = telnet_command('getgamepref', /^GamePref\.ZombiesRun/).split "\n"

  game_prefs = Hash.new

  game_pref_data = game_pref_results.select{ |x| x if x.include? 'GamePref.' }.map do |current_pref|
    extracted_pref_data = current_pref.match( /^GamePref\.([^\s]+)\s+=\s+(.*)/ ).captures

    key   = extracted_pref_data.first.to_sym
    value = extracted_pref_data.last

    game_prefs[key] = value
  end

  return game_prefs
end
loglevel(level, state) click to toggle source
# File lib/sdtd_server.rb, line 380
def loglevel(level, state)
  level.upcase!

  valid_log_levels = [
    'INF', 'WRN', 'ERR',
    'EXC', 'ALL']

  raise InvalidConsoleLogLevelError unless valid_log_levels.include? level and [true, false].include? state

  results = telnet_command "loglevel #{level} #{state}", /on this connection\./
end
placeholder() click to toggle source
# File lib/sdtd_server.rb, line 422
def placeholder
  puts "This function has not been added yet."
end
telnet_command(string, match=/.*/, extract=nil) click to toggle source
# File lib/sdtd_server.rb, line 403
def telnet_command(string, match=/.*/, extract=nil)
  command_results = @connection.cmd('String' => string, 'Match' => match)
  return command_results unless extract
  return command_results.scan(extract)
end