Create: Computing AgesDoc Brass
Piloter le monde

Périphériques

Les blocs que pilote un ordinateur : ce qui compte comme périphérique, les noms par face et sur un réseau de Câbles de données, wrap, find et call, et du code qui survit à un bloc retiré.

Un périphérique est un bloc avec lequel l'ordinateur peut parler : un coffre dont il compte les objets, un arbre de Create dont il lit la vitesse, un Contrôleur de vitesse de rotation dont il règle la vitesse, un Feu tricolore qu'il commute, un moniteur, une radio... La bibliothèque peripheral les trouve et fait de chacun une table de fonctions, ses méthodes.

Ce guide explique les idées : ce qui compte comme périphérique, comment ils sont nommés, comment les atteindre, et comment écrire du code qui continue de marcher quand le monde change. Chaque sorte de bloc a sa propre page avec toutes ses méthodes en détail (voir le tableau récapitulatif à la fin).

Ce qui compte comme périphérique

Un bloc est un périphérique quand il touche l'ordinateur sur l'une de ses six faces, ou quand il touche son réseau de Câbles de données (Mini-ordinateur et plus récents), et que l'ordinateur sait lui parler :

  • les blocs du mod : Feu tricolore, Boucle de détection, moniteurs, Modem radio, Routeur Wi-Fi ;
  • la Liaison de redstone de Create ;
  • tout bloc de Create qui tourne (kinetic) : arbres, moteurs, presses, le Contrôleur de vitesse de rotation... ;
  • tout bloc qui contient des objets (inventory) : coffres, tonneaux, Coffres à objet renforcés, Dépôts, machines de Create à emplacements ;
  • tout bloc qui contient des fluides (tank) : les Réservoirs à fluide de Create et leurs semblables ;
  • avec Create Aeronautics, ses capteurs et son brûleur à air chaud (Hot Air Burner).

Un simple bloc de pierre, une lampe ou un fil de redstone n'est pas un périphérique : on les atteint par la redstone (voir Redstone et liaisons de Create). Les autres ordinateurs du câble ne figurent pas non plus parmi les périphériques : les ordinateurs se parlent avec net.

Astuce

L'arbre qui entraîne l'ordinateur touche sa face back (sa face bottom pour le Microcontrôleur), et un arbre est cinétique. peripheral.wrap("back").speed() donne donc à un programme la vitesse à laquelle il tourne.

Les noms : faces et noms de réseau

Chaque périphérique a un nom, une chaîne, qui sert à l'atteindre :

  • Un bloc contre l'ordinateur porte le nom de la face qu'il touche, par rapport à l'écran : "front", "back", "left", "right", "top", "bottom" (les mêmes noms que pour rs, voir Redstone et liaisons de Create).
  • Un bloc du réseau de Câbles de données reçoit un nom de réseau : son type, un @, et ses coordonnées, comme "inventory@120,64,-35" ou "traffic_light@12,70,8". Ce sont les coordonnées qu'affiche F3 quand vous regardez le bloc. Le nom ne change jamais tant que le bloc reste en place.

Un bloc qui touche à la fois l'ordinateur et son câble a les deux noms.

peripheral.list() renvoie tous les noms, les faces d'abord, puis les noms de réseau. Avec un type, elle ne garde que les périphériques de ce type : peripheral.list("inventory"). peripheral.type(nom) donne le type de l'un d'eux, ou nil quand il n'y a rien à qui parler sur cette face.

Les réseaux de Câbles de données

À partir du Mini-ordinateur, un ordinateur a un port réseau. Les Câbles de données qui le touchent forment son réseau, et chaque bloc qui touche ces câbles devient l'un de ses périphériques, aussi loin que vont les câbles (2048 câbles au plus). Le Calculateur à tubes et l'Ordinateur à transistors n'ont pas de port : ils n'atteignent que les six blocs qui les entourent.

Quelques règles des réseaux câblés :

  • Les simples arbres, roues dentées et boîtes de vitesses le long d'un câble ne sont pas des périphériques du réseau : un câble qui longe une transmission reste propre. Les machines qui font quelque chose (une presse, un moteur, un Contrôleur de vitesse de rotation) en sont.
  • Un côté de câble frappé à la Clé de Create ne laisse rien passer : servez-vous-en pour tenir un coffre voisin du câble hors du réseau, ou pour garder séparés deux câbles côte à côte.
  • Les parties du réseau situées dans des chunks déchargés sont simplement hors de portée jusqu'à leur rechargement.
  • Le réseau est exploré de nouveau dès qu'un câble est posé ou cassé. Un bloc posé contre un câble existant peut mettre jusqu'à une seconde à apparaître dans peripheral.list().

wrap, find et call

Il y a trois façons de se servir d'un périphérique.

**peripheral.wrap(nom)** renvoie l'objet qui pilote le bloc, une table de méthodes, ou nil quand il n'y a rien. Faites-le une fois, au début, et gardez l'objet :

Brass
local coffre = peripheral.wrap("left")         -- un Coffre à objet renforcé à gauche
local presse = peripheral.wrap("kinetic@40,64,12")
print(coffre.count("minecraft:iron_ingot"))
print(presse.speed())

**peripheral.find(type)** renvoie l'objet du premier périphérique d'un type, les faces d'abord, puis le réseau. Aucun nom à taper, idéal quand il n'y en a qu'un de son espèce :

Brass
local feu = peripheral.find("traffic_light")
if feu == nil then
  error("aucun feu tricolore trouvé")
end
feu.set("green")

**peripheral.call(nom, méthode, ...)** appelle une méthode sans garder d'objet. Pratique pour un appel isolé, ou avec des noms construits par le programme :

Brass
peripheral.call("left", "set", "red")
print(peripheral.call("inventory@120,64,-35", "count"))

Il arrête le programme avec no peripheral 'left' quand rien ne répond à ce nom, et avec peripheral 'left' has no method 'sett' pour une méthode que le bloc n'a pas.

Chaque objet a aussi une méthode type() (any.type()), qui renvoie le type du bloc.

Un bloc à plusieurs types

Un bloc peut être plusieurs choses à la fois. Une Meule de Create tourne et contient des objets : elle est à la fois kinetic et inventory. Son objet a les méthodes des deux, et son type est le premier dans cet ordre : capteur d'Aeronautics, traffic_light, inductive_loop, monitor, radio_modem ou wifi_router, redstone_link, kinetic, inventory, tank.

Brass
local meule = peripheral.wrap("left")   -- une Meule à gauche
print(meule.type())                     -- kinetic
print(meule.speed() .. " tr/min, " .. meule.count() .. " objets dedans")

peripheral.type("left") dit donc "kinetic", mais peripheral.list("inventory") et peripheral.find("inventory") comptent aussi la meule : elles regardent tous les types d'un bloc, pas seulement le premier. Sur le réseau, son nom commence par son premier type : kinetic@x,y,z.

Recenser tout ce qui est branché

Un petit programme qui liste chaque périphérique avec son type et ses méthodes. Enregistrez-le sous le nom scan et lancez-le chaque fois que vous construisez quelque chose de nouveau :

scan
for _, nom in ipairs(peripheral.list()) do
  local appareil = peripheral.wrap(nom)
  local methodes = table.keys(appareil)
  table.sort(methodes)
  print(nom .. " (" .. appareil.type() .. ")")
  print("  " .. table.concat(methodes, " "))
end
Terminal
> scan
back (kinetic)
  capacity overstressed set_speed speed stress type
left (inventory)
  count get list push size type
traffic_light@12,70,8 (traffic_light)
  get release set type

Le programme fourni devices fait la même chose avec un plus bel écran.

Du code robuste : blocs retirés et déchargés

Un objet de périphérique ne contient pas le bloc lui-même : chaque appel va le chercher de nouveau à sa place. L'objet ne devient donc jamais périmé, mais un appel peut échouer quand le monde a changé :

ce qui s'est passéce que fait un appel
le bloc a été cassé ou remplacéarrête le programme : not an inventory anymore, not a kinetic block anymore, traffic light removed, monitor removed...
son chunk n'est pas chargéarrête le programme : peripheral is not loaded
rien à cet endroit au moment de wrapperipheral.wrap et peripheral.find renvoient nil

Un programme qui doit tourner des jours protège ses appels avec pcall, qui attrape l'erreur et renvoie une table {ok = true, value = ...} ou {ok = false, error = "..."} :

Brass
local coffre = peripheral.wrap("left")

local function fer_dans_le_coffre()
  if coffre == nil then
    coffre = peripheral.wrap("left")   -- il a peut-être été reconstruit
    if coffre == nil then
      return nil
    end
  end
  local r = pcall(coffre.count, "minecraft:iron_ingot")
  if r.ok then
    return r.value
  end
  coffre = nil   -- cassé ou déchargé : on refera wrap la prochaine fois
  return nil
end

while true do
  local fer = fer_dans_le_coffre()
  if fer == nil then
    print("coffre introuvable")
  else
    print(fer .. " lingots de fer")
  end
  sleep(5)
end

pcall(coffre.count, "minecraft:iron_ingot") appelle coffre.count("minecraft:iron_ingot") en attrapant son erreur. Quand le coffre revient (reconstruit, ou son chunk rechargé), le programme le retrouve au tour suivant, sans redémarrer.

Le coût des grands réseaux

Parler aux périphériques coûte des instructions, comme tout le reste (voir Vitesse, mémoire et limites). C'est le plus souvent peu, mais certains appels grandissent avec la taille du réseau :

appelinstructions
peripheral.list, peripheral.find16, plus 4 par bloc qui touche le réseau câblé
peripheral.wrap8
un nom de réseau dans wrap, type, call ou comme cible de push1 pour 4 blocs du réseau
une méthode d'un objetquelques-unes, plus son propre travail
list, count, push d'un inventaire1 par emplacement de l'inventaire
stress, capacity d'un bloc cinétique1 par bloc du réseau cinétique

Sur un réseau de 200 blocs, un peripheral.find coûte environ 800 instructions, près de trois ticks d'un Mini-ordinateur à pleine vitesse. Faites donc wrap une fois au début et gardez les objets, au lieu d'appeler find, ou call avec un nom de réseau, dans une boucle. De même, un grand Coffre à objet renforcé a des centaines d'emplacements : le compter deux fois par seconde n'est rien pour un Micro-ordinateur, mais une vraie charge pour un ordinateur lent.

Tableau récapitulatif des appareils

typeblocsméthodes principalespage
touschaque périphériqueany.type()Tous les périphériques
traffic_lightFeu tricoloretraffic_light.set(), traffic_light.get(), traffic_light.release()Feu tricolore
inductive_loopBoucle de détectioninductive_loop.detected(), inductive_loop.count()Boucle de détection
monitorMoniteur cathodique, Moniteur LCDmonitor.size()Moniteurs
radio_modem, wifi_routerModem radio, Routeur Wi-Firadio.range(), radio.get_ssid(), radio.set_ssid()Modem radio et Routeur Wi-Fi
redstone_linkLiaison de redstone de Createredstone_link.get(), redstone_link.set(), redstone_link.frequency(), redstone_link.is_receiver()Liaison de redstone
kinetictout bloc de Create qui tournekinetic.speed(), kinetic.stress(), kinetic.capacity(), kinetic.overstressed(), kinetic.set_speed()Blocs cinétiques de Create
inventorycoffres, tonneaux, Coffres à objet renforcés, Dépôts...inventory.size(), inventory.list(), inventory.get(), inventory.count(), inventory.push()Inventaires
tankRéservoirs à fluide et autres contenants de fluidestank.tanks()Réservoirs
altitude_sensor, gimbal_sensor, velocity_sensor, optical_sensor, navigation_table, swivel_bearing, torsion_springles capteurs et roulements de Create Aeronauticssensor.read() et une méthode par mesureCapteurs de Create Aeronautics
hot_air_burnerbrûleur à air chaud (Hot Air Burner) de Create Aeronauticshot_air_burner.amount(), hot_air_burner.set_amount(), hot_air_burner.filled()Brûleur à air chaud