CC: Tweaked

CC: Tweaked

57M Downloads

Turtle movement yields when lots of peripherals attach/detach at once

Kan18 opened this issue · 9 comments

commented

Minecraft Version

1.19.2

Version

1.100.9

Details

Basically: when while true do print(os.pullEvent()) end is running in a tab in a turtle's multishell, and the turtle disconnects or connects to a wired modem network with a lot of peripherals (I tested with 512 for this) when moving with turtle.forward()/turtle.back(), the turtle movement call sometimes yields until terminated. I think this might be because the peripheral attach and detach events are overflowing the event queue, but I'm not sure.

Video
Same video on different link

Logs attached although it doesn't look like anything relevant to this is showing in them: logs.zip

commented

I forget how big the event queue is, but overflowing it does seem to be a plausible explanation.

What kind of setup do you have that means you have turtles causally going past modems with over 500 peripherals connected to the network? Could you isolate your turtles from this network, perhaps using a proxy computer if they have to interact with it? The setup in the video is very artificial.

commented

Networks with hundreds of chests are not unheard of on SwitchCraft (To be clear, this affects 1.12, 1.19, and probably other versions but I haven't tested with them) - my base has 275 peripherals. This was how I ran into this bug initially, but I later just moved the wired modem on top of the chest so that the turtle doesn't hit it.

What's a bit interesting about this bug is that I couldn't get it to reproduce if I didn't run the while true do print(os.pullEvent()) end in the REPL in another multishell tab. The other multishell tab wasn't even focused!

commented

Minecraft Version

1.19.2

Version

1.100.9

How are you playing on mc version 1.19.2 ? CC tweaked only supports 1.19.1 as far as I can see?

commented

🤷‍♂️ It worked

commented

Can you let me know which release you're using?

commented

The latest version should work on both.

commented

Basically: when while true do print(os.pullEvent()) end is running in a tab in a turtle's multishell, and the turtle disconnects or connects to a wired modem network with a lot of peripherals (I tested with 512 for this) when moving with turtle.forward()/turtle.back(), the turtle movement call sometimes yields until terminated. I think this might be because the peripheral attach and detach events are overflowing the event queue, but I'm not sure.

This issue is quite awhile, but this is how I solved the problem:

local function discardAllEvents()
	local count = 0
	local timer = os.startTimer(0.5)
	while true do
		local event, id = os.pullEvent()
		if event == 'timer' and id == timer then
			print('discarded', count, 'events')
			return
		else
			count = count + 1
			os.cancelTimer(timer)
			timer = os.startTimer(0.5)
		end
	end
end

local function noCareAction(action, ...)
	local thr = coroutine.create(action)
	coroutine.resume(thr, ...)
	discardAllEvents()
end

local function placeModemCol()
	noCareAction(turtle.down)
	for i = 2, 13 do
		-- print('DBUG: moving back')
		noCareAction(turtle.back)
		-- print('DBUG: selecting modem')
		while not selectItem(modemId) do sleep(0.1) end
		-- print('DBUG: placing modem')
		noCareAction(turtle.place)
		-- print('DBUG: activing modem')
		waitForCooldown('useOnBlock')
		-- print('DBUG: using on block')
		automata.useOnBlock()
		discardAllEvents()
	end
	noCareAction(turtle.up)
	for i = 2, 13 do
		noCareAction(turtle.forward)
	end
end
commented

Yea throwing all events away alongside with coroutinethat is waiting for event is a "solution" but it feels off.
Heck all you probably needed to do is just throw away the coroutine.

I know this suggestion may seem extreme but how about changing how event queue works java side and instead of throwing away overflowing events, if queue reaches point its overflowed just delay overflowed events at next tick and so on so on? This would have side benefit of artificially slowing down computers that generate too many events but it would probably need to get thought thru to make sure it don't have side effects i can't think of right now.

commented

Heck all you probably needed to do is just throw away the coroutine.

No because the actions require the previous action to be done, so I should throw away all events to ensure the action is either success or fail, from the context in my world the action should always success