Jump to content
  • entries
    943
  • comments
    5,899
  • views
    923,763

Louie, Lua


Josh

4,036 views

 Share

Below is raw output from the Lua debugger. It displays all variables, tables, and functions in the Lua script call stack. This will be displayed in a nice treeview interface that looks much better, but I found this terribly exciting.

 

You'll notice that tables don't get expanded, even though I have the ability to display all the values in a table. The reason they don't get expanded is because tables can contain tables, including tables that might be found elsewhere in the program. This can easily cause an infinite loop of tables leading to tables leading to tables. This is why the Lua debugger must be a networked program that talks to the running process. When the user opens a treeview node to view the contents of that table, the main program will return all the values in the table so you can view them, but not before.

>Starting interpreter...

>Script is running...

>An error has occurred!

>[Level 0]

>{

>source: @test.lua

>short_src: test.lua

>linedefined: 0

>lastlinedefined: 0

>what: main

>currentline: 22

>namewhat:

>nups: 0

>locals:

>a = 2

>b = 3

>mytable = {}

>[Level 1]

>{

>source: @test.lua

>short_src: test.lua

>linedefined: 15

>lastlinedefined: 20

>what: Lua

>currentline: 19

>name: dostuff

>namewhat: global

>nups: 0

>locals:

>test = dog

>[Level 2]

>{

>source: =[C]

>short_src: [C]

>linedefined: -1

>lastlinedefined: -1

>what: C

>currentline: -1

>name: RuntimeError

>namewhat: global

>nups: 2

>locals:

>}

>}

>}

>Globals:

>string = {}

>package = {}

>os = {}

>io = {}

>someglobaltable = {}

>someglobalvalue = hello!

>debug = {}

>math = {}

>table = {}

>coroutine = {}

>_G = {}

>_VERSION = Lua 5.1

 

Here's what the Lua script looks like:

print("Script is running...")

local a = 2
local b = 3

someglobalvalue = "hello!"
someglobaltable = {}

local mytable={}
mytable.color = "red"
mytable.mood = "happy"
mytable.subtable = {}
mytable.subtable.n = 9

function dostuff()

local test = "dog"
RuntimeError("An error has occurred!")
end

dostuff()

 

This will allow you to examine the entire contents of the virtual machine of any Leadwerks Engine 3 program built with debugging enabled, regardless of what language the main loop is coded in. The Lua implementation in Leadwerks Engine 2 was well-received, but we found in advanced programs we needed better tools to debug and analyze scripts. The script debugger in Leadwerks Engine 3 will make everything perfectly transparent so you can easily identity and fix problems. It also gave me a start on networking, because networking commands were needed to set this up.

 

My plan for the networking API is to have commands for sending raw data with a message id:

bool Send(const int& message, Bank* data=NULL, const int& channel=0, const int& flags=MESSAGE_SEQUENCED)

 

As well as a few game-oriented commands to easily set up basic behavior:

bool Say(const std::string& text)
bool TeamSay(const std::string& text)
bool Join(const int& team)

 

The real magic is the entity syncing, which handles networked physics and makes it so any command you call on the server affects the corresponding entities on all clients. If you call entity->SetColor(1,0,0) to make an object red, it will turn red on all clients. I've tested an earlier prototype of this, and it worked well, even across continents. This makes network programming fairly easy, and a lot of fun.

 

I'd really like to have a simple open-source tournament shooter game the whole community can play around with. Only by building a good networking base with a high-level entity syncing system does this become convenient and easy to modify.

 

http://www.youtube.com/watch?v=7Vae_AkLb4Q

 

---------------------------------------------------------------------------------------

 

And here's the debug output displayed in a tree view. The tables each get one blank child node, and when the user expands the table, the debugger will send a request for that table's data:

blogentry-1-0-55017500-1304546993_thumb.png

 Share

15 Comments


Recommended Comments

Very nice, Josh. Better debugging is a great enhancement to the LUA integration also the easier entity network handling is great news as well. Networking is something that I can use very so since our current project, Grim, is going to have online multiplayer modes.

Link to comment

Are these commands going to be able to not be network synced if we so want? There might be instances where I only want my local client to turn red.

 

Also, are you looking at coroutines yet in Lua? I think coroutines are a must as it gives an amazing way to program sequence of events from Lua. It would allow for cutscene style programming.

Link to comment

NOTE: I should use wstrings for the game oriented commands. French people (and others) will not be happy with the multibyte character set :).

Link to comment

I'm VERY excited about the network support!! It sounds like it'll work exactly how I was hoping it would!

 

I would also love the option to not include an entity in the network.

NetworkEntityExclude(Entity);

or something.

Link to comment

To make an entity appear on all clients, you would call this:

entity->Sync(server)

 

That entity will be sent to all clients, and whatever happens on the server is reflected on all clients.

 

Entities within maps get a little tricky. You'll have stuff like a door you put in the scene you will want the server to control. I am thinking we'll have a checkbox that makes an entity in a map networked when checked.

 

Partial syncing of a single entity isn't possible; the server controls synced entities, and a given entity is either synced or it isn't.

Link to comment

What's sync'd about an entity? Postion, rotation, scale? Anything else? There is generally more to what you'd want sync'd than that. Ammo count, health, etc. These are generally things that would be stored in a class. If we wanted to use this syncing method you have would we have to use entity keys for this data and have that get sync'd?

Link to comment

What's sync'd about an entity? Postion, rotation, scale? Anything else? There is generally more to what you'd want sync'd than that. Ammo count, health, etc. These are generally things that would be stored in a class. If we wanted to use this syncing method you have would we have to use entity keys for this data and have that get sync'd?

Position, material, color, keys, etc. One way to sync info would be using entity keys. As far as syncing entire classes, the best bet is to send a raw data packet.

Link to comment
Guest Red Ocktober

Posted

yes... the networking sounds like it's right on the money...

 

so if if i understand this, say i instantiate an object in a multiplayer game, and the class update method contains entity->sync... then it'll reflect the current location, orientation, etc on all clients?

 

if so... super cooool...

 

--Mike

Link to comment

You only need to call sync once, and thereafter it is automatic:

 

Entity::Sync(Server* server);

 

Then you can do whatever you want, even delete the entity, and it will be automatically updated in regular intervals.

Link to comment

The deletion seems interesting. Will we be informed in any way of this deletion or would we have to pull from inside our classes that contain these entities to check them against null?

 

For that matter the creation also seems interesting. How will clients be informed of this? A model entity is just another piece of data that your "Player" class would have just like it's name or health. So you would want more than just the model entity to be created remotely, you would want the "Player" class to be created, but since this model piece is a variable inside the overall "Player" class, it seems the 2 would have to happen at the same time. I feel like a callback would be required to inform the client that an entity is being created on it so we can then create an instance of the proper class and store the LE entity inside it.

 

The reality is, from my side and I know others, LE entities don't stand alone. They are generally nested as objects inside a class that describes everything about a game object. A game object is more than just it's model entity. So I want to make sure when a client gets an entity ghosted on it, we have a chance to know about this so we can assign it to these greater game object classes.

 

Will that be the case?

Link to comment

It should appear in a message, where the message ID is something like MESSAGE_CREATEENTITY and an extra parameter gives you the entity that was created.

Link to comment

Like a network message or an entity message? I assume network message since entity messages are tied to already created entities. That would mean we will get a network message callback that we can hook into for all LE network messages coming and going? That would be nice.

Link to comment

Something like that. Right now it is like this:

Message* Client::Update(const int& timeout=0)

 

But a callback might be added, or you can add your own and run this command on a separate thread.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...