Redstone et liaisons de Create
Les six faces de l'ordinateur, les Liaisons de redstone de Create et les blocs qui obéissent à la redstone : lire boutons et détecteurs, piloter embrayages, inverseurs et chaînes Create entières.
La redstone est le moyen par lequel un ordinateur touche l'essentiel du monde. Un bouton, un levier, une plaque de pression ou un détecteur de Create signalent au programme que quelque chose s'est passé ; une lampe, une porte, un Embrayage ou un Inverseur de rotation font ce que le programme décide. Un ordinateur atteint la redstone de trois façons :
- Ses six faces, avec la bibliothèque
rs: un fil, un bouton, une lampe ou un Embrayage de Create posé directement contre lui. - Les Liaisons de redstone de Create, avec la bibliothèque
linkou une Liaison de redstone utilisée comme périphérique (Liaison de redstone) : des signaux sans fil, jusqu'à 256 blocs par défaut. - Les appareils qui ont leurs propres sorties, pilotés comme périphériques : le Feu tricolore, la Boucle de détection, le brûleur à air chaud (Hot Air Burner) de Create Aeronautics.
Les six faces
Les faces sont nommées par rapport à l'écran, telles que vous voyez l'ordinateur en face de son écran : front est l'écran lui-même, left et right sont votre gauche et votre droite, top et bottom le dessus et le dessous.
back
(l'arbre arrive ici)
+-------------------+
| |
left | ordinateur | right
| (vu de |
| dessus) |
+-------------------+
front
(l'écran)
vousComme les noms suivent l'écran, un programme continue de marcher quand vous reconstruisez le même montage tourné dans une autre direction.
Deux faces sont souvent prises : l'arbre qui entraîne l'ordinateur arrive à l'arrière, back (en dessous, bottom, pour le Microcontrôleur, entraîné par le bas), et un moniteur peut occuper une autre face. Les autres faces sont libres pour la redstone.
rs.sides() renvoie les six noms, pratique pour parcourir toutes les faces. Tout autre nom arrête le programme avec bad side 'up' (front, back, left, right, top, bottom).
Lire les entrées
rs.get(face) renvoie la puissance redstone que le bloc posé sur cette face envoie dans l'ordinateur, de 0 (rien) à 15 (pleine puissance) : un levier, un bouton, une plaque de pression, un fil de redstone qui pointe vers l'ordinateur, un bloc alimenté, un comparateur, un Observateur intelligent de Create, une Liaison de redstone en mode réception posée contre lui...
La puissance redstone est analogique : 16 niveaux, pas seulement allumé ou éteint. Un fil perd un niveau par bloc, un comparateur mesure le remplissage d'un conteneur, un Levier analogique de Create donne le niveau que vous réglez. Pour traiter une face comme un simple interrupteur, testez rs.get(face) > 0.
if rs.get("left") > 0 then
print("le levier de gauche est levé")
end
print("puissance sur le dessus : " .. rs.get("top") .. " / 15")Attendre un changement : l'évènement redstone
Lire une face en boucle fonctionne, mais gaspille des instructions. Mieux vaut attendre l'évènement redstone. L'ordinateur en place un dans la file chaque fois qu'une entrée change, sur n'importe quelle face, y compris un changement de niveau (de 7 à 8). L'évènement ne porte aucun champ : lisez les faces qui vous intéressent quand il arrive.
while true do
os.pull_event("redstone")
print("gauche " .. rs.get("left") .. ", droite " .. rs.get("right"))
endComme un bouton donne un évènement quand on l'enfonce et quand il se relâche, et qu'un changement sur une autre face en donne un aussi, la plupart des programmes cherchent un front : l'instant où une face passe d'éteinte à allumée (front montant) ou d'allumée à éteinte (front descendant). Retenez la dernière valeur de chaque face et comparez :
local avant = {}
for _, face in ipairs(rs.sides()) do
avant[face] = rs.get(face)
end
while true do
os.pull_event("redstone")
for _, face in ipairs(rs.sides()) do
local maintenant = rs.get(face)
if maintenant > 0 and avant[face] == 0 then
print(face .. " s'allume")
elseif maintenant == 0 and avant[face] > 0 then
print(face .. " s'éteint")
end
avant[face] = maintenant
end
endUn programme qui attend dans os.pull_event lit les faces moins d'un tick après le changement : il voit toutes les impulsions ordinaires, même celle de 2 ticks d'un observateur. Un programme occupé ailleurs, ou qui dort entre deux lectures, peut regarder trop tard et trouver une impulsion courte déjà terminée : gardez ces programmes dans une boucle principale, ou allongez les impulsions avec un Extenseur d'impulsions de Create.
Régler les sorties
rs.set(face, puissance) envoie de la puissance par une face : un nombre de 0 à 15, ou true (15) et false (0). Au-delà de 15, la valeur compte pour 15 ; en dessous de 0, pour 0. Un nombre à virgule arrête le programme avec bad argument #2 to 'set' (number has no integer representation) : arrondissez-le d'abord avec math.floor.
local niveau = 11.6 -- une valeur calculée par le programme
rs.set("top", true) -- la lampe du dessus s'allume
rs.set("right", 8) -- mi-puissance, pour une ligne de comparateurs ou un Tube Nixie
rs.set("left", math.floor(niveau)) -- 11
print(rs.get_output("top")) -- ce que l'ordinateur envoie sur le dessus : 15L'ordinateur donne une puissance forte, comme un bloc de redstone : la lampe ou l'Embrayage qui touche la face s'active, et un bloc plein contre la face transmet le signal à ce qui le touche.
rs.get_output(face) renvoie ce que l'ordinateur envoie sur une face. rs.get(face) est ce qu'il reçoit : ce sont deux choses distinctes, et un programme peut se servir des deux sur la même face.
Appliqué à la fin du tick
Les changements de sorties ne partent pas tout de suite vers le monde : ils sont appliqués une fois, à la fin du tick où le programme s'est exécuté, avec la dernière valeur demandée. Une boucle qui allume et éteint une face mille fois dans un tick ne coûte donc au monde qu'une seule mise à jour, et le serveur ne rame jamais.
Le revers de la médaille : allumer puis éteindre dans le même tick ne fait aucune impulsion.
rs.set("top", true)
rs.set("top", false) -- même tick : la lampe ne voit jamais le 15
rs.set("top", true)
sleep(0.05) -- un tick : le monde voit le 15
rs.set("top", false) -- une impulsion d'un tickLa même règle vaut pour les Liaisons de redstone et pour la vitesse d'un Contrôleur de vitesse de rotation.
Relâchées quand l'ordinateur s'arrête
| ce qui se passe | les sorties |
|---|---|
| le programme se termine, plante, ou est arrêté par Ctrl+T | restent telles quelles |
| l'ordinateur cesse de tourner (pas de rotation, surcharge) | restent : l'ordinateur est figé |
| l'ordinateur redémarre, s'éteint, ou son chunk se décharge | relâchées : toutes les faces à 0, toutes les Liaisons de redstone muettes |
Une lampe allumée par un programme reste donc allumée après la fin du programme, jusqu'à ce que quelque chose l'éteigne ou que l'ordinateur redémarre. Et un programme qui démarre après un redémarrage trouve toutes les sorties à 0 : mettez-les dans un état connu au début.
Quand une sortie fait tourner une machine, pensez au plantage. Lancez le programme dans pcall et remettez tout en sécurité quoi qu'il arrive :
local function principal()
-- le vrai programme : fait tourner la chaîne de presses...
end
local resultat = pcall(principal)
rs.set("left", true) -- l'Embrayage de gauche arrête la chaîne, quoi qu'il se soit passé
if not resultat.ok then
print("chaîne arrêtée : " .. resultat.error)
endCtrl+T ne s'intercepte pas : après lui, les sorties restent comme elles étaient.
Les Liaisons de redstone de Create
Une Liaison de redstone envoie un signal redstone à travers les airs à toutes les liaisons de la même fréquence, une paire d'objets placés dans ses deux emplacements. L'ordinateur est lui-même une Liaison de redstone, pour 32 fréquences à la fois au plus, dans les deux sens :
link.set(a, b, puissance)émet sur la fréquence formée des objetsaetb(des identifiants d'objets comme"minecraft:iron_ingot"; un emplacement vide vaut"minecraft:air"). La puissance va de 0 à 15, outrue/false, comme pourrs.set.link.get(a, b)renvoie la plus forte puissance émise par les autres liaisons de cette fréquence à portée. L'ordinateur n'entend jamais son propre signal.
Les liaisons portent à 256 blocs par défaut (le réglage serveur linkRange de Create), dans les chunks chargés, et transmettent le niveau complet de 0 à 15. Un identifiant d'objet erroné arrête le programme avec unknown item 'minecraft:iron_ingt' ; une 33e fréquence avec too many link frequencies (max 32).
Dès qu'un programme a utilisé une fréquence (avec link.get ou link.set), chaque changement de la puissance reçue dessus place dans la file un évènement link avec les deux objets et la nouvelle puissance. Pour écouter une fréquence, lisez-la donc une fois, puis attendez :
-- un levier à distance : la lampe du dessus recopie la fréquence fer + redstone
local A, B = "minecraft:iron_ingot", "minecraft:redstone"
rs.set("top", link.get(A, B))
while true do
local e = os.pull_event("link")
if e.a == A and e.b == B then
rs.set("top", e.power)
end
endEt pour piloter une machine lointaine, posez à côté d'elle une Liaison de redstone en mode réception avec les deux mêmes objets, puis émettez :
link.set("minecraft:iron_ingot", "minecraft:gold_ingot", true) -- le pont se lève
sleep(10)
link.set("minecraft:iron_ingot", "minecraft:gold_ingot", false) -- et redescendTous les signaux de Liaison de redstone de l'ordinateur s'arrêtent quand il redémarre, s'éteint ou se décharge.
Une Liaison de redstone comme périphérique
Taper des identifiants d'objets est source d'erreurs, et changer de fréquence oblige à modifier le programme. À la place, posez une Liaison de redstone contre l'ordinateur (ou sur son Câble de données), et mettez les objets dans ses emplacements, dans le monde. Comme périphérique, elle offre les mêmes get et set, sur sa fréquence :
local liaison = peripheral.find("redstone_link")
local f = liaison.frequency()
print("fréquence : " .. f.a .. " + " .. f.b)
liaison.set(15) -- tous les récepteurs de cette fréquence s'allument
print(liaison.get()) -- ce que les autres liaisons y envoientC'est toujours l'ordinateur qui émet et qui écoute : le bloc ne fait que nommer la fréquence, et changer les objets de ses emplacements règle le programme sur une autre fréquence sans toucher au code. Voir Liaison de redstone pour frequency et is_receiver.
Les appareils qui ont leurs propres sorties
Certains blocs du mod obéissent seuls à la redstone, et offrent à un ordinateur un contrôle plus fin comme périphériques :
- Feu tricolore (
Feu tricolore). Sans ordinateur, il suit la plus forte entrée redstone : 0 éteint, 1 à 4 rouge, 5 à 7 rouge et orange, 8 à 11 vert, 12 à 14 orange, 15 orange clignotant.rs.set(face, 9)passe donc au vert un feu posé contre l'ordinateur. Comme périphérique,set("green")en prend le contrôle, et le feu ignore alors la redstone jusqu'àrelease(), même après la fin du programme ou un redémarrage. - Boucle de détection (
Boucle de détection). Elle donne 15 tant que quelque chose se trouve au-dessus (créatures, joueurs, wagonnets, bateaux, véhicules de Create Aeronautics) : une boucle contre l'ordinateur déclenche donc des évènementsredstone. Comme périphérique,count()dit combien. - Brûleur à air chaud de Create Aeronautics (
Brûleur à air chaud). Sa flamme suit la redstone qu'il reçoit :rs.set(face, 15)quand il touche l'ordinateur, une Liaison de redstone sinon.
Piloter Create
Beaucoup de blocs de Create changent de comportement quand ils sont alimentés. Un ordinateur qui règle leur redstone mène toute la machine :
| bloc de Create | une fois alimenté |
|---|---|
| Embrayage | coupe la rotation : tout ce qui suit s'arrête |
| Inverseur de rotation | inverse le sens de rotation qui suit |
| Inverseur de rotation séquencé | exécute sa liste de mouvements programmée, puis attend le signal suivant |
| Chaine de transmission ajustable | change le rapport de vitesse, de 1 à 2 selon le niveau analogique |
| Tube Nixie | affiche le niveau de puissance, de 0 à 15 |
| Liaison de redstone (mode émission) | envoie le signal à ses récepteurs |
Le Contrôleur de vitesse de rotation n'écoute pas la redstone : un ordinateur règle sa vitesse comme périphérique, avec kinetic.set_speed() (voir Blocs cinétiques de Create). Le même périphérique cinétique lit la vitesse et le stress de n'importe quel bloc de Create.
local controleur = peripheral.wrap("top") -- un Contrôleur de vitesse de rotation sur le dessus
controleur.set_speed(64) -- la chaîne tourne maintenant à 64 tr/minUne chaîne de presses avec un Embrayage
Un tapis de Presses mécaniques fabrique des plaques de fer. Le moteur atteint la chaîne à travers un Embrayage posé sur la face gauche de l'ordinateur ; un Observateur intelligent qui surveille le tapis après la dernière presse est relié à la face droite. Le programme presse exactement un lot, puis arrête la chaîne :
local LOT = 64
local faites = 0
local etait_allume = rs.get("right") > 0
rs.set("left", false) -- embrayage relâché : la chaîne tourne
while faites < LOT do
os.pull_event("redstone")
local allume = rs.get("right") > 0
if allume and not etait_allume then -- une nouvelle plaque devant l'observateur
faites = faites + 1
end
etait_allume = allume
end
rs.set("left", true) -- embrayage alimenté : la chaîne s'arrête
print(faites .. " plaques de fer pressées")La sortie reste allumée après la fin du programme : la chaîne reste arrêtée jusqu'au lot suivant.
Inverser avec un Inverseur de rotation
Un pont-levis sur un Roulement mécanique, un monte-charge sur une Poulie à corde : le même moteur les déplace dans les deux sens, un Inverseur de rotation choisit lequel. Avec un inverseur sur la face droite, un seul bouton à gauche le bascule :
local monte = false
local etait_appuye = false
while true do
os.pull_event("redstone")
local appuye = rs.get("left") > 0
if appuye and not etait_appuye then
monte = not monte
rs.set("right", monte) -- inverseur alimenté : l'autre sens
end
etait_appuye = appuye
endLancer un Inverseur de rotation séquencé
Un Inverseur de rotation séquencé exécute une liste de mouvements réglée dans son écran (« tourner de 90°, attendre, revenir ») chaque fois qu'il reçoit un signal. L'ordinateur décide quand : ici, chaque fois qu'un train passe devant l'Observateur de train relié à la face gauche (une plaque de pression ou n'importe quel détecteur marche de la même façon) :
while true do
os.pull_event("redstone")
if rs.get("left") > 0 then
rs.set("top", true) -- l'inverseur séquencé du dessus lance sa séquence
sleep(0.1)
rs.set("top", false) -- prêt pour le train suivant
end
endExemple : un générateur d'impulsions
Une fonction qui envoie un nombre d'impulsions, d'une longueur et d'un espacement choisis : pour alimenter un distributeur, lancer plusieurs fois un inverseur séquencé, ou faire clignoter une lampe.
local function impulsions(face, nombre, duree, pause)
for i = 1, nombre do
rs.set(face, true)
sleep(duree)
rs.set(face, false)
sleep(pause)
end
end
impulsions("top", 5, 0.1, 0.4) -- cinq impulsions courtes, deux par seconde
while true do
impulsions("right", 1, 0.5, 0.5) -- puis une horloge régulière à 1 Hz à droite
endL'impulsion la plus courte dure un tick (sleep(0.05)), et les durées s'arrondissent au tick supérieur. Sur un ordinateur lent, le code entre deux pauses prend aussi du temps : voir Vitesse, mémoire et limites.
Exemple : compter les objets d'un entonnoir
Un Observateur intelligent posé contre un entonnoir donne une impulsion chaque fois que des objets le traversent. Relié à la face gauche, il permet à l'ordinateur de compter ce qui sort d'une chaîne de Presses mécaniques, et de l'afficher sur son écran et sur un Panneau d'affichage (par une Liaison d'affichage pointée sur l'ordinateur) :
local compte = 0
local etait_allume = rs.get("left") > 0
local function afficher()
term.clear()
term.set_cursor(1, 1)
print("Plaques de fer : " .. compte)
display.set({"Plaques de fer", tostring(compte)})
end
afficher()
while true do
os.pull_event("redstone")
local allume = rs.get("left") > 0
if allume and not etait_allume then
compte = compte + 1
afficher()
end
etait_allume = allume
endUn entonnoir peut déplacer plusieurs objets d'un coup : chaque impulsion est alors un transfert, pas un objet. Pour compter les objets exactement, lisez plutôt l'inventaire d'arrivée comme périphérique (inventory.count()).
Exemple : une sortie codée en binaire
Une face peut porter 16 niveaux, mais un fil de redstone perd un niveau par bloc, et certaines machines ne comprennent qu'allumé ou éteint. Quatre faces utilisées comme quatre bits portent un nombre de 0 à 15 avec de simples signaux allumé/éteint : pour allumer une lampe parmi 16 à travers un décodeur, ou choisir une destination parmi 16 avec quatre Liaisons de redstone.
local BITS = {"left", "right", "top", "bottom"} -- valent 1, 2, 4 et 8
local function afficher_binaire(n)
local allumees = {}
for i, face in ipairs(BITS) do
local allume = (n // 2 ^ (i - 1)) % 2 == 1
rs.set(face, allume)
if allume then
table.insert(allumees, face)
end
end
return allumees
end
print(table.concat(afficher_binaire(11), " "))
print(table.concat(afficher_binaire(4), " "))left right bottom top
11 vaut 8 + 2 + 1 : les faces qui valent 8, 2 et 1 sont allumées. (n // 2 ^ (i - 1)) % 2 est le bit numéro i de n. Les quatre faces changent dans le même tick, puisque les sorties sont appliquées ensemble à la fin du tick : ce qui les lit ne voit jamais un nombre à moitié écrit.