minetest-mods / mesecons

Mod for minetest that adds digital circuitry [=Minecraft redstone]
https://mesecons.net
Other
204 stars 118 forks source link

Noteblocks (MESECONS_GLOBALSTEP) #108

Closed khonkhortisan closed 11 years ago

khonkhortisan commented 11 years ago

Two problems:

1. They have echos

Noteblock, Chest, Wire, Switch

N
CWS

I added some debug to see where the echo was coming from

        action_on = function (pos, node)
            print("on")
            mesecon.noteblock_play(pos, node.param2)
            print("off")
        end

It turns out turning the switch on runs action_on 12 times! And it goes on off on off, not on on off off

2. They aren't synchronized

I hooked up all the noteblocks to a single button, and it consistently takes 5 seconds to play all of them (fixing the first problem might lessen this one). It starts at the percussion and goes down the notes, at least in my case.

khonkhortisan commented 11 years ago

1. MESECONS_GLOBALSTEP

Turning it off fixes the problem

2. server distance

It's 5 seconds on VanessaE's server (with MESECONS_GLOBALSTEP), over 1 second locally with MESECONS_GLOBALSTEP, and (nearly-instant) locally without MESECONS_GLOBALSTEP.

khonkhortisan commented 11 years ago

TL;DR skip to the divider

Execution flow:

We'll start at the switch (-10,8,-6), which runs mesecon:receptor_on_i which runs mesecon:turnon (with no rulename) for the wire (-11,9,-6). mesecon:turnon goes into if mesecon:is_conductor_off, and yada yada. Then mesecon:turnon gets run for the noteblock, and skips if mesecon:is_conductor_off, going into elseif mesecon:is_effector. mesecon:turnon then runs mesecon:changesignal({x=12,y=9,z=-6},"mesecons_noteblock:noteblock",nil,"on").

If MESECONS_GLOBALSTEP = false

mesecon:changesignal skips over if MESECONS_GLOBALSTEP, checks if effector and effector.action_change, and stops because noteblocks don't have that. Back to mesecon:turnon, it checks if mesecon:is_effector_off, then runs mesecon:activate. mesecon:activate skips over if MESECONS_GLOBALSTEP and goes to the else. Then it checks if effector and effector.action_on and runs effector.action_on because noteblocks have that.

If MESECONS_GLOBALSTEP = true

mesecons:changesignal goes into if MESECONS_GLOBALSTEP, then into if rulename == nil then and starts looping through mesecon:effector_get_rules(node)), running mesecon:changesignal({x=12,y=9,z=-6},"mesecons_noteblock:noteblock",{y=0,x=1,z=0},"on"). For noteblocks, there are twelve rules. The 12 second iterations of mesecon:changesignal also go into if MESECONS_GLOBALSTEP but do not go into if rulename == nil. Then they run add_action({x=12,y=9,z=-6},"con",{y=0,x=1,z=0}). add_action goes through the mesecon.to_update list

...skipping a lot, sorry...

execute_actions with i in mesecons.to_update being (-12,9-6) "on" {y=0,x=1,z=0}. It goes to if i.action == "on" and runs effector.action_on


What's going on: Without MESECONS_GLOBALSTEP, mesecon:activate runs effector.action_on. With MESECONS_GLOBALSTEP, mesecon:activate multiplies itself by the number of rules, then (add_action,execute_actions) each copy still runs effector.action_on, doing nothing with the rules that the function was just multiplied by. With a wire, it doesn't matter if it turns on when it's on. But with a noteblock, it's noticable.

I'm looking at the add_action function. It only considers actions the same if both the position and rule are the same. Where is the rule used? It's passed into `effector.action_on(i.pos, node, i.rname), making the node think it was called from all directions.

UNRELATED NOTE: mesecons:changesignal shouldn't add anything to globalstep if the if effector and effector.action_change check doesn't pass (before looping through rules, at the beginning of the function). Checking mesecon:effector_get_rules(node) isn't enough to check for action_change.

I'll give this to you to make sense of.

khonkhortisan commented 11 years ago

mesecon:turnon(pos, rulename) has nil for the rulename. That might be the cause of the problem. edit: fixed it, pull request coming

khonkhortisan commented 11 years ago

Or not: https://github.com/Jeija/minetest-mod-mesecons/commit/4f2604e01bce9bca71105ad6822fd9d98d6511f9 A single mistake can snowball into malfunctions elsewhere

Uberi commented 11 years ago

Does this fix the issue? I have not had a chance to debug it much yet.

khonkhortisan commented 11 years ago

Yes, it fixes the issue, and it's obvious that that part was wrong (so if it didn't fix the issue, there's another problem somewhere else) Not sending nil as the rule that caused the activation makes it not resend the activation for every rule the node has. Also, I can now play a chord or all the noteblocks at the same time locally. I'll have to see if they're still synchronized on a server. And they are.