This chapter covers the latest updates and changes made to the Table Realms Lua IDE. The releases are ordered as per descending chronological order.
GetEpoc date from a calender. Previous it would return the current epoc not that Calendars epoc.FindChildrenByName(name))GetProfileImage this leads to some games loosing the profile image when rapid scanning between. We have placed the profile image into a static cache and used the known one as we reload any newer ones. This was also copied from the original bundle into the new bundle.GetBase64OfImage from lua but the image name you send is not in the asset cache. It now returns null if the image can not be found.Unfortunately due to extreme pressure notes were not kept for releases 18-22. We will try recapture these here in as much detail as can be rebuilt.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | PanelScrolling.lua |
This now respects insets.
We have added a new global flag SERVER if true the Lua is executing in a server environment. This is true even if the code is executing in a embedded server environment on the client.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Page.lua, Component.lua |
Components now have a function to update when a page becomes visible.
function Component:PageShown()
This can be extended for components to do preparations before display if need be.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
The following two functions were added. The enable the pushing of the current page and changing to a new one so the destination page can pop back to the page. This is handy for screens that are reused from various places.
PushAndSetPage will remember the current page and move to another. You can push more then one time and pop back.
function PushAndSetPage(pageName)
Restore last page we were pushed from.
function PopAndSetPage()
Clear the current page stack back to nothing. You only need this if you know you plan to abort the stack for some reason.
function ClearPageStack()
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
Two new model change listeners have been added. These take a Lua pattern as apposed to a fixed pattern name. This is called now automatically by Label and Button when we have nested keys.
"${player.${currentPlayerId}.name}"
The lua keys for the above are
"currentPlayerId"
"^player%..*.name$"
the first is a simple direct model value and will place a standard model listener. The second places a pattern listener. This way if either changes the label/button will update it’s display.
function AddPatternModelListener(itemName,functionToCall)
function RemovePatternModelListener(itemName,functionToCall)
Additionally to support these changes the following functions were also modified.
Find model keys will return nested keys as shown above. It automatically converts a key with a sub key into a suitable pattern for Lua to test with.
function FindModelStringKeys(text)
Replace model keys will now perform nested key replacement. This means you can construct a key from sub-keys all in the string and the correct value will be shown.
function ReplaceWithModelStrings(text)
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
Additional management functions for online storage were added. The current back-end does not yet divide the storage data into these groups but the interfaces manage the distinction for now.
This will add a set of new keys to maintain online.
Loads a online set of parameters and adds them to the model then calls the callback function this sets name.
| Parameter | Detail |
|---|---|
setName |
The name of this set of keys |
onlineKeys |
The array of the online keys to add |
callBack |
The callback to be called when these keys have been loaded |
function DefineOnlineModelKeys(setName,onlineKeys,callBack)
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Page.lua |
We have added hook functions for pages when they show or hide. This is useful to make adjustments just before a page shows or just after it is hidden.
The hook function will be passed the page being show or hidden.
function Page:AddShowHook(showFunction)
function Page:AddHideHook(hideFunction)
| Name | Detail |
|---|---|
| Package: | components.twitter |
| Files: | TwitterSearch.lua |
This is a native component extension that shows a twitter search view. It will show you the results of the search with either dar or light themes.
| Name | Detail |
|---|---|
| Package: | components.youtube |
| Files: | YourTubePlayer.lua |
This is a native component extension that shows a you tube player in the application. The native viewer can be configured to auto play and to allow full screen interaction.
A new function was added to GeneralInformation to return put the players profile image into the image cache.
environment:GetProfileImage("profileImage")
When an attempt to draw a missing image is made that attempt just returns. Previously there was an exception that stopped the Lua from continuing.
In dark theme some color changes were made for readability. The console input block now honors the editor theme.
It was discovered that Android 7 had very poor connection handling. The socket defaults differ to those of android 8 and have been configured manually. The stability is not much improved.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Button.lua |
Added the same behavior to the Button as Label so now we have the ability to embed model data into the strings and it will automatically update.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Page.lua |
Added a new value to page that allows the passthrough of touch events to an embedded web view.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
Main was moved to -4 in package order.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | FlagsManagement.lua |
A small script to split Global model flags up into parts and set them in the environment.
A new dark theme has been added to the UI Dark theme. This can be changed in the settings window opened from the file menu.
There was a bug introduced when we fixed the updating of the component values. This has been resolved although the page will only rebuild when you click off it and back on. More resolution for the rebuilding should still be done.
To implement correct flags handling we have had to make a few changes to various places. The flags are all managed in the Controller Model now those from the URL and those specified from the Global FLAGS variable as well as any added manually in the Lua code.
Added a new method to the GeneralInterface
/**
* This is where flags are added to the solution from Lua. The Lua main code should identify the FLAGS global
* set from server break it apart on "," and send each part to this method.
*
* Flags need to be set in time to be effective. Each flag has different rules for this. Flag that need to be
* set right early must be done so through the URL rather as thsoe are set before anything happens.
*
* @param flagDetails an individual flag to be set.
*/
public void AddFlag(String flagDetails);
Made the following change to the WebView
webSettings.setDomStorageEnabled(true);
This allows the dom storage API to function. For come WebView application this may be a performance boost.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | TouchPassthrough.lua |
Fixed a typo in the definition of the component params.
Also fixed the x,y coordinates on the Touch and Release events to be modified, before they were just sending the raw x,y.
Added a Multi Touch checkbox on the component that defaults to true. This defaults to true.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | PanelHorizontal.lua |
Changed the one layout option from saying Fixed % Width to saying Fixed % Height also corrected the mathematical code to multiply by this factor first then divide by 100.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Button.lua |
To make button more flexible we added a new method to set the script after runtime. This is needed as the current function is compiled during new so if you modify the script it will not recompile. So to set a button script you must call.
function Button:SetScript(script)
script: the new script string.| Name | Detail |
|---|---|
| Package: | components |
| Files: | PanelVerticle.lua |
Changed the one layout option from saying Fixed % Height to saying Fixed % Width also corrected the mathematical code to multiply by this factor first then divide by 100.
Arguments in Lua have now been moved to been accusable during the compile phase. This was need as the initial compile really needs to set up things like instanceId from the arguments.
Various changes to the ModelController for the Lua histed stuff, fixing some threading issues and making it more resilient.
The ControlerModel has an added method to ConectionListerner. This is called just before the compilation. This allows for the creation of the Asset Cache (needed for some of the image functions) before the compilation of the Lua code.
BUG: When a number is passed from one Lua instance to another via the global model the type of double reverts to a string type.
When a component value is of type boolean and that component was added to a page. As can be seen with Label for example. The default value suggested for the component is not set. This has been fixed now to provide the correct Boolean default value.
There has been a bug in the solution where often values changed in a form do not save and it takes a few iterations of back and forth to resolve them. This is in fact a technical issue due to various threaded event listeners and race conditions.
After removing the unnecessary beanIntoGui in the changes and additionally making changed only update fields if there was in fact an alteration we have removed many of the race conditions.
It remains possible that there are some situations where the save does not happen. If any are seen please try recreate them and let us know the pattern that makes this happen.
| Name | Detail |
|---|---|
| Package: | players |
| Files: | Players.lua |
Added a new list for players playersOrdered it is a normal array of all players. To order in this array is guaranteed to be the same in all players environments.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Panel.lua, Component.lua |
Added the functions needed for Panel to return the component that matches SELECTED_ITEM_ID this will also evaluate the actual panel. The return is done as part of Paint this is required for performance as this is when graphics is available.
Component has a new method PaintSelected(graphics) this can be overrides if needed to add your own information to components that only shows in design mode. This is called last so it will pain over any children that might also render.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Label.lua |
Label now allows the text binding of model data into the label. For example there is a model.name this is generally the current players handle. If you wanted to greet this player by name you can set the label text to "Hello ${name}." this will be replaced with "Hello Player.".
Whats more is if the value changes during execution it will update the label and repaint automatically. This means you do not need to repeatedly update the label yourself.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Button.lua |
Button has had it’s disabled render behavior modified. Previously when a button was disabled and had no disabled style it would still render with it’s normal style. This has been changed to hiding the button when disabled if there is no disabled style. This is mor flexible as you can achieve the original behavior by allocating the same style to enabled and disabled. But now to hide the button simply do not give it a style.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | PanelVerticle.lua |
There was a layout bug that didn’t correctly handle self.gap being nil. Also it did not correctly calculate the gap in dp.
Also noticed the incorrect spelling of Vertical. This will need to be refactored one day. Might be able to do it with a temporary facade that remains for a while.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | PanelStack.lua |
There was a feature gap in PanelStack it did not take inset gaps into account correctly. This has been remedied.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
Two new functions were added to assist the labels with model data replacements in strings. Some changes for stability were made to the Paint function.
This will return an array of all the model data keys in the string.
This will only search the first discoverable values. It will not search the returned data from the model for each and then process a second set of keys.
function FindModelStringKeys(text)
text: the string to search for keys in.return: an array of the string keys in the string.This will replace items in the string with items from the model.
For example calling this with "Hello ${name}" will return with
"Hello Bob" assuming the model contains a key, value pair of name=bob. For now values that are not found in the model are replaced with three periods "..." .
function ReplaceWithModelStrings(text)
text: source the string to replace model data in.return: the returned string of model data.| Name | Detail |
|---|---|
| Package: | base |
| Files: | Page.lua |
Page Paint(graphics) was modified to call the PaintSelected(graphics) of the returned item from baseComponent.Paint(Graphics) only if such a method can be found.
We have added a bounding box on screen around the currently selected item in the tree view. This is to make it easier to see where your item falls in the screen display for layout. This required changed to both the base and component packages.
Added the following flags into the model
| Lua Key | Details |
|---|---|
DESIGN_MODE |
This is true if you are running in the designer. Not set at all if not. |
SELECTED_ITEM_ID |
When in the Editor this is the ID of the correctly selected item. Used to display debugging information |
nil/nullChanged have been made to the model management to allow for the sending of nil/null values to essentially remove a key from the model.
So you can set model data to nil in Lua and it will remove from the Lua table and it will remove from the Map on the game/server.
If you set the model data to null in the Game/Server it will remove from the Lua table essentially leaving a nil in it’s place.
This is a HIGH RISK change and it has not yet been implemented in the .js or Unity engines. IT is currently only implemented in the Java Lua hosted solution.
The controller has been updated to correctly flag incoming model data as global in the global set as it arrives from the host.
There was a bug when the model data was causing a callback into Lua and further changed to the mode data would be ignored. This was because there is a flag to prevent recursive updates when adjusting values form the network. The callback was moved to outside this loop so that model data changed in Lua during a callback for model data changed still works.
There was some synchronized data around information that was received from the connection before the Lua was ready to execute. This data was help in a list until the Lua was ready. During setting of data in a callback from Lua this could cause a thread locking issue. Where the thread processing the change synchronized around the list, would block a set from within the change listener that also tried to synchronize around the same list. This was fixed by removing the synchronization after the Lua was ready. Sine this can only happen as a result of a callback and they only occur when the Lua is ready it resolved the issue.
| Name | Detail |
|---|---|
| Package: | players |
| Files: | PlayersUpdatedOnStart.lua |
Some code was moved from players to this file. This was to allow the developer to first add listeners to Add or Remove player functions before we calculate the first set. Previously functions added would not be called on the first calculation of players.
The controller has been updated to correctly flag incoming model data as global in the global set as it arrives from the host.
Making the global data synchronize when changed in one Lua environment to the others was added to the unity implementation.
There was a bug in the implementation of global data. This bug was causing any global data without a ‘.’ in the name to fail to synchronize with the players environments. This in turn was breaking the Player management in Lua.
Making the global data synchronize when changed in one Lua environment to the others was added to the JS implementation.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | TouchPassthrough.lua |
Comments typos fixed
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua, DataStore.lua |
| Changes: | Paint now checks if there is a graphics in the Lua context before performing paint. This was needed after we made the system able to run the camera at the same time as the Lua. A new file with data storage features was added called DataStore.lua |
Use this to add a local data store for model data.
All model data defined here will be saved locally on the device. No effort is made to synchronize this data.
Note:
- All data is simply added to the model, this means all keys need to be unique per model.
- The data loading for local happens right up front. However it will not access the local data until you have added the keys as a set.
function AddLocalDataStore(name, keys)
name: the name of the data store.keys: an array of keys to store locallyUse this to add an online data store for model data. A callback can be added for when it returns. Note only one callback per data-store key will be managed. So if you do more then that it call the last one.
All model data defined here will be saved online against the account holder and the game.
Note:
- All data is simply added to the model, this means all keys need to be unique per model.
- The loading happens asynchronously, you can not immediately assume the data is loaded. That is why a callback was added.
- A current limitation of one DataSet need to be self managed by the developer. This is planned to change.
function AddOnlineDataStore(name, keys, callBack)
name: the name of the data store. Will be passed into the callback.keys: an array of keys to store onlinecallBack: if supplied this method will be called when the keys are loaded.| Name | Detail |
|---|---|
| Package: | players |
| Files: | Players.lua |
| Changes: | Fixed a nil errors when players are added or removed but we have not selected to have any listers. |
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
function AddGlobalKeys(globalKeys)
This function will add the keys delivered to global keys. This means that when shared with the host game from here on the keys will be marked as global.
Global keys are replicated between all devices and the game. Be careful as changes are not synchronized so if you change a global key on two players devices you may end up with an unknown state. It is best to make sure all global keys are only effected in one place.
There is no way to undo the addition of global keys in a session.
globalKeys: an array of keys to add to the global set.Be careful not to add keys you intent to save locally or remotely to a global set. The behavior should you do so is indeterminate from session to session.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Base.lua |
| Changes: | New methods added to assist with the handling of images, qr codes and taking photos. |
This will load an image into the image set from the base64 string provided.
function AddImageFromBase64(imageName, imagebase64)
imageName: the name of the image to be loaded.imagebase64: the base64 encoded string for the image.return: returns the image table or nothing if the load failed.This will encode an image into a base64 string for decoding elsewhere. The encoding format is determined by the encoding type. Default is ‘png’
function GetBase64OfImage(imageName, encodingType)
imageName: the name of the image to be encoded.encodingType: the encoding format desired (‘gif’,‘png’,‘jpg’).return: returns the base64 string or nil if the conversion failed for any reason.function CreateQRImage(imageName, stringToEncode)
This will encode a string value into a QR code and add that coded image to the image library.
imageName: the name of the image to be created.stringToEncode: the string content to be encoded into the image.return: returns the image table or nothing if the encoding failed.function TakePhoto(imageName,callBack)
This will start the process of taking a photo. When the picture is taken or failed it will call back the function supplied.
imageName: the name of the image to be created.callBack: the function to be called when the photo has been completed.function ScanCode(callBack)
This will start the process of taking a photo and resolving the QR code in it. When the QR code has been scanned the callBack will be called.
callBack: the callBack function to call once the code has been scanned. If no function is supplied the ScanCode will do nothing.| Name | Detail |
|---|---|
| Package: | components |
| Files: | Image.lua |
The image component has had a new selection drop down added Render Quality. This allows us to set the quality of rendering for the image.
Main feature added is the player management information for both P2P and Lua to have more information about each player and to know which player the game instance is for.
The Unity plugin has been updated to keep the following global model data up to date. The plugin was pushed at 2019/02/01 09:50. `
| Scope | Key Client | Key In game | Type | ReadOnly | Example | Meaning |
|---|---|---|---|---|---|---|
| Global | players |
players |
string | yes | 5242,34523 | A comma seperated list of player id’s currently connected to the game. |
| Global | player.{id}.name |
player.{id}.name |
string | yes | Fred | Players data shared to all devices |
| Global | player.{id}.state |
player.{id}.state |
string | yes | Connecting | Players data shared to all devices |
| Global | player.{id}.loaded |
player.{id}.loaded |
float | yes | 0.5 | Players data shared to all devices |
| Global | player.{id}.color |
player.{id}.color |
any | no | (by design) | Players data shared to all devices |
Because of these changes all the above model data will be available in the hosts and clients. The set of data player.{id}.{term} is flexible and as a game developer you can add to this model data for anything you want shared between all Lua clients and all the game instances.
Additionally the Unity Table Realms plugin code now intercepts the model.yourid update and sets it in TableRealmsGameNetwork.instance.yourid this is for games to know which player there game is running on.
These changes should not specifically effect the emulator as it can not be used for P2P testing.
P2P now sends the id for each device to the game that players is seeing. In embedded mode that is to the WebGL game hosted inside the application. This id goes through the model as yourid but is handled by each engine differently.
At time of writing this changes need to still be implemented separately in the Android application, these changes will only work with the correct application.
A new Lua package players has been added. This package is some helper functions for player management.
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Utils.lua |
Added a function to assist with splitting strings string.split. It can be used as follows.
local str="Items,More,OtherThings"
local items=string.split(str,',')
print(table.tostring(items))
-- output
{
"Items",
"More",
"OtherThings"
}
| Name | Detail |
|---|---|
| Package: | base |
| Files: | Main.lua |
Main.lua was moved to order -5 this was to make room for the new players package to be before 0 but after Main.lua. This means a new version of the base libraries should be imported before player.
| Name | Detail |
|---|---|
| Package: | players |
| Files: | Players.lua |
Players.lua introduces a few new functions to assist with player management. In particular it listened to changes to model.players and then breaks those changes into players leaving and joining the game. Calling callbacks for each event.
AddPlayersAddedListener(function(playerId)
print("Added Player:" .. playerId)
end
)
AddPlayersRemovedListener(function(playerId)
print("Removed Player:" .. playerId)
end
)
| Name | Detail |
|---|---|
| Package: | base |
| File: | Main.lua |
Two errors fixed causing nulls to report when certain conditions were not met in the Main function. This happened when the screen was pressed but no suitable page was in fact selected.
| Name | Detail |
|---|---|
| Package: | components |
| Files: | Thumbstick.lua and ThumbstickDrawn.lua |
There was an error on releasing where the incorrect parameters were being sent to update causing the thumbstick to lock down.
| Name | Detail |
|---|---|
| Package: | components |
| File: | TouchPassthrough.lua |
A new component that passes the touch events to the game. There is some comments in the component on how to implement it in the engine.
To facilitate better behavior I have made the following improvement to the way model data for doubles is handled. Previously that data is only shipped every 60ms this was to slow down the impact of multiple touch events saturating the network. I have changed this to send the double values if they were sent previously within 60ms immediately if not they will be cached and send on the 60ms timer. This means that the touch values for the touch component will always update just before the action for touch is sent preventing us from having a zero issue. This would also solve the issues we had previously with colors in Dashpop.
This new library needs to be compiled into the test version of the Table Realms android device.