ChatdServerClientExample: Difference between revisions

From Arianne
Jump to navigation Jump to search
imported>Hendrik Brummermann
m cat
imported>Hendrik Brummermann
m cat
(No difference)

Revision as of 14:17, 20 February 2010

The information on this page is mainly outdated. You can find a draft version of client/server chat example based on Marauroa 2.5 at ClientServerChatExample.

A very simple example for you, the lazy reader, who can't be bothered to read the manual!
But note, this example is by no way a substitute of HowToWriteGamesUsingArianne and it is only intended for readers that want a light introduction to Arianne.

Server

First we create the server class using python.

import marauroa.game.python.PythonRP

class ChatServer(marauroa.game.python.PythonRP):
  def __init__(self, zone):
    self._zone=zone
    self._removeAttributes=[]

  def execute(self, id, action):
    result=0
    player=self._zone.get(id)
    action_code=action.get("type")

    if action_code='chat':
      player.put('text',action.get('text'))
      self._zone.modify(player)
      self._removeAttributes.append(player)
      result=1

    return result

  def nextTurn(self):
    for player in self._removeAttributes:
      if player.has('text'):
        player.remove('text')
        self._zone.modify(player)

  def onInit(self, object):
    self._zone.add(object)
    return 1

  def onExit(self, objectid):
    self._zone.remove(objectid)
    return 1

  def onTimeout(self, objectid):
    return onExit(self,objectid)

Ok, most of it is just trivial stuff. The core code is at execute and nextTurn.
The execute method is the one called to execute the actions the client sends and it is really simple, it adds the messages content as a player attribute, and the trick thing is that is add the player a list so that it can be deleted the attribute in the next turn.

The nextTurn just delete the attributes that now are useless.

Client

The client is a bit more complex. We need to make it login and choose a character. We will use a curses wrapper for python. TODO: Improve it

import pyarianne
import curses
import os
import time
import signal
import sys

def sendMessage(lines):
    text = ""
    for i in lines:
      text = text + i + "\n"
    action=pyarianne.RPAction()
    action.put("type","chat")
    action.put("content",text)
    pyarianne.send(action)


def paintStatusArea(text):
    statusArea.clear()
    statusArea.border()
    statusArea.addstr(1,1,text)
    statusArea.refresh()

def paintTextArea(history_lines):
    textArea.clear()
    textArea.border()
    textArea.addstr(0,3," The first marauroa-python-curses-chat client ")
    row=1
    for line_entry in history_lines:
      name = line_entry['name']
      text = line_entry['text']
      name = name.rjust(16)+": "
      textArea.addstr(row,1,name,curses.color_pair(1))
      textArea.addstr(text,curses.color_pair(2))
      row=row+1
    textArea.refresh()

def paintInputArea(text):
    inputArea.clear()
    inputArea.border()
    inputArea.addstr(1,1,">"+text)
    inputArea.refresh()
def repaintInputArea():
    global text
    paintInputArea(text)

def dostuffonCallback():
    if False:
       winmain.addstr(0,0,"Calling from Python!")

def printChatMessage(world):
    global history_lines
    if True:
       for i in world.objects:
         if world.objects[i].get("type") == "character":
            name = world.objects[i].get("name")
            if world.objects[i].has("?text"):
               text = world.objects[i].get("?text")
               text_lines = text.split("\n")
               for line in text_lines:
                   if line != "":
                      history_lines.append({'name': name,'text': line})

               #if overflow - remove first element
               while len(history_lines) > 18:
                  history_lines.pop(0)

               paintTextArea(history_lines)
               repaintInputArea()


def initCurses():
    stdscr = curses.initscr()
    curses.noecho()
    curses.cbreak()
    stdscr.keypad(True)
    stdscr.nodelay(True)
    if curses.has_colors():
       curses.start_color()
       curses.init_pair(1, curses.COLOR_BLUE,   curses.COLOR_BLACK);
       curses.init_pair(2, curses.COLOR_GREEN,  curses.COLOR_BLACK);
       curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK);
       curses.init_pair(4, curses.COLOR_RED,    curses.COLOR_BLACK);
       curses.init_pair(5, curses.COLOR_CYAN,   curses.COLOR_BLACK);
       curses.init_pair(6, curses.COLOR_MAGENTA,curses.COLOR_BLACK);
       curses.init_pair(7, curses.COLOR_WHITE,  curses.COLOR_BLACK);
    return stdscr

def uninitCurses(sign,arg2):
    signal.signal(sign, signal.SIG_IGN)
    try:
      curses.nocbreak()
      stdscr.keypad(0)
      stdscr.nodelay(0)
      curses.echo()
      curses.endwin()
      print "Exiting by signal "+ str(sign)
    except err:
      print "Exception: " +str(err)
    sys.exit(0)
stdscr = initCurses()

#register singal handler to be able to restore the console
signal.signal(signal.SIGINT,  uninitCurses)
signal.signal(signal.SIGTERM, uninitCurses)

begin_x = 0 ; begin_y = 0
height  = 20 ; width = 100
textArea = curses.newwin(height, width, begin_y, begin_x)

begin_x = 0 ; begin_y = 20
height  = 3 ; width = 100
inputArea = curses.newwin(height, width, begin_y, begin_x)
inputArea.keypad(True)
inputArea.nodelay(True)

begin_x = 0 ; begin_y = 23
height  = 3 ; width = 100
statusArea = curses.newwin(height, width, begin_y, begin_x)

world=pyarianne.World()
perceptionHandler=pyarianne.PerceptionHandler()
pyarianne.setIdleMethod(dostuffonCallback)
pyarianne.connectToArianne("marauroa.ath.cx",3214)
paintStatusArea("Connecting to server...")
text = ""
history_lines = []
if pyarianne.login("root777","root777"):
    chars=pyarianne.availableCharacters()
    paintStatusArea("Logged in, choosing character "+chars[0]+"...")
    if pyarianne.chooseCharacter(chars[0]):
        paintStatusArea("Choosed character "+chars[0])
        exit = False
        repaintInputArea()
        while True:
            time.sleep(0.2)
            if pyarianne.hasPerception():
                perception=pyarianne.getPerception()
                perceptionHandler.applyPerception(perception, world)
                printChatMessage(world)

            ch = inputArea.getch()
            if ch != curses.ERR :
               if ch == 10 or ch == curses.KEY_ENTER: #enter
                  if text == "/quit":
                     break
                  if text != "":
                     sendMessage([text])
                  text = ""
               else:
                  text = text + str(chr(ch))
               repaintInputArea()
        pyarianne.logout()
    else:
        paintStatusArea("CAN'T CHOOSE: "+pyarianne.errorReason())
else:
    paintStatusArea("CAN'T LOGIN: "+pyarianne.errorReason())

paintStatusArea("Finishing pyclient")
uninitCurses(1,2)

And here you can see how it looks:

Chat Client Screenshot