Kernel::load("core/creation_data.rb")
module SocketData
### Attaches a nanny to a socket. It only exists while in creation.
def assign_nanny
@nanny = Fiber.new do
### enter login menu
text_to_socket $greeting
text_to_socket "#nWhat is your name? "
### yield and on next call set arg
while !check_name((narg = Fiber.yield false).capitalize)
text_to_socket "That's not a valid name. What is your name?" + ENDL
log :info, "-- #{@addr}:#{@port}: (#{narg}) Invalid name in character creation."
end
### ensures the name is capital.
narg.capitalize!
log :info, "-- #{@addr}:#{@port}: #{narg} is trying to connect."
### valid name found. We should create their player now.
text_to_socket "Thank you." + ENDL
# see if the player exists in the database
player_definition = Player.first({:name=>narg.downcase.capitalize})
if !player_definition
### If a new player is not found we need to create a new one.
log :info, "-- #{@addr}:#{@port}: #{narg}: New Character."
@player = Player.new
@player.name = narg.downcase.capitalize
# prepare for next step
text_to_socket DONT_ECHO
### This will loop until both passwords match.
loop do
text_to_socket "Please enter a new password: "
while !check_pass((parg = Fiber.yield false))
### We could also explain here what constitutes a valid password.
text_to_socket "That's not a valid password. What is your new password#{ENDL}: "
end
### Ask them to reenter their password.
text_to_socket "Thank you. Can you please verify the password?" + ENDL
p2arg = Fiber.yield false
if parg.eql? p2arg
text_to_socket "Passwords match." + ENDL
@player.password = parg.dup
break
else
text_to_socket "Passwords do not match." + ENDL
end
end
text_to_socket DO_ECHO
text_to_socket "Entering character creation." + ENDL
text_to_socket "Enter any key to continue . . ." + ENDL
Fiber.yield false
creation_menu = enter_creation_menu()
creation_menu.resume "" # Start menu system.
### enter creation menu.
loop do
# Break after the creation menu is no longer active.
if !creation_menu.alive?
break
end
if creation_menu.resume(Fiber.yield false)
break
end
end
### End character creation loop
###
log :info, "-- #{@addr}:#{@port}: #{@player.name} successfully created."
else
log :info, "-- #{@addr}:#{@port}: #{narg} player file found."
player_definition.load_from_database # pull extra data from the database and into memory.
# At the time of writing this most things fall into this category.
@player = player_definition
### old player found.
### do this until passwords match.
attempt = 0
text_to_socket DONT_ECHO
begin
log :info, "-- #{@addr}:#{@port}: #{@player.name} password incorrect." if attempt > 0
attempt += 1
if attempt > 3
log :info, "-- #{@ip}: #{@port} has been disconnected for 3 failed attempts for #{@player.name}."
Fiber.yield true
end
text_to_socket "Password: "
parg = Fiber.yield false
end while parg != @player.password
text_to_socket DO_ECHO
text_to_socket "Password matches. Thank you." +ENDL
if (@player = check_reconnect(@player.name)) != nil
@state = :state_reconnect
elsif
@player = player_definition
end
end
@player.socket = self
if @state == :state_reconnect
log :info, "-- #{@addr}:#{@port}: #{@player} has reconnected."
text_to_socket "You take over a body already in use." + ENDL
else
log :info, "-- #{@player.name} has entered the game."
@player.to_room(ROOM_ON_CREATE)
$dplayer_list << @player
end
@state = :state_playing
text_to_socket $motd
@player.execute_command("look");
@player.save_to_database
false
end
@nanny.resume ""
end
def enter_creation_menu
return Fiber.new do
### dump the menu options
### generate the menu each pass.
length = 79
### CREATION TABLE
### To add more creation categories add to this table.
ccmenu =[
{:tag=>'1', :desc=>"race", :data=>CCDEFAULT_DATA, :count=>1, :table=>$ccmenu_element[:menu_race],:question=>"Please choose a race."},
{:tag=>'2', :desc=>"class", :data=>CCDEFAULT_DATA, :count=>1, :table=>$ccmenu_element[:menu_class],:question=>"Please choose a class."},
{:tag=>'3', :desc=>"sign", :data=>CCDEFAULT_DATA, :count=>1, :table=>$ccmenu_element[:menu_signs],:question=>"Under which sign were you born?"},
{:tag=>'4', :desc=>"traits", :data=>CCDEFAULT_DATA, :count=>3, :table=>$ccmenu_element[:menu_traits],:question=>"Please pick 3 traits."},
{:data=>"".ljust(length-2, "-")}, ### This line has no way of accessing it but the data still will be printed.
{:tag=>'q', :desc=>"quit"}]
### At this point we should enter our menu driven system.
loop do
buf = "#w" + "#W________________________".ljust(length, '_') + ENDL
buf << "#w" + "#W___#BCHARACTER CREATION#W___".ljust(length, '_') + ENDL
ccmenu.each do |main_menu_option|
t = ""
### Each m is a map
t << "%3s)" % main_menu_option[:tag] + " " if main_menu_option[:tag] != nil
t << main_menu_option[:desc].o_ljust(18) + " " if main_menu_option[:desc] != nil
### Depending on the type of data we may do something different with it.
### Type String: Print it
### Type Array: Print on each line.
if main_menu_option[:data] == nil
buf << "#W=" + t.o_ljust(length-2) + "#W=" + ENDL
elsif main_menu_option[:data].is_a? String
tmp = main_menu_option[:data]
if tmp.eql? CCDEFAULT_DATA
t.insert(0, "#R")
else
t.insert(0, "#W")
end
t << tmp
buf << "#W=" + t.ljust(length-2) + "#W=" + ENDL
elsif main_menu_option[:data].is_a? Array
datum = main_menu_option[:data]
if datum.length == 1
t << main_menu_option[:table][datum[0]][:name]
buf << "#W=" + t.ljust(length-2) + "#W=" + ENDL
next
end
t.gsub!(" ", "_")
buf << "#W=" + "#W" + t.o_ljust(length-2, '_') + "#W=" + ENDL
datum.each do |e|
### For each element in the array dump an explaination on its own line.
tmp = main_menu_option[:table][e][:desc].dup
tmp_n = main_menu_option[:table][e][:name]
ccc = 0
while !tmp.empty?
if ccc == 0
buf << "#W= " + " #C#{'%-20s' % tmp_n}#C " + tmp.pop_some(length-4-22).ljust(length-4-22) + "#W =" + ENDL
else
buf << "#W= " + "#C" + tmp.pop_some(length-4).ljust(length-4) + "#W =" + ENDL
end
ccc += 1
end
end
end
end
buf << "#W"+ "==[#{Time.now.strftime("#R%I:%M%p#w")}#W]==".rjust(length, '=') + ENDL
text_to_socket buf
text_to_socket "Please make a selection:"
# receive input for menu.
argselect = Fiber.yield false
### parse the options and see if any match
menufound = nil
ccmenu.each do |v|
next if v[:tag] == nil
if argselect.eql? v[:tag].downcase
### And this is ugly because each field has a totally different check against the parameter.
### We're trying to streamline it based on how many options and the table of options.
menufound = v
end
end
if menufound == nil ### This means the user option was not found on the menu.
text_to_socket "That is not a valid option." + ENDL
else
### We found The key
if menufound[:tag].eql? "q"
### This is the quit option. Special case for this since it is for breaking the loop.
### Check to see if every condition is met.
all_cond_met = true
ccmenu.each do |check_each|
next if check_each[:tag] == nil || check_each[:data] == nil
if !check_each[:data].is_a?(Array)
all_cond_met = false
break
end
if check_each[:data].length != check_each[:count]
all_cond_met = false
break
end
end
if !all_cond_met
text_to_socket "All conditions are not met." + ENDL
text_to_socket "Enter any key to continue . . ." + ENDL
Fiber.yield false
else
text_to_socket "Thank you. All conditions are met." + ENDL
text_to_socket "Enter any key to continue . . ." + ENDL
Fiber.yield false
### convert the data we mined into data on the Player structure.
ccmenu.each do |elem|
case elem[:desc]
when "race" then @player.race = elem[:data][0]
when "class" then @player.clas = elem[:data][0]
when "traits" then @player.traits = elem[:data].dup
when "sign" then @player.sign = elem[:data][0]
end
end
break
end
else ### Otherwise figure out which table we're using and let them select a certain number of options.
### First clear the data
menufound[:data] = []
print_menu_options(self, menufound)
loop do ### print the current menu and its selections.
if menufound[:data].length != 0
text_to_socket "#W".center(length, '_') + ENDL
text_to_socket "#W__#BYOUR #{menufound[:desc].upcase}#W".ljust(length, '_') + ENDL
text_to_socket "= Empty".ljust(length-2) + " =" + ENDL if menufound.empty?
menufound[:data].each do |mmm|
text_to_socket "= " + menufound[:table][mmm][:name].ljust(length-4) + " =" + ENDL
end
text_to_socket "#W= " + "".center(length-4, '=') + " =#n" + ENDL
end
break if menufound[:data].count >= menufound[:count]
text_to_socket menufound[:question] + ENDL
text_to_socket ">>>"
argselect = Fiber.yield false ### Accept input
### Match argselect against menufound[:table] values
mfound = false
menufound[:table].each do |k, v|
if argselect.eql?(v[:name].downcase) && !menufound[:data].include?(k)
### we found a valid object. We should add the key to the data.
menufound[:data] << k
mfound = true
break
end
end
next if mfound == true
text_to_socket "That is not a valid selection." + ENDL
text_to_socket "Enter any key to continue . . ." + ENDL
Fiber.yield false
print_menu_options(self, menufound)
end
end
end
end ### MENU LOOP
end ### Entire thing in a fiber returned.
end
end