Redstone Gold Block

Flag: CYBN{JE_F4IS_D3S_M4IS0NS_3N_C0BBL3}

Challenge

Description


Ici tu trouveras la meilleure sélection de bloc de la région !

Format du flag : CYBN{Tu_Ad0pT3s_un_Bl0Cs_P01nT_c0M}

(Version : 1.14)

Solution

Le fichier est un .mca, c'est un fichier region. Il contient l'ensemble des blocs sur une zone de 512 par 512 (un chunk fait 16x16 blocs et la region contient 32x32 chunks).

Si on n'a pas Minecraft pour remplacer le fichier région d'une map déjà créée, on peut quand même avoir un aperçu avec un tool comme MCASelector :

Le titre du challenge est assez explicite, Redstone Gold Block -> RGB, on va devoir transformer ce fichier en image.

Chaque bloc est représenté par un identifiant. L'identifiant est désormais une chaîne de caractères, mais pendant longtemps, c'était un nombre codé sur 1 octet.

La stratégie : utiliser chaque bloc comme un canal RGB (bloc 0 -> R, bloc 1 -> G, bloc 2 -> B, bloc 3 -> R, ...). On va reconstituer une image pixel par pixel. En python, une librairie comme anvil-parser permet de parser le fichier .mca et récupérer les blocs.

J'ai utilisé ce fichier json contenant l'ensemble des blocs et leur id, je l'ai simplement scrappé depuis le site https://minecraft-ids.grahamedgecombe.com avec le code suivant :

[...document.querySelector('table').querySelectorAll('tr')].map(o => ({id: o.children[0].textContent.split(':')[0], text: o.children[2].textContent.split(':')[1].split(')')[0]}))
from anvil import Region, Chunk
import json
from PIL import Image

with open('rgb-minecraft-data.json') as f:
  data = json.loads(f.read())
BLOCKS = {}
for b in data:
  if b['id'] in BLOCKS:
    continue
  BLOCKS[b['text']] = int(b['id'])


region = Region.from_file('r.0.0.mca')
chunks = [[Chunk.from_region(region, x, y) for y in range(32)] for x in range(32)]
blocs = [[BLOCKS[chunks[x // 16][y // 16].get_block(x % 16, 0 , y % 16).id] for x in range(512)] for y in range(512)]

data = []
width = 512
height = 512
img = Image.new('RGB', (width, height))
for i in range(0, width * height):
  rgb = []
  for j in range(i*3, i*3+3):
    x = i % width
    y = i // width
    bloc = chunks[x // 16][y // 16].get_block(x % 16, 0, y % 16)
    rgb.append(BLOCKS[bloc.id])
  if len(rgb) < 3:
    rgb = [0, 0, 0]
  img.putpixel((x, y), tuple(rgb))
img.resize((1024, 256)).show()

j'ai resize l'image pour une question de lisibilité, mais on obtient :

Ensuite, on décode l'alphabet galactique :

Dernière mise à jour

Cet article vous a-t-il été utile ?