This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Imred Gemu's profile picture

Overriding The Event System

Started by Imred Gemu, 18 September 2015 - 02:53 AM
Imred Gemu #1
Posted 18 September 2015 - 04:53 AM
I'll try to be as thorough as I can explaining this. I'm reinventing the wheel a bit here with this API but I need it for something else I'm working on: http://pastebin.com/kjKrUP41 Most of it works perfectly fine. The problem I'm dealing with is in the function "receiveEvents" at line 643, or more specifically, the point where it overrides the "os.pullEventRaw" function at line 654. The idea here is that the event receivers and senders can be passed a table of strings indexed to strings. The functions will then take any event which matches an index in those tables and convert the event to the value of that index. For example {["foo"]="bar"} will convert all "foo" events into "bar" events. On the sender side, this happens just before the event is sent. On the receiving side, this happens in the "os.pullEventRaw" function so that both events received over rednet, and events fired by that computer will be converted according to the tables mentioned earlier. The purpose I had in mind for this is to have it send all events from the sender as "remote_eventName", which would then be converted back to "eventName" on the receiving computer. This works just fine, the trouble comes in when I take it to the next step. I want to convert all local events from "eventName" to "void_eventName". The final result being that the sending computer can fire events on the receiving computer, while the receiving computer can not. The problem is, when working with the parallel system, os.pullEventRaw will be called multiple times, so the event ends up getting modified more than once. "remote_eventName" becomes "eventName" becomes "void_eventName". This of course breaks the sending computer's ability to control the receiving computer. I thought the work around would be simple enough, just add and extra flag to the event saying "event has been modified" so that no other "pullEventRaw"s try to mess with it. This works for most events, but for whatever reason one of the coroutines removes the flag from all mouse events resulting in them being modified more than once. I can type, but not click. Basically, I need help either fixing this workaround, or finding another workaround. I'll post the testing code below, to set up the environment, place down two advanced computers and attach wireless modems to the top of each. Set the label of both and install TRoR on them. Modify the following code where needed to match the credentials of your computers.


--"sender" refers to the computer which will be sending events, not the computer which will be sending its screen
rednet.open("top")
if os.getComputerID() == [sender ID] then

parallel.waitForAny(

  function()
  
   sendEvents(asPacketDataS(
	
	 "test",
	 "all",
	 rednet.CHANNEL_BROADCAST
	
	),
	genWhitelistTable(
	
	 "terminate",
	 "key",
	 "char",
	 "key_up",
	 "mouse_click",
	 "mouse_up",
	 "mouse_scroll",
	 "mouse_drag"
	
	),
	{
	
	 ["terminate"]="remote_terminate",
	 ["key"]="remote_key",
	 ["char"]="remote_char",
	 ["key_up"]="remote_key_up",
	 ["mouse_click"]="remote_mouse_click",
	 ["mouse_up"]="remote_mouse_up",
	 ["mouse_scroll"]="remote_mouse_scroll",
	 ["mouse_drag"]="remote_mouse_drag"
	
	}, true)
  
  end,
  function()
  
   receiveScreen(asPacketData(
	
	 "test",
	 nil,
	 [receiver ID],
	 nil,
	 rednet.CHANNEL_BROADCAST
	
	))
  
   if term.termRediected then
  
	term.resetTerm()
  
   end
  
  end

)

else

parallel.waitForAny(

  function()
  
   receiveEvents(nil,
	asPacketData(
	
	 "test",
	 nil,
	 [sender ID],
	 nil,
	 rednet.CHANNEL_BROADCAST
	
	),
	{
	
	 ["remote_terminate"]="terminate",
	 ["remote_key"]="key",
	 ["remote_char"]="char",
	 ["remote_key_up"]="key_up",
	 ["remote_mouse_click"]="mouse_click",
	 ["remote_mouse_up"]="mouse_up",
	 ["remote_mouse_scroll"]="mouse_scroll",
	 ["remote_mouse_drag"]="mouse_drag",
	 ["terminate"]="void_terminate",
	 ["key"]="void_key",
	 ["char"]="void_char",
	 ["key_up"]="void_key_up",
	 ["mouse_click"]="void_mouse_click",
	 ["mouse_up"]="void_mouse_up",
	 ["mouse_scroll"]="void_mouse_scroll",
	 ["mouse_drag"]="void_mouse_drag"
	
	}
   )
  
  end,
  function()
  
   sendScreen(function()
	
	 shell.run("shell")
	
	 if os.pullEventRawOverriden then
	
	  os.resetOsTable()
	
	 end
	
	end,
	asPacketDataS(
	
	 "test",
	 "all",
	 rednet.CHANNEL_BROADCAST
	
	), true
  
   )
  
  end

)

end
Lyqyd #2
Posted 18 September 2015 - 05:30 AM
The multishell program is stripping your flag.

Seems like you're going about TRoR the really, really hard way. Why do you need to block user input, and why not just use a program on the receiving machine to directly handle the incoming modem messages and ignore user input?
Bomb Bloke #3
Posted 18 September 2015 - 08:19 AM
If the answer to that last point happens to be "because you don't want the receiving system to have two instances of shell in RAM all the time", you might consider the TLCO technique.

As I was saying in your other thread, the other option is to implement a system to keep track of which events have already been modified. This could be done as simply as adding an extra parameter (say a boolean set to true) to each of them.
Imred Gemu #4
Posted 18 September 2015 - 02:35 PM
The multishell program is stripping your flag.

Seems like you're going about TRoR the really, really hard way. Why do you need to block user input, and why not just use a program on the receiving machine to directly handle the incoming modem messages and ignore user input?
The test code I put up is a simplified version of the program that the API was designed for. The sending computer sends its events and receives term output from the receiving computer. The receiving computer receives events and queues them, sends its term output to the sending computer, and runs the shell on top of all this. The idea is basically a remote control shell where I can control the computer that the shell runs on from my computer, but the person using the computer can not. By converting normal events to "void_eventName", most programs won't know to look for them and therefor, won't respond to those events. Remote events however are converted into regular events. If the system worked properly, they wouldn't be modified again and programs on the computer would respond to them.
If the answer to that last point happens to be "because you don't want the receiving system to have two instances of shell in RAM all the time", you might consider the TLCO technique.

As I was saying in your other thread, the other option is to implement a system to keep track of which events have already been modified. This could be done as simply as adding an extra parameter (say a boolean set to true) to each of them.
I already am adding an extra parameter as a string which flags the event as having already been modified, the problem is somewhere in the chain of coroutines, someone is stripping that flag off for mouse events. Key events, terminate events, and any other events seem to work fine, just not mouse events. Lyqyd said multishell is the culprit for this, and I don't really need multishell for what I'm doing here. That being said TLCO looks like a promising fix, I'll give that a try.
Lyqyd #5
Posted 18 September 2015 - 08:06 PM
Have you seen my nsh program? What you're trying to do could be accomplished via four or five removed lines, and one added line, I'd suspect. Just wanted to point out that option in case you hadn't seen it before.
Imred Gemu #6
Posted 19 September 2015 - 02:02 AM
Have you seen my nsh program? What you're trying to do could be accomplished via four or five removed lines, and one added line, I'd suspect. Just wanted to point out that option in case you hadn't seen it before.
No I had not seen this program before, could have saved me a lot of time as it's very similar to what I'm trying to do. I had seen your implementation of TRoR, but I didn't think I could use it for this purpose without a lot of modifications. I've pretty much already got my program finished though, the only thing left is to patch this bug.
Imred Gemu #7
Posted 22 September 2015 - 04:06 PM
Exiting the multishell fixes the problem, I'm working on polishing it. The finished version with the fix will be uploaded to the same pastebin link.