Working with WebRTC from fengari lua in the browser...first steps
I decided to create this simple RTCDataChannel example in lua using fengari. The most interesting part of this process was figuring out how to translate the promise-chaining as seen here:
localConnection.createOffer()
.then(offer => localConnection.setLocalDenoscription(offer))
.then(() => remoteConnection.setRemoteDenoscription(localConnection.localDenoscription))
.then(() => remoteConnection.createAnswer())
.then(answer => remoteConnection.setLocalDenoscription(answer))
.then(() => localConnection.setRemoteDenoscription(remoteConnection.localDenoscription))
.catch(handleCreateDenoscriptionError);
I had to create the then, catch, finally functions in addition to the pdo function which starts the chain.
weft.fengari:
js=require('js')
window=js.global
document=window.document
function then(prom,...)
local p=prom['then'](prom,...)
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function catch(prom,...)
local p=prom'catch'
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function finally(prom,...)
local p=prom['finally'](prom,...)
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function pdo(p)
p.then=then
p.catch=catch
p.finally=finally
return p
end
function elevate(from,members)
-- "elevates" table of top level members of a js object (from) into global, for convenience
for , v in ipairs(members) do
ENVv=fromv
end
end
elevate(js.global,{
'console',
'RTCPeerConnection'
})
local connectButton = nil
local disconnectButton = nil
local sendButton = nil
local messageInputBox = nil
local receiveBox = nil
local localConnection = nil -- RTCPeerConnection for our "local" connection
local remoteConnection = nil -- RTCPeerConnection for the "remote"
local sendChannel = nil -- RTCDataChannel for the local (sender)
local receiveChannel = nil -- RTCDataChannel for the remote (receiver)
function handleCreateDenoscriptionError(error)
console:log('unable to create an offer')
end
function handleLocalAddCandidateSuccess()
connectButton.disabled = true
end
function handleRemoteAddCandidateSuccess()
disconnectButton.disabled = false
end
function handleAddCandidateError()
console:log("Oh noes! addICECandidate failed!")
end
-- Handles clicks on the "Send" button by transmitting
-- a message to the remote peer.
function sendMessage()
local message = messageInputBox.value
sendChannel:send(message)
-- Clear the input box and re-focus it, so that we are
-- ready for the next message.
messageInputBox.value = ""
messageInputBox:focus()
end
-- Handle status changes on the local end of the data
-- channel; this is the end doing the sending of data
-- in this example.
function handleSendChannelStatusChange(self,event)
if (sendChannel) then
local state = sendChannel.readyState
console:log('sendChannel',state)
if (state == "open") then
messageInputBox.disabled = false
messageInputBox:focus()
sendButton.disabled = false
disconnectButton.disabled = false
connectButton.disabled = true
else
messageInputBox.disabled = true
sendButton.disabled = true
connectButton.disabled = false
disconnectButton.disabled = true
end
end
end
-- Called when the connection opens and the data
-- channel is ready to be connected to the remote.
function
I decided to create this simple RTCDataChannel example in lua using fengari. The most interesting part of this process was figuring out how to translate the promise-chaining as seen here:
localConnection.createOffer()
.then(offer => localConnection.setLocalDenoscription(offer))
.then(() => remoteConnection.setRemoteDenoscription(localConnection.localDenoscription))
.then(() => remoteConnection.createAnswer())
.then(answer => remoteConnection.setLocalDenoscription(answer))
.then(() => localConnection.setRemoteDenoscription(remoteConnection.localDenoscription))
.catch(handleCreateDenoscriptionError);
I had to create the then, catch, finally functions in addition to the pdo function which starts the chain.
weft.fengari:
js=require('js')
window=js.global
document=window.document
function then(prom,...)
local p=prom['then'](prom,...)
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function catch(prom,...)
local p=prom'catch'
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function finally(prom,...)
local p=prom['finally'](prom,...)
if p then
p.then = then
p.catch = catch
p.finally = finally
end
return p
end
function pdo(p)
p.then=then
p.catch=catch
p.finally=finally
return p
end
function elevate(from,members)
-- "elevates" table of top level members of a js object (from) into global, for convenience
for , v in ipairs(members) do
ENVv=fromv
end
end
elevate(js.global,{
'console',
'RTCPeerConnection'
})
local connectButton = nil
local disconnectButton = nil
local sendButton = nil
local messageInputBox = nil
local receiveBox = nil
local localConnection = nil -- RTCPeerConnection for our "local" connection
local remoteConnection = nil -- RTCPeerConnection for the "remote"
local sendChannel = nil -- RTCDataChannel for the local (sender)
local receiveChannel = nil -- RTCDataChannel for the remote (receiver)
function handleCreateDenoscriptionError(error)
console:log('unable to create an offer')
end
function handleLocalAddCandidateSuccess()
connectButton.disabled = true
end
function handleRemoteAddCandidateSuccess()
disconnectButton.disabled = false
end
function handleAddCandidateError()
console:log("Oh noes! addICECandidate failed!")
end
-- Handles clicks on the "Send" button by transmitting
-- a message to the remote peer.
function sendMessage()
local message = messageInputBox.value
sendChannel:send(message)
-- Clear the input box and re-focus it, so that we are
-- ready for the next message.
messageInputBox.value = ""
messageInputBox:focus()
end
-- Handle status changes on the local end of the data
-- channel; this is the end doing the sending of data
-- in this example.
function handleSendChannelStatusChange(self,event)
if (sendChannel) then
local state = sendChannel.readyState
console:log('sendChannel',state)
if (state == "open") then
messageInputBox.disabled = false
messageInputBox:focus()
sendButton.disabled = false
disconnectButton.disabled = false
connectButton.disabled = true
else
messageInputBox.disabled = true
sendButton.disabled = true
connectButton.disabled = false
disconnectButton.disabled = true
end
end
end
-- Called when the connection opens and the data
-- channel is ready to be connected to the remote.
function
MDN Web Docs
A simple RTCDataChannel sample - Web APIs | MDN
The RTCDataChannel interface is a feature of the WebRTC API which lets you open a channel between two peers over which you may send and receive arbitrary data. The API is intentionally similar to the WebSocket API, so that the same programming model can be…
Working with WebRTC from fengari lua in the browser...first steps
I decided to create [this simple RTCDataChannel example](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample) in lua using fengari. The most interesting part of this process was figuring out how to translate the promise-chaining as seen here:
localConnection.createOffer()
.then(offer => localConnection.setLocalDenoscription(offer))
.then(() => remoteConnection.setRemoteDenoscription(localConnection.localDenoscription))
.then(() => remoteConnection.createAnswer())
.then(answer => remoteConnection.setLocalDenoscription(answer))
.then(() => localConnection.setRemoteDenoscription(remoteConnection.localDenoscription))
.catch(handleCreateDenoscriptionError);
I had to create the _then, _catch, _finally functions in addition to the p_do function which starts the chain.
weft.fengari:
js=require('js')
window=js.global
document=window.document
function _then(prom,...)
local p=prom['then'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function _catch(prom,...)
local p=prom['catch'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function _finally(prom,...)
local p=prom['finally'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function p_do(p)
p._then=_then
p._catch=_catch
p._finally=_finally
return p
end
function elevate(from,members)
-- "elevates" table of top level members of a js object (from) into global, for convenience
for _, v in ipairs(members) do
_ENV[v]=from[v]
end
end
elevate(js.global,{
'console',
'RTCPeerConnection'
})
local connectButton = nil
local disconnectButton = nil
local sendButton = nil
local messageInputBox = nil
local receiveBox = nil
local localConnection = nil -- RTCPeerConnection for our "local" connection
local remoteConnection = nil -- RTCPeerConnection for the "remote"
local sendChannel = nil -- RTCDataChannel for the local (sender)
local receiveChannel = nil -- RTCDataChannel for the remote (receiver)
function handleCreateDenoscriptionError(error)
console:log('unable to create an offer')
end
function handleLocalAddCandidateSuccess()
connectButton.disabled = true
end
function handleRemoteAddCandidateSuccess()
disconnectButton.disabled = false
end
function handleAddCandidateError()
console:log("Oh noes! addICECandidate failed!")
end
-- Handles clicks on the "Send" button by transmitting
-- a message to the remote peer.
function sendMessage()
local message = messageInputBox.value
sendChannel:send(message)
-- Clear the input box and re-focus it, so that we are
-- ready for the next message.
messageInputBox.value = ""
messageInputBox:focus()
end
-- Handle status changes on the local end of the data
-- channel; this is the end doing the sending of data
-- in this example.
function handleSendChannelStatusChange(self,event)
if (sendChannel) then
local state = sendChannel.readyState
console:log('sendChannel',state)
if (state == "open") then
messageInputBox.disabled = false
messageInputBox:focus()
sendButton.disabled = false
disconnectButton.disabled = false
connectButton.disabled = true
else
messageInputBox.disabled = true
sendButton.disabled = true
connectButton.disabled = false
disconnectButton.disabled = true
end
end
end
-- Called when the connection opens and the data
-- channel is ready to be connected to the remote.
function
I decided to create [this simple RTCDataChannel example](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample) in lua using fengari. The most interesting part of this process was figuring out how to translate the promise-chaining as seen here:
localConnection.createOffer()
.then(offer => localConnection.setLocalDenoscription(offer))
.then(() => remoteConnection.setRemoteDenoscription(localConnection.localDenoscription))
.then(() => remoteConnection.createAnswer())
.then(answer => remoteConnection.setLocalDenoscription(answer))
.then(() => localConnection.setRemoteDenoscription(remoteConnection.localDenoscription))
.catch(handleCreateDenoscriptionError);
I had to create the _then, _catch, _finally functions in addition to the p_do function which starts the chain.
weft.fengari:
js=require('js')
window=js.global
document=window.document
function _then(prom,...)
local p=prom['then'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function _catch(prom,...)
local p=prom['catch'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function _finally(prom,...)
local p=prom['finally'](prom,...)
if p then
p._then = _then
p._catch = _catch
p._finally = _finally
end
return p
end
function p_do(p)
p._then=_then
p._catch=_catch
p._finally=_finally
return p
end
function elevate(from,members)
-- "elevates" table of top level members of a js object (from) into global, for convenience
for _, v in ipairs(members) do
_ENV[v]=from[v]
end
end
elevate(js.global,{
'console',
'RTCPeerConnection'
})
local connectButton = nil
local disconnectButton = nil
local sendButton = nil
local messageInputBox = nil
local receiveBox = nil
local localConnection = nil -- RTCPeerConnection for our "local" connection
local remoteConnection = nil -- RTCPeerConnection for the "remote"
local sendChannel = nil -- RTCDataChannel for the local (sender)
local receiveChannel = nil -- RTCDataChannel for the remote (receiver)
function handleCreateDenoscriptionError(error)
console:log('unable to create an offer')
end
function handleLocalAddCandidateSuccess()
connectButton.disabled = true
end
function handleRemoteAddCandidateSuccess()
disconnectButton.disabled = false
end
function handleAddCandidateError()
console:log("Oh noes! addICECandidate failed!")
end
-- Handles clicks on the "Send" button by transmitting
-- a message to the remote peer.
function sendMessage()
local message = messageInputBox.value
sendChannel:send(message)
-- Clear the input box and re-focus it, so that we are
-- ready for the next message.
messageInputBox.value = ""
messageInputBox:focus()
end
-- Handle status changes on the local end of the data
-- channel; this is the end doing the sending of data
-- in this example.
function handleSendChannelStatusChange(self,event)
if (sendChannel) then
local state = sendChannel.readyState
console:log('sendChannel',state)
if (state == "open") then
messageInputBox.disabled = false
messageInputBox:focus()
sendButton.disabled = false
disconnectButton.disabled = false
connectButton.disabled = true
else
messageInputBox.disabled = true
sendButton.disabled = true
connectButton.disabled = false
disconnectButton.disabled = true
end
end
end
-- Called when the connection opens and the data
-- channel is ready to be connected to the remote.
function
MDN Web Docs
A simple RTCDataChannel sample - Web APIs | MDN
The RTCDataChannel interface is a feature of the WebRTC API which lets you open a channel between two peers over which you may send and receive arbitrary data. The API is intentionally similar to the WebSocket API, so that the same programming model can be…
receiveChannelCallback(self,event)
receiveChannel = event.channel
receiveChannel.onmessage = handleReceiveMessage
receiveChannel.onopen = handleReceiveChannelStatusChange
receiveChannel.onclose = handleReceiveChannelStatusChange
end
-- Handle onmessage events for the receiving channel.
-- These are the data messages sent by the sending channel.
function handleReceiveMessage(self,event)
local el = document:createElement("p")
local txtNode = document:createTextNode(event.data)
el:appendChild(txtNode)
receiveBox:appendChild(el)
end
-- Handle status changes on the receiver's channel.
function handleReceiveChannelStatusChange(event)
if (receiveChannel) then
console:log("Receive channel's status has changed to ",receiveChannel.readyState)
end
-- Here you would do stuff that needs to be done
-- when the channel's status changes.
end
function connectPeers()
localConnection = js.new(RTCPeerConnection)
sendChannel = localConnection:createDataChannel("sendChannel")
sendChannel.onopen = handleSendChannelStatusChange
sendChannel.onclose = handleSendChannelStatusChange
remoteConnection = js.new(RTCPeerConnection)
remoteConnection.ondatachannel = receiveChannelCallback
function localConnection.onicecandidate(self,e)
if e.candidate then
p_do(remoteConnection:addIceCandidate(e.candidate))
:_catch(function(self,error)
handleAddCandidateError(error)
end)
end
end
function remoteConnection.onicecandidate(self,e)
if e.candidate then
p_do(localConnection:addIceCandidate(e.candidate))
:_catch(function(self,error)
handleAddCandidateError(error)
end)
end
end
p_do(localConnection:createOffer())
:_then(function(self,offer)
return localConnection:setLocalDenoscription(offer)
end)
:_then(function()
local localDenoscription = localConnection.localDenoscription
return remoteConnection:setRemoteDenoscription(localDenoscription)
end)
:_then(function()
return remoteConnection:createAnswer()
end)
:_then(function(self,answer)
return remoteConnection:setLocalDenoscription(answer)
end)
:_then(function()
return localConnection:setRemoteDenoscription(remoteConnection.localDenoscription)
end)
:_catch(function(self,error)
handleCreateDenoscriptionError(error)
end)
end
-- Close the connection, including data channels if they are open.
-- Also update the UI to reflect the disconnected status.
function disconnectPeers()
-- Close the RTCDataChannels if they are open.
sendChannel:close()
receiveChannel:close()
-- Close the RTCPeerConnections
localConnection:close()
remoteConnection:close()
sendChannel = null
receiveChannel = null
localConnection = null
remoteConnection = null
-- Update user interface elements
connectButton.disabled = false
disconnectButton.disabled = true
sendButton.disabled = true
messageInputBox.value = ""
messageInputBox.disabled = true
end
function startup()
connectButton = document:getElementById("connectButton")
disconnectButton = document:getElementById("disconnectButton")
sendButton = document:getElementById("sendButton")
messageInputBox = document:getElementById("message")
receiveBox = document:getElementById("receive-box")
-- Set event listeners for user interface widgets
connectButton:addEventListener("click", connectPeers, false)
disconnectButton:addEventListener("click", disconnectPeers, false)
sendButton:addEventListener("click", sendMessage, false)
end
startup()
And weft.html:
<!doctype html>
<html>
<style>
body {
font-family:
receiveChannel = event.channel
receiveChannel.onmessage = handleReceiveMessage
receiveChannel.onopen = handleReceiveChannelStatusChange
receiveChannel.onclose = handleReceiveChannelStatusChange
end
-- Handle onmessage events for the receiving channel.
-- These are the data messages sent by the sending channel.
function handleReceiveMessage(self,event)
local el = document:createElement("p")
local txtNode = document:createTextNode(event.data)
el:appendChild(txtNode)
receiveBox:appendChild(el)
end
-- Handle status changes on the receiver's channel.
function handleReceiveChannelStatusChange(event)
if (receiveChannel) then
console:log("Receive channel's status has changed to ",receiveChannel.readyState)
end
-- Here you would do stuff that needs to be done
-- when the channel's status changes.
end
function connectPeers()
localConnection = js.new(RTCPeerConnection)
sendChannel = localConnection:createDataChannel("sendChannel")
sendChannel.onopen = handleSendChannelStatusChange
sendChannel.onclose = handleSendChannelStatusChange
remoteConnection = js.new(RTCPeerConnection)
remoteConnection.ondatachannel = receiveChannelCallback
function localConnection.onicecandidate(self,e)
if e.candidate then
p_do(remoteConnection:addIceCandidate(e.candidate))
:_catch(function(self,error)
handleAddCandidateError(error)
end)
end
end
function remoteConnection.onicecandidate(self,e)
if e.candidate then
p_do(localConnection:addIceCandidate(e.candidate))
:_catch(function(self,error)
handleAddCandidateError(error)
end)
end
end
p_do(localConnection:createOffer())
:_then(function(self,offer)
return localConnection:setLocalDenoscription(offer)
end)
:_then(function()
local localDenoscription = localConnection.localDenoscription
return remoteConnection:setRemoteDenoscription(localDenoscription)
end)
:_then(function()
return remoteConnection:createAnswer()
end)
:_then(function(self,answer)
return remoteConnection:setLocalDenoscription(answer)
end)
:_then(function()
return localConnection:setRemoteDenoscription(remoteConnection.localDenoscription)
end)
:_catch(function(self,error)
handleCreateDenoscriptionError(error)
end)
end
-- Close the connection, including data channels if they are open.
-- Also update the UI to reflect the disconnected status.
function disconnectPeers()
-- Close the RTCDataChannels if they are open.
sendChannel:close()
receiveChannel:close()
-- Close the RTCPeerConnections
localConnection:close()
remoteConnection:close()
sendChannel = null
receiveChannel = null
localConnection = null
remoteConnection = null
-- Update user interface elements
connectButton.disabled = false
disconnectButton.disabled = true
sendButton.disabled = true
messageInputBox.value = ""
messageInputBox.disabled = true
end
function startup()
connectButton = document:getElementById("connectButton")
disconnectButton = document:getElementById("disconnectButton")
sendButton = document:getElementById("sendButton")
messageInputBox = document:getElementById("message")
receiveBox = document:getElementById("receive-box")
-- Set event listeners for user interface widgets
connectButton:addEventListener("click", connectPeers, false)
disconnectButton:addEventListener("click", disconnectPeers, false)
sendButton:addEventListener("click", sendMessage, false)
end
startup()
And weft.html:
<!doctype html>
<html>
<style>
body {
font-family:
"Lucida Grande", "Arial", sans-serif;
font-size: 16px;
}
.messagebox {
border: 1px solid black;
padding: 5px;
width: 450px;
}
.buttonright {
float: right;
}
.buttonleft {
float: left;
}
.controlbox {
padding: 5px;
width: 450px;
height: 28px;
}
</style>
<head>
<noscript>WebRTC: Simple RTCDataChannel sample</noscript>
<meta charset="utf-8">
<noscript src="js/adapter-latest.js"></noscript>
<noscript src="/js/fengari-web.js" type="text/javanoscript"></noscript>
<noscript id="weft.fengari" src="/weft.fengari" type="application/lua" async></noscript>
</head>
<body>
<h1>MDN - WebRTC: Simple RTCDataChannel sample</h1>
<p>This sample is an admittedly contrived example of how to use an <code>RTCDataChannel</code> to
exchange data between two objects on the same page. See the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample">
corresponding article</a> for details on how it works.</p>
<div class="controlbox">
<button id="connectButton" name="connectButton" class="buttonleft">
Connect
</button>
<button id="disconnectButton" name="disconnectButton" class="buttonright" disabled>
Disconnect
</button>
</div>
<div class="messagebox">
<label for="message">Enter a message:
<input type="text" name="message" id="message" placeholder="Message text"
inputmode="latin" size=60 maxlength=120 disabled>
</label>
<button id="sendButton" name="sendButton" class="buttonright" disabled>
Send
</button>
</div>
<div class="messagebox" id="receive-box">
<p>Messages received:</p>
</div>
</body>
</html>
https://redd.it/1gxagd6
@r_lua
font-size: 16px;
}
.messagebox {
border: 1px solid black;
padding: 5px;
width: 450px;
}
.buttonright {
float: right;
}
.buttonleft {
float: left;
}
.controlbox {
padding: 5px;
width: 450px;
height: 28px;
}
</style>
<head>
<noscript>WebRTC: Simple RTCDataChannel sample</noscript>
<meta charset="utf-8">
<noscript src="js/adapter-latest.js"></noscript>
<noscript src="/js/fengari-web.js" type="text/javanoscript"></noscript>
<noscript id="weft.fengari" src="/weft.fengari" type="application/lua" async></noscript>
</head>
<body>
<h1>MDN - WebRTC: Simple RTCDataChannel sample</h1>
<p>This sample is an admittedly contrived example of how to use an <code>RTCDataChannel</code> to
exchange data between two objects on the same page. See the
<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample">
corresponding article</a> for details on how it works.</p>
<div class="controlbox">
<button id="connectButton" name="connectButton" class="buttonleft">
Connect
</button>
<button id="disconnectButton" name="disconnectButton" class="buttonright" disabled>
Disconnect
</button>
</div>
<div class="messagebox">
<label for="message">Enter a message:
<input type="text" name="message" id="message" placeholder="Message text"
inputmode="latin" size=60 maxlength=120 disabled>
</label>
<button id="sendButton" name="sendButton" class="buttonright" disabled>
Send
</button>
</div>
<div class="messagebox" id="receive-box">
<p>Messages received:</p>
</div>
</body>
</html>
https://redd.it/1gxagd6
@r_lua
MDN Web Docs
A simple RTCDataChannel sample - Web APIs | MDN
The RTCDataChannel interface is a feature of the WebRTC API which lets you open a channel between two peers over which you may send and receive arbitrary data. The API is intentionally similar to the WebSocket API, so that the same programming model can be…
Reading Text in a Status Bar
Greetings, I’m looking for a way to read text from another window, in particular the status bar. I currently do this with an AHK noscript using the StatusbarGetText command. It works well enough but I’m considering switching from Windows to Mac and that means moving away from AHK. This is all for populating an OBS scene so doing it directly in OBS with a lua noscript felt like a good place to start.
If statusbar reading is not possible, I’d be open to other methods, but text files wouldn’t be quick enough.
I realise I haven’t explained the background very well so here is what I currently have set up.
I use a custom build of an emulator to play games and the emulator displays various information in the status bar from the game. An AutoHotKey noscript I made constantly reads the status bar and does various things with it. Some of which is graphical (which OBS displays via window capture) and some (things that can be slower) are exported to text files that OBS, again, does various things with. It’s a bodge, but it works, but as mentioned, I’m wondering if I can now remove the AHK element and have just the emulator and OBS(with lua noscripts)
I’d really appreciate any input. Thanks.
https://redd.it/1gxafs1
@r_lua
Greetings, I’m looking for a way to read text from another window, in particular the status bar. I currently do this with an AHK noscript using the StatusbarGetText command. It works well enough but I’m considering switching from Windows to Mac and that means moving away from AHK. This is all for populating an OBS scene so doing it directly in OBS with a lua noscript felt like a good place to start.
If statusbar reading is not possible, I’d be open to other methods, but text files wouldn’t be quick enough.
I realise I haven’t explained the background very well so here is what I currently have set up.
I use a custom build of an emulator to play games and the emulator displays various information in the status bar from the game. An AutoHotKey noscript I made constantly reads the status bar and does various things with it. Some of which is graphical (which OBS displays via window capture) and some (things that can be slower) are exported to text files that OBS, again, does various things with. It’s a bodge, but it works, but as mentioned, I’m wondering if I can now remove the AHK element and have just the emulator and OBS(with lua noscripts)
I’d really appreciate any input. Thanks.
https://redd.it/1gxafs1
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Please help me learn Lua
I recently switched to Arch Linux, before macOS, where I came into contact with Neovim, Awesomewm, etc., all of which are configured in lua, I myself have learned C, java, etc., and I think I can skip the basic syntax stage when learning lua.
I also tried to find some ways to learn Lua on the Internet.,And then I went to check and learn some big guys' profiles.,But I found that I couldn't understand it.,Of course, some configuration files I put on my computer can also run normally.,But if you want to customize some functions,,I can't do it at all.。
I don't know how I'm going to access the learning lua, please help me!
https://redd.it/1gxxw3x
@r_lua
I recently switched to Arch Linux, before macOS, where I came into contact with Neovim, Awesomewm, etc., all of which are configured in lua, I myself have learned C, java, etc., and I think I can skip the basic syntax stage when learning lua.
I also tried to find some ways to learn Lua on the Internet.,And then I went to check and learn some big guys' profiles.,But I found that I couldn't understand it.,Of course, some configuration files I put on my computer can also run normally.,But if you want to customize some functions,,I can't do it at all.。
I don't know how I'm going to access the learning lua, please help me!
https://redd.it/1gxxw3x
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Lua docs
Hello, I've been learning Lua through docs and I came across this example: https://www.lua.org/pil/10.1.html
db.lua file is calling entry function with the table containing data and in this case they are calling dofile() twice.
I am aware that lua compiles fast but my question is: is there an advantage to doing things this way instead of making db.lua return a table, calling require('db.lua') once and simply passing the table to both entry functions?
https://redd.it/1gyenqc
@r_lua
Hello, I've been learning Lua through docs and I came across this example: https://www.lua.org/pil/10.1.html
db.lua file is calling entry function with the table containing data and in this case they are calling dofile() twice.
I am aware that lua compiles fast but my question is: is there an advantage to doing things this way instead of making db.lua return a table, calling require('db.lua') once and simply passing the table to both entry functions?
https://redd.it/1gyenqc
@r_lua
Help understanding header of a function
I'm trying to understand what the "&" in this function header means
void ChangeColor(const struct FLinearColor& New_Blade_Color, const struct FLinearColor& New_Blade_Glow_Color);
The FLinearColor struct contains 4 attributes (R, G, B and A), all of which are floats; But whenever I try to use the function by passing a table to the parameters it defaults all of them to 0
Hero[2]:ChangeColor({0.9, 0.9, 0.9, 0.9}, {0.9, 0.9, 0.9, 0.9})
(When I access the variables changed by the function they all print '0.0')
What am I doing/understanding wrong here?
https://redd.it/1gym1gu
@r_lua
I'm trying to understand what the "&" in this function header means
void ChangeColor(const struct FLinearColor& New_Blade_Color, const struct FLinearColor& New_Blade_Glow_Color);
The FLinearColor struct contains 4 attributes (R, G, B and A), all of which are floats; But whenever I try to use the function by passing a table to the parameters it defaults all of them to 0
Hero[2]:ChangeColor({0.9, 0.9, 0.9, 0.9}, {0.9, 0.9, 0.9, 0.9})
(When I access the variables changed by the function they all print '0.0')
What am I doing/understanding wrong here?
https://redd.it/1gym1gu
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Obfuscators
Hello everyone,
I decided to create a Discord bot that works as a Lua obfuscator. This is interesting to me because luaobfuscator.com crashes quite often. The bot uses the free API from luaobfuscator.com to obfuscate files uploaded in the server.
It’s no secret that luaobfuscator.com doesn’t provide very strong obfuscation, just something basic to deter skidders. However, if someone really wants the source code, they can still access it without much effort.
I’m looking for a Python-based obfuscator or websites offering APIs for Lua obfuscation. Any help would be appreciated!
https://redd.it/1h00bii
@r_lua
Hello everyone,
I decided to create a Discord bot that works as a Lua obfuscator. This is interesting to me because luaobfuscator.com crashes quite often. The bot uses the free API from luaobfuscator.com to obfuscate files uploaded in the server.
It’s no secret that luaobfuscator.com doesn’t provide very strong obfuscation, just something basic to deter skidders. However, if someone really wants the source code, they can still access it without much effort.
I’m looking for a Python-based obfuscator or websites offering APIs for Lua obfuscation. Any help would be appreciated!
https://redd.it/1h00bii
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
My 100% free obfuscator
Hello,
I created a free Discord obfuscator bot with no hidden costs. It was a great learning experience for me, so it’s a win-win for everyone.
Enjoy!
https://discord.gg/N25mkPRsk9
https://redd.it/1h008x9
@r_lua
Hello,
I created a free Discord obfuscator bot with no hidden costs. It was a great learning experience for me, so it’s a win-win for everyone.
Enjoy!
https://discord.gg/N25mkPRsk9
https://redd.it/1h008x9
@r_lua
Discord
Join the 🔒 LuaMask 0.1 Discord Server!
Check out the 🔒 LuaMask 0.1 community on Discord - hang out with 7 other members and enjoy free voice and text chat.
Can someone help add a 5 second cooldown to this barrage noscript?
function onTouched(touch)
local hums = touch.Parent:FindFirstChildOfClass("Humanoid")
if hums then
hums:TakeDamage(0.3)
end
end
function onTouched2(touch2)
local hums2 = touch2.Parent:FindFirstChildOfClass("Humanoid")
if hums2 then
hums2:TakeDamage(0.3)
end
end
noscript.Parent.Activated:Connect(function()
local anim = noscript.Parent.Hurts
local human = noscript.Parent.Parent:FindFirstChildOfClass("Humanoid")
local playanim = human:LoadAnimation(anim)
playanim:Play()
local parts = noscript.Parent.Parent["Left Arm"\].Touched:Connect(onTouched)
local parts2 = noscript.Parent.Parent["Right Arm"\].Touched:Connect(onTouched2)
wait(3)
parts:Disconnect()
parts2:Disconnect()
end)
https://redd.it/1h0bnw4
@r_lua
function onTouched(touch)
local hums = touch.Parent:FindFirstChildOfClass("Humanoid")
if hums then
hums:TakeDamage(0.3)
end
end
function onTouched2(touch2)
local hums2 = touch2.Parent:FindFirstChildOfClass("Humanoid")
if hums2 then
hums2:TakeDamage(0.3)
end
end
noscript.Parent.Activated:Connect(function()
local anim = noscript.Parent.Hurts
local human = noscript.Parent.Parent:FindFirstChildOfClass("Humanoid")
local playanim = human:LoadAnimation(anim)
playanim:Play()
local parts = noscript.Parent.Parent["Left Arm"\].Touched:Connect(onTouched)
local parts2 = noscript.Parent.Parent["Right Arm"\].Touched:Connect(onTouched2)
wait(3)
parts:Disconnect()
parts2:Disconnect()
end)
https://redd.it/1h0bnw4
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Lua api-wrapper for llm-inference chatllm.cpp
Hi. I used Qwen 2.5 32b Coder Instruct to make lua api wrapper for llm-inference chatllm.cpp: https://github.com/JohnClaw/chatllm.lua/
https://redd.it/1h0ggym
@r_lua
Hi. I used Qwen 2.5 32b Coder Instruct to make lua api wrapper for llm-inference chatllm.cpp: https://github.com/JohnClaw/chatllm.lua/
https://redd.it/1h0ggym
@r_lua
GitHub
GitHub - JohnClaw/chatllm.lua: lua api wrapper for llm-inference chatllm.cpp
lua api wrapper for llm-inference chatllm.cpp. Contribute to JohnClaw/chatllm.lua development by creating an account on GitHub.
Need help with a recoil noscript
I downloaded this recoil noscript for Rust. It works fine except for the fact that I need to double click in order for the recoil compensation to kick in. So essentially when I click once it compensates the recoil, but when held down it doesn't work. If I click once and then hold down mouse 1 RIGHT after it, it works.
I need a high IQ individual to help me out here, im not familiar with coding and even tried to ask ChatGPT for help but to no avail. :(
Heres the code:
function hzCf681ZWWcx()
return not IsMouseButtonPressed(1)
end
function IsRightNotPressed()
return not IsMouseButtonPressed(3)
end
function hzCf681ZWWcxfjjs(a)
b = GetRunningTime() + a
repeat
until GetRunningTime() > b - 1
end
function Sleep_extra(gun, a)
local b = GetRunningTime() + a
repeat
if IsMouseButtonPressed(gun) then
break
end
until GetRunningTime() > b - 1
end
function round(x)
return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)
end
function Smoothing(c, d, e)
local f, g, h = 0, 0, 0
local i = d / c
local j = e / c
for k = 0, c do
local l = round(k * i)
local m = round(k * j)
local n = k
MoveMouseRelative(l - f, m - g)
hzCf681ZWWcxfjjs(n - h)
f, g, h = l, m, n
end
end
GunsPatterns = {
[1] = {
[1] =
Thank you!
https://redd.it/1h0v6mo
@r_lua
I downloaded this recoil noscript for Rust. It works fine except for the fact that I need to double click in order for the recoil compensation to kick in. So essentially when I click once it compensates the recoil, but when held down it doesn't work. If I click once and then hold down mouse 1 RIGHT after it, it works.
I need a high IQ individual to help me out here, im not familiar with coding and even tried to ask ChatGPT for help but to no avail. :(
Heres the code:
function hzCf681ZWWcx()
return not IsMouseButtonPressed(1)
end
function IsRightNotPressed()
return not IsMouseButtonPressed(3)
end
function hzCf681ZWWcxfjjs(a)
b = GetRunningTime() + a
repeat
until GetRunningTime() > b - 1
end
function Sleep_extra(gun, a)
local b = GetRunningTime() + a
repeat
if IsMouseButtonPressed(gun) then
break
end
until GetRunningTime() > b - 1
end
function round(x)
return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)
end
function Smoothing(c, d, e)
local f, g, h = 0, 0, 0
local i = d / c
local j = e / c
for k = 0, c do
local l = round(k * i)
local m = round(k * j)
local n = k
MoveMouseRelative(l - f, m - g)
hzCf681ZWWcxfjjs(n - h)
f, g, h = l, m, n
end
end
GunsPatterns = {
[1] = {
[1] =
Thank you!
https://redd.it/1h0v6mo
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Any tools to read Lua source, parse the LuaDoc in it, and spit out a data structure of the results?
I'm writing a program that would benefit from being able to read the LuaDoc in a lua source file. I first tried to set up a regex to do this but it would wind up being gigantic and not worth the effort. Are there any such tools out there? I need it to give me a list of the functions and whatever params the user supplied in the LuaDoc.
For example:
---Begin fishing at a spot, allowing the player to click the fishing reticle
---to "complete" the attempt. This function must be called outside a coroutine.
---@param fishList FishableList The list of fish. Preferably, return results of calling Fishing.Find.
---@param junkList JunkableList The list of junk.
---@param reticlePointEntity Entity The point entity where the fishing reticle will spawn.
---@param fishingRod Entity The fishing rod entity, which will be hidden during fishing.
---@param consolationLootTable string Loot table to use as a consolation prize (unsuccessful fishing outcome but there was a fish in the reticle).
---@param catchCallback? function Function to call when catching a fish, with a single
function Fishing.Setup(fishList, junkList, reticlePointEntity, fishingRod, consolationLootTable, catchCallback)
I need back the function name
There seem to be tons of LuaDoc doc makers out there but nothing that kinda specifically stops at just exporting the data in a more programmer-friendly fashion.
https://redd.it/1h0y4wo
@r_lua
I'm writing a program that would benefit from being able to read the LuaDoc in a lua source file. I first tried to set up a regex to do this but it would wind up being gigantic and not worth the effort. Are there any such tools out there? I need it to give me a list of the functions and whatever params the user supplied in the LuaDoc.
For example:
---Begin fishing at a spot, allowing the player to click the fishing reticle
---to "complete" the attempt. This function must be called outside a coroutine.
---@param fishList FishableList The list of fish. Preferably, return results of calling Fishing.Find.
---@param junkList JunkableList The list of junk.
---@param reticlePointEntity Entity The point entity where the fishing reticle will spawn.
---@param fishingRod Entity The fishing rod entity, which will be hidden during fishing.
---@param consolationLootTable string Loot table to use as a consolation prize (unsuccessful fishing outcome but there was a fish in the reticle).
---@param catchCallback? function Function to call when catching a fish, with a single
entity argument. This will be called in a coroutine.function Fishing.Setup(fishList, junkList, reticlePointEntity, fishingRod, consolationLootTable, catchCallback)
I need back the function name
Fishing.Setup, along with all args and their given types, for all functions in a file.There seem to be tons of LuaDoc doc makers out there but nothing that kinda specifically stops at just exporting the data in a more programmer-friendly fashion.
https://redd.it/1h0y4wo
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
How do i decode this Lua code for my TI Nspire CX CAS
Define GreenLagrangeTensor()=
Prgm
Local u1, u2, u3, X1, X2, X3, E11, E22, E33, E12, E13, E23
// Eingabe der Verschiebungsfunktionen
Request "u1(X1,X2,X3):", u1
Request "u2(X1,X2,X3):", u2
Request "u3(X1,X2,X3):", u3
// Berechnung der Komponenten des Green-Lagrange-Verzerrungstensors
E11 := diff(u1, X1) + 0.5 * (diff(u1, X1)\^2 + diff(u2, X1)\^2 + diff(u3, X1)\^2)
E22 := diff(u2, X2) + 0.5 * (diff(u1, X2)\^2 + diff(u2, X2)\^2 + diff(u3, X2)\^2)
E33 := diff(u3, X3) + 0.5 * (diff(u1, X3)\^2 + diff(u2, X3)\^2 + diff(u3, X3)\^2)
E12 := 0.5 * (diff(u1, X2) + diff(u2, X1)) + 0.5 * (diff(u1, X1)*diff(u1, X2) + diff(u2, X1)*diff(u2, X2) + diff(u3, X1)*diff(u3, X2))
E13 := 0.5 * (diff(u1, X3) + diff(u3, X1)) + 0.5 * (diff(u1, X1)*diff(u1, X3) + diff(u2, X1)*diff(u2, X3) + diff(u3, X1)*diff(u3, X3))
E23 := 0.5 * (diff(u2, X3) + diff(u3, X2)) + 0.5 * (diff(u1, X2)*diff(u1, X3) + diff(u2, X2)*diff(u2, X3) + diff(u3, X2)*diff(u3, X3))
// Ausgabe der Ergebnisse
Disp "E11=", E11
Disp "E22=", E22
Disp "E33=", E33
Disp "E12=", E12
Disp "E13=", E13
Disp "E23=", E23
EndPrgm
https://redd.it/1h0ztye
@r_lua
Define GreenLagrangeTensor()=
Prgm
Local u1, u2, u3, X1, X2, X3, E11, E22, E33, E12, E13, E23
// Eingabe der Verschiebungsfunktionen
Request "u1(X1,X2,X3):", u1
Request "u2(X1,X2,X3):", u2
Request "u3(X1,X2,X3):", u3
// Berechnung der Komponenten des Green-Lagrange-Verzerrungstensors
E11 := diff(u1, X1) + 0.5 * (diff(u1, X1)\^2 + diff(u2, X1)\^2 + diff(u3, X1)\^2)
E22 := diff(u2, X2) + 0.5 * (diff(u1, X2)\^2 + diff(u2, X2)\^2 + diff(u3, X2)\^2)
E33 := diff(u3, X3) + 0.5 * (diff(u1, X3)\^2 + diff(u2, X3)\^2 + diff(u3, X3)\^2)
E12 := 0.5 * (diff(u1, X2) + diff(u2, X1)) + 0.5 * (diff(u1, X1)*diff(u1, X2) + diff(u2, X1)*diff(u2, X2) + diff(u3, X1)*diff(u3, X2))
E13 := 0.5 * (diff(u1, X3) + diff(u3, X1)) + 0.5 * (diff(u1, X1)*diff(u1, X3) + diff(u2, X1)*diff(u2, X3) + diff(u3, X1)*diff(u3, X3))
E23 := 0.5 * (diff(u2, X3) + diff(u3, X2)) + 0.5 * (diff(u1, X2)*diff(u1, X3) + diff(u2, X2)*diff(u2, X3) + diff(u3, X2)*diff(u3, X3))
// Ausgabe der Ergebnisse
Disp "E11=", E11
Disp "E22=", E22
Disp "E33=", E33
Disp "E12=", E12
Disp "E13=", E13
Disp "E23=", E23
EndPrgm
https://redd.it/1h0ztye
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Simple table assignment in for loop not working.
Hey,
I have a decent amount of programming experience, and am trying to learn some lua (for DCS noscripting) But just quickly going through the basic tutorials I ran into a problem. For some reason this simple code, which should just reverse a table won't work:
days = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",}
revDays = {}
for i,v in ipairs(days) do
revDaysv = i
print('Adding weekday "' .. v .. '" with value: ' .. i)
end
for day,index in ipairs(revDays) do
print(" day " .. day .. " has index " .. index)
end
I know I'm probably missing something obvious, but for the life of me I can't figure it out.
The code itself is copy-pasted from https://lua.org/pil/4.3.5.html
https://redd.it/1h10qd3
@r_lua
Hey,
I have a decent amount of programming experience, and am trying to learn some lua (for DCS noscripting) But just quickly going through the basic tutorials I ran into a problem. For some reason this simple code, which should just reverse a table won't work:
days = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",}
revDays = {}
for i,v in ipairs(days) do
revDaysv = i
print('Adding weekday "' .. v .. '" with value: ' .. i)
end
for day,index in ipairs(revDays) do
print(" day " .. day .. " has index " .. index)
end
I know I'm probably missing something obvious, but for the life of me I can't figure it out.
The code itself is copy-pasted from https://lua.org/pil/4.3.5.html
https://redd.it/1h10qd3
@r_lua
Why does Lua have ipairs ?
I am aware of the difference between pairs() and ipairs() but seeing another post here today I was wondering why lua actually has ipairs.
does exactly the same thing after all. I always use ipairs for non-dictionary arrays but is it actually worth it? Is there a minimal memory advantage or performance difference?
https://redd.it/1h12gmj
@r_lua
I am aware of the difference between pairs() and ipairs() but seeing another post here today I was wondering why lua actually has ipairs.
t = { "a", "b", "c", "d"}for i,v in ipairs(t) doprint(i, v)endfor i,v in pairs(t) doprint(i, v)enddoes exactly the same thing after all. I always use ipairs for non-dictionary arrays but is it actually worth it? Is there a minimal memory advantage or performance difference?
https://redd.it/1h12gmj
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Looking for 5 to 10 people animator and noscripters for developing a game PetQuest DM me for more information and payment
https://redd.it/1h15dnh
@r_lua
https://redd.it/1h15dnh
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Adding of lua plugins support for the C/C++ application
Guys, what would you recommend for developers who want to support Lua plugins in their desktop applications? Any best practices or examples to start?
https://redd.it/1h1x1ch
@r_lua
Guys, what would you recommend for developers who want to support Lua plugins in their desktop applications? Any best practices or examples to start?
https://redd.it/1h1x1ch
@r_lua
Reddit
From the lua community on Reddit
Explore this post and more from the lua community
Redbean + Fengari = fun
I've posted several times on here lately about fengari, but I haven't mentioned Redbean and I don't see a lot of reference to it in the sub.
Anybody else using these two together?
https://redd.it/1h1wivb
@r_lua
I've posted several times on here lately about fengari, but I haven't mentioned Redbean and I don't see a lot of reference to it in the sub.
Anybody else using these two together?
https://redd.it/1h1wivb
@r_lua
lua-language-server cant be called even after adding to path in windows
https://redd.it/1h20r2d
@r_lua
https://redd.it/1h20r2d
@r_lua