Tulio Paschoalin Leao

O sistema de correções de problemas de cenário do OpenRCT2

· Tulio Paschoalin Leao · 10 min


Esse artigo foi escrito originalmente para o blog do OpenRCT2.


Introdução

Estamos no ano 2000 e acabei de chegar em casa vindo da escola. Ligo o meu computador e fico quieto olhando fixamente para o grande monitor de tubo, enquanto espero os três minutos que leva para que a máquina termine de iniciar. Abro o jogo RollerCoaster Tycoon no cenário Lago Frondoso, que estava jogando freneticamente no dia anterior, e rumo para construir a nova atração que tenho em mente. Tenho de comprar mais terrenos para conseguir, então começo a fazê-lo, até que percebo que há um quadradinho em particular que não é comprável. Fico atônito e me pergunto: por quê 😨?

Captura de tela do cenário Lago Frondoso do RollerCoaster Tycoon mostrando um único quadrado de terreno não adquirido em meio a vários outros comprados.

Os jogos RollerCoaster Tycoon originais contavam com alguns problemas de configuração dos cenários e dentre esses o de posse do terreno era o mais disruptivo: terrenos ou direitos de construção que deveriam ser compráveis ou estarem disponíveis não estavam. Não que eu fosse experiente o suficiente para ter notado isso àquela época, tanto que a história acima é completamente fictícia, mas isso incomodava, com razão, algumas pessoas que eventualmente deram um jeito de corrigir os cenários quando fossem carregados no OpenRCT2, e é aqui que a história realmente começa.

Correções de cenário do OpenRCT2 ao resgate!

Havia correções para os cenários dos jogos originais aparecendo no código do OpenRCT2 tão cedo quanto a versão v0.0.6 do OpenRCT2, há 8 anos, e com o passar do tempo elas continuaram aparecendo sempre que um par de olhos afiados de um de nossos jogadores as avistava e decidia fazer a coisa certa1. A maioria dessas mudanças era funcional, como consertar a disponibilidade do terreno acima no Lago Frondoso ou inverter a entrada e a saída do Carrossel do Parque Urbano, mas também havia mudanças cosméticas e elas estavam começando a deixar o código muito desorganizado2. Contudo, o sistema estava funcionando por anos a fio, e parecia que nada mudaria e foi aí que apareceu a sugestão de mudança #19740.

Essa mudança sozinha adicionaria mais de 200 linhas de código, majoritariamente para arrumar a altura da linha d’água de bordas de lago que não estavam configuradas apropriadamente (e portanto não pareciam um corpo d’água normal onde a água se autonivela). Foi um trabalho ótimo e meticuloso feito por @HtotheTML, mas tivemos receio de alimentar ainda mais nosso pequeno monstro de correções, então decidimos que precisávamos introduzir uma nova maneira de submeter correções ou parar de aceitá-las como um todo, já que se tornara difícil de mantê-las. Esse foi o fim da história por cerca de 4 meses, até que decidi ajeitar a postura e encarar esse desafio.

O surgimento dos arquivos .parkpatch

O principal objetivo de criar um novo sistema de correções para os cenários do OpenRCT2 foi de remover o código feio e verboso das nossas rotinas de carregamento e ter apenas um código genérico capaz de lidar com os arquivos de correção. Não foi o único objetivo, no entanto, também queríamos tornar mais fácil para as pessoas contribuírem com reparos, já que qualquer jogador pode perceber um erro e não deveria ser preciso que saibam programar absurdamente para poderem corrigi-lo.3. Com essa mentalidade, decidimos armazenar as correções de cada cenário em um arquivo JSON diferente, e é assim que um deles se parece, o do Parque Urbano4:

 1{
 2    "scenario_name": "Urban Park",
 3    "sha256": "835ec8bdba3dc4086906126907c022cf42fa0f9cd6ee06221f36aac526ac4ec4",
 4    "land_ownership": {
 5        "available": {
 6            "coordinates": [
 7                [ 34, 60 ], [ 34, 61 ], [ 35, 60 ], [ 35, 61 ],
 8                [ 48, 19 ], [ 48, 20 ],
 9                [ 52, 15 ], [ 53, 15 ], [ 54, 15 ], [ 55, 15 ],
10                [ 52, 16 ], [ 53, 16 ], [ 54, 16 ], [ 55, 16 ],
11                [ 52, 17 ], [ 52, 18 ], [ 52, 19 ],
12                [ 64, 77 ], [ 61, 66 ], [ 61, 67 ], [ 39, 20 ]
13            ]
14        },
15        "construction_rights_available": {
16            "coordinates": [
17                [ 46, 47 ]
18            ]
19        }
20    },
21    "rides": [
22        {
23            "id": 0,
24            "operation": "swap_entrance_exit"
25        }
26    ]
27}

Pode não parecer menos verboso, mas lembre-se que tudo isso foi removido do código e é agora um conjunto de arquivos. Vamos percorrer cada chave a qual damos suporte desse JSON e explicar seu objetivo.

  1. scenario_name (“nome do cenário”): Puramente para tornar o .parkpatch facilmente compreensível para humanos, sem nenhum propósito durante o jogo5.

  2. sha256: A hash do arquivo de cenário utilizando SHA256. O sistema de correções antigos era muito suscetível a erros, dependendo de uma combinação de metadados internos e do nome do arquivo do cenário para ser capaz de encontrar o arquivo de correções de um dado parque. Isso porque alguns cenários tiveram erros de configuração advindos de “copiar e colar” e foram todos internamente nomeados de “Montanha Mágica Six Flags”. Utilizar a hash nos dá uma maneira unificada de identificar um cenário e o seu arquivo de correções correspondente6, que simplifica o código ao substituir uma longa série de comparações de texto do tipo se...senão com uma simples conversão hash seguida por verificar se o arquivo <hash>.parkpatch existe7.

  3. land_ownership (“posse do terreno”): Permite controlar se um terreno deve ser:

    • indisponível: nem parte do parque, nem adquirível em nenhuma condição.
    • adquirido: já parte do parque.
    • direito de construção adquirido: Permite ao jogador construir sob/sobre o terreno, mas não no terreno em si e nem modificá-lo.
    • disponível para compra: pode ser adquirido para controle total.
    • direitos de construção disponíveis para compra: pode-se comprar o direito de construção.

    A maioria dos cenários coberta no sistema de correções antigo apenas corrigia a posse do terreno, então daí partiu o grosso da migração. Houve casos interessantes de cenários que já estavam parcialmente consertados em suas versões do RollerCoaster Tycoon Classic, como o Mundo de Katie, o que favoreceu o nosso modelo de um arquivo de correções por cenário, já que mesmo sendo parques iguais, eles precisavam de reparos diferentes.

  4. water (“água”): Permite mudar a altura da água de um terreno específico, dado que algumas vezes ela não aparentava se comportar de forma natural, como mostrado na captura de tela abaixo.

  5. operations (“operações”): Deixa que os elementos de pista sejam consertados, como na “Splashster” do Aventura Uluru que nunca passava da primeira descida por conta de um canal d’água mal posicionado.

  6. rides (“atrações”): Permite modificar as atrações em si, como inverter a entrada e a saída do carrossel do Parque Urbano, já mencionado anteriormente.

Captura de tela do cenário *Six Flags Holanda* do *RollerCoaster Tycoon 2* mostrando um terreno onde a água estranhamente não está nivelada com o resto do corpo d'água e a margem.

Pode parecer que tínhamos tudo planejado desde o começo e que foi uma série de mudanças bem direta e fácil para chegar à versão final, mas garanto que não foi. Levei cerca de 2 meses e 30 mudanças para ter tudo funcionando como esperado e um semestre para que tivesse as mudanças incorporadas ao repositório, enquanto o time e a comunidade me ajudavam com sugestões e revisões cuidadosas para que não quebrasse nada no processo. Não vou à fundo nos detalhes do algoritmo de correções, porque a manipulação de JSON não é muito empolgante, mas fique à vontade para dar uma olhada!

O futuro do .parkpatch

Ao longo do caminho da migração dessas correções para os arquivos JSON, notei que havia espaço para muitas melhorias no código, algumas das quais fiz de uma vez, outras que deixei para serem feitas posteriormente, pois não queria arrastar essas mudanças para sempre. Eis aqui algumas ideias, caso alguém queira se arriscar, tenha em mente que as que já não estiverem registradas no repositório devem ser discutidas antes com o time:

Sumarizando

A partir da versão v0.4.14, seu OpenRCT2 estará corrigindo os cenários de uma forma diferente, mas nosso objetivo é que você nem consiga perceber! Do jeito que foi desenvolvido, você pode esperar ver várias novas linhas de correções de cenário nos nossos arquivos de mudança de versão e esperamos que isso motive alguns de vocês a contribuir e que torne mais divertida a experiência de toda a comunidade 🥳.

Mãos às correções!


  1. Vou deixar como exercício para o leitor definir se esse esforço era: motivado pela raiva de encontrar um terreno mal configurado, TOC de ter as coisas simétricas/alinhadas ou apenas heroísmo. ↩︎

  2. Era assim que se fazia para corrigir as posses de terreno de um cenário de RCT2, 600 linhas! ↩︎

  3. Ainda não é super fácil por causa dos hashes, mas já parece um pouco mais amigável. ↩︎

  4. Por favor não se incomode com a inconsistência de escolha entre chaves e colchetes. ↩︎

  5. Na verdade é utilizado para imprimir mensagens de depuração, mas esse é um pequeno detalhe de desenvolvedor. ↩︎

  6. Enquanto traduzia o artigo me deu muita vontade de traduzir patch para remendo 😂. ↩︎

  7. Utilizamos apenas os 7 primeiros caracteres da sequência SHA para o nome do arquivo, para prevenir que eles sejam muito longos, mas conferimos que a sequência toda é equivalente quando abrimos o arquivo de correção. Colisões são muito incomuns, mesmo assim não custa ter certeza, né? ↩︎

  8. Na verdade já estou fazendo isso e fiz um plugin para auxiliar, que deve ser tema de um artigo futuro! ↩︎

  9. Sei que pode não parecer mais simples nesse exemplo, mas imagine que você tenha um retângulo especificado por 20 coordenadas e em vez de listar todas, você apenas lista o início e o fim do retângulo, 2 coordenadas. É uma simplificação considerável do JSON, ao custo de um pouco mais de complexidade no C++. ↩︎

#código-aberto #c++ #openrct2

Responda a este post por email ↪