Search code examples
socketslualuasocketmoai

Moai: Graphics that reacts to commands via Sockets


I need a program that can create pre-defined shapes on screen according to that commands I send to it via TCP. I'm trying to listen to a port and so that I can use them. Before waiting of a command (via network) I have the commands required to create a square (I plan to change its attributes via network commands)

The problem is it is not creating any graphics or opening the window as it should be..

require "socket"
require "mime"
require "ltn12"

host = "localhost"
port = "8080"
server, error = socket.bind(host, port)
if not server then print("server: " .. tostring(error)) os.exit() end


screen=MOAISim.openWindow ( "test", 640, 640 )

viewport = MOAIViewport.new (screen)
viewport:setSize ( 640, 640 )
viewport:setScale ( 640, 640 )

layer = MOAILayer2D.new ()
layer:setViewport ( viewport )
MOAISim.pushRenderPass ( layer )

function fillSquare (x,y,radius,red,green,blue)
a = red/255
b = green/255
c = blue/255
MOAIGfxDevice.setPenColor ( a, b, c) -- green
MOAIGfxDevice.setPenWidth ( 2 )
MOAIDraw.fillCircle ( x, y, radius, 4 ) -- x,y,r,steps
end
function onDraw (  )

fillSquare(0,64,64, 0,0,255)
end

scriptDeck = MOAIScriptDeck.new ()
scriptDeck:setRect ( -64, -64, 64, 64 )
scriptDeck:setDrawCallback (    onDraw)


prop = MOAIProp2D.new ()
prop:setDeck ( scriptDeck )
layer:insertProp ( prop )


while 1 do
   print("server: waiting for client command...")
   control = server:accept()
    command, error = control:receive()
    print(command,error)
    error = control:send("hi from Moai\n")

end

It is waiting of the command from client at control = server:accept() but it is not opening up the graphics window as it should.. Is there any command to force it to open or render

Thank you


Solution

  • MOAI doesn't run your scripts in a separate thread. A blocking call (server:accept) or forever loop (while true do) will block your MOAI app and it will appear to freeze while it merrily sits in your script forever.

    So you have to do two things:

    1. Use non-blocking calls. In this case, you need to set your server's timeout to 0. That makes server:accept return immediately. Check it's return value to see if you got a connection.
    2. Put your while loop in a coroutine and yield once per iteration.

    You'll need to handle the client the same way, using non-blocking calls in a coroutine loop.

    function clientProc(client)
      print('client connected:', client)
    
      client:settimeout(0) -- make client socket reads non-blocking
    
      while true do
        local command, err = client:receive('*l')
        if command then 
          print('received command:', command) 
          err = client:send("hi from Moai\n")
        elseif err == 'closed' then
          print('client disconnected:', client)
          break
        elseif err ~= 'timeout' then
          print('error: ', err)
          break
        end
        coroutine.yield()
      end
      client:close()
    end
    
    function serverProc()
        print("server: waiting for client connections...")
    
        server:settimeout(0) -- make server:accept call non-blocking
    
        while true do
            local client = server:accept()
            if client then
                MOAICoroutine.new():run(clientProc, client)
            end
            coroutine.yield()
        end
    end
    
    MOAICoroutine.new():run(serverProc)