# # This file handles the Unicron protocol. It is used by both client # and server. # global handle_char # a client procedure; leave null for server class Commands(commands) #extract user command from user input method GetCommand(datagram) local l if not (l:=find(" ", datagram)) then l:=*datagram return datagram[2:l] end #validate command and service it method ExecuteCommand(L, Sockets, Users, buffer, i) local UserCmd, g if IsCommand(buffer) then { UserCmd := GetCommand(buffer) if ValidCommand(UserCmd) then { case UserCmd of { "say": ForwardMessage(L, Users, Sockets, buffer, i) "afk": Sockets[L[i]].afk := 1 "back": Sockets[L[i]].afk := 0 "emote": g:=1 # not sure what this is supposed to do yet "ignore": UpdateIgnoreList(L, Users, Sockets, buffer, i, 1) "noignore": UpdateIgnoreList(L, Users, Sockets, buffer, i, 2) "who": who_is_on(L, Users, Sockets, buffer, i) "sysop": PublicAnnouncement(L, Users, Sockets, buffer, i) "quit!": SimplexMessage(L, i) "tell": DirectedMessage(L, Users, Sockets, buffer, i) default: write("Command not implemented yet.") } } else fail } else fail end # this kind of message goes to the # server executes some server side code # and then it return to the sender to # complete the request. Perfect example: quit! method SimplexMessage(L, i) # nothing on the server side yet write(L[i], "\\quit! now") end # directed message goes from user to user method DirectedMessage(L, Users, Sockets, buffer, i) local l, recipient, sender, message, x, args sender := Sockets[L[i]] args := GetMessage(buffer, 7) # no message if not (l:=find(" ", args)) then { write(L[i], "\\say No message. Bad Syntax. Try Again. Usage: tell user message") return } recipient := args[1:l] write("recipient " || recipient) # no message? message := args[l+1:*args+1] write("message " || message) if *Users > 0 then { every x := 1 to *Users do { if Sockets[Users[x]].uid == recipient then { write(Users[x], "\\say " || message) return } } } write(L[i], "\\say no such user is online") end #delete user from server & close conection method DeleteUser(L, Sockets, Users, i) local n, Xuser close(L[i]) Xuser := Sockets[L[i]].uid delete(Sockets, L[i]) every n := 1 to *Users do { if L[i] === Users[n] then{ delete(Users, n) break } } write("Deleted user ", Xuser, " at ", &dateline, "\nNumber Users: ", *Users, "::" , *Sockets) end method UpdateIgnoreList(L, Users, Sockets, buffer, i, switch) local sender, user_to_ignore, n sender := Sockets[L[i]] if switch == 1 then { user_to_ignore := GetMessage(buffer, 9) # check to see if user already in the ignore list if sender.isIgnored(user_to_ignore) == 1 then { put(sender.IgnoreList, user_to_ignore) write(L[i], "\\say sysadmin " || user_to_ignore || " is being ignored.") } else write(L[i], "\\say sysadmin " || user_to_ignore || " already being ignored.") } else { user_to_ignore := GetMessage(buffer, 11) # check to see if user already in the ignore list if sender.isIgnored(user_to_ignore) == 1 then { write(L[i], "\\say sysadmin " || user_to_ignore || " not being ignored from the first place.") } else { if *(sender.IgnoreList) > 0 then { every n := 1 to *(sender.IgnoreList) do { if sender.IgnoreList[n] == user_to_ignore then { delete(sender.IgnoreList, n) break } } } write(L[i], "\\say sysadmin " || user_to_ignore || " not being ignored anymore.") } } end method who_is_on(L, Users, Sockets, buffer, i) local x, newbuf, sender sender := "sysadmin" newbuf := "Users Online as of " || &dateline || ": " every x := 1 to *Users do newbuf := newbuf || Sockets[Users[x]].uid || ", " newbuf := "\\say " || newbuf write(L[i], newbuf) end method PublicAnnouncement(L, Users, Sockets, buffer) local x, newbuf, sender sender := "sysadmin" newbuf := "\\say " || sender || ": " || GetMessage(buffer, 8) every x := 1 to *Users do { write(Users[x], newbuf) } end #write message to all other users method ForwardMessage(L, Users, Sockets, buffer, i) local x, newbuf, sender, recipient if *Users == 1 then write(L[i], "\\say No other users connected to talk to.") else{ sender := Sockets[L[i]].uid newbuf := "\\say " || sender || ": " || GetMessage(buffer,6) every x := 1 to *Users do { if not (L[i] === Users[x]) then{ if (Sockets[Users[x]].afk > 0) then write(L[i], "\\say " || Sockets[Users[x]].uid || " is away from the keyboard") recipient := Sockets[Users[x]] if recipient.isIgnored(sender) == 1 then write(Users[x], newbuf) } } } end #get message from user input method GetMessage(datagram, l) return datagram[l:*datagram] end #check to see if message is a command method IsCommand(datagram) if datagram[1] == "\\" then return else fail end #check user command against set of available user commands method ValidCommand(usercmd) return member(commands,usercmd) end #validate command and service it method ClientCommand(net, buffer) local UserCmd if IsCommand(buffer) then { UserCmd := GetCommand(buffer) if ValidCommand(UserCmd) then { case UserCmd of { "say": ClientMessage(buffer,*UserCmd+3) "quit!": Clientquit(net) default: ClientMessage("message processed, no command available",0) } } else fail } else fail end method Clientquit(net) write("Client wants to quit") close(net) end #write out available input for user to read method ClientMessage(buffer,n) if /handle_char then stop("can't call ClientMessage from server") handle_char(1,buffer[n:*buffer+1], "\n") end initially commands := set("afk", "cmd", "course", "disband","door","draw", "emote","enroll","erase","exit","follow","give", "group","hand","ignore","invite","join","kill", "loc","lock","log","login","move","pen","quit!", "say","sound","stop","take","tell","video", "voice","who", "back", "sysop", "noignore") end