youhide@homelab: ~/blog

$cat oddside.md

I never really left Britannia

Eu nunca saí de Britannia de verdade

There is a line in my own timeline that I wrote without noticing what it was confessing: 2000, Ultima Online, five years inside it, and then 2005, UO stops being a game and becomes a server, I move to the other side. Twenty-one years later I am still on that side of it, and I have stopped pretending that is a coincidence.

Tem uma linha na minha própria timeline que eu escrevi sem perceber o que ela estava confessando: 2000, Ultima Online, cinco anos dentro dele, e depois 2005, UO deixa de ser jogo e vira servidor, passo para o outro lado. Vinte e um anos depois eu continuo desse lado, e parei de fingir que isso é coincidência.

I am building Oddside. It is a persistent online sandbox: a medieval world you live in, work in and make your own, with skills you get by practising them rather than levels and classes, crafting, gathering, trade, housing, exploration, and PvP that has consequences. The design rule I care most about is that a peaceful producer should be able to prosper without ever fighting another player.

Estou construindo o Oddside. É um sandbox online persistente: um mundo medieval para morar, trabalhar e tornar seu, com habilidades que se ganham praticando em vez de níveis e classes, crafting, coleta, comércio, moradia, exploração, e PvP com consequência. A regra de design com que eu mais me importo é que um produtor pacífico consiga prosperar sem nunca brigar com outro jogador.

That last sentence is the whole reason the project exists. It is what Ultima Online let you be, and almost nothing since has let you be it again.

Essa última frase é a razão inteira de o projeto existir. É o que o Ultima Online deixava você ser, e quase nada depois dele deixou de novo.

The rules live on the server

As regras moram no servidor

The server is Rust. The client is Godot, and the piece that connects them is also Rust: an extension the client loads, carrying the session and the shared rules. Maps, collision, walking, reach, stamina, items and names are written once, in a crate that knows nothing about rendering, and both sides run that same code.

O servidor é Rust. O cliente é Godot, e a peça que liga os dois também é Rust: uma extensão que o cliente carrega, levando a sessão e as regras compartilhadas. Mapas, colisão, caminhada, alcance, stamina, itens e nomes são escritos uma vez, num crate que não sabe nada sobre renderização, e os dois lados rodam esse mesmo código.

Movement is validated by the server, equipment is the server's opinion, and the global cooldown and the one-action queue belong to the server too. The client is allowed to predict and to draw. It is not allowed to decide.

A movimentação é validada pelo servidor, o equipamento é opinião do servidor, e o cooldown global e a fila de uma ação só também são do servidor. O cliente pode prever e pode desenhar. Decidir, não pode.

If that sounds familiar, it is the same boundary I described for a game about plants a few posts ago. I did not plan to arrive at it twice. It turns out that once you have operated something where the client was trusted, you stop wanting to find out again.

Se isso soa familiar, é a mesma fronteira que eu descrevi para um jogo sobre plantas alguns posts atrás. Eu não planejei chegar nela duas vezes. Acontece que depois de operar uma coisa em que o cliente era confiável, você perde a vontade de descobrir de novo.

For the part that cannot be reasoned about, there are headless bots: a command that walks thirty fake players into town, because a market square is a different problem with thirty people in it than with one.

Para a parte que não dá para resolver no raciocínio existem bots headless: um comando que põe trinta jogadores falsos andando pela cidade, porque uma praça de mercado é um problema diferente com trinta pessoas dentro dela do que com uma.

Concept, or actual

Conceito, ou real

Here is the habit I am most glad I started, and it costs nothing. Every image in the project's documentation is labelled as one of two things: a concept, which is art showing where it is going, or an actual client capture, which is a photograph of the thing running and connected. Never a caption that lets you guess.

Aqui está o hábito que eu mais me alegro de ter começado, e ele não custa nada. Toda imagem na documentação do projeto é rotulada como uma de duas coisas: um conceito, que é arte mostrando para onde a coisa vai, ou uma captura do cliente real, que é a fotografia daquilo rodando e conectado. Nunca uma legenda que deixe você adivinhar.

Concept images illustrate direction. They do not establish shipped features.
Imagens de conceito ilustram direção. Elas não estabelecem funcionalidades entregues.

Alongside them there is a decisions document whose only job is to keep established direction and untested hypothesis in separate columns. A design document that does not do this becomes a sales pitch to its own author within about three months: you read your own plan, your brain files it under "done", and you start building on top of something that was never built.

Ao lado delas existe um documento de decisões cujo único trabalho é manter direção estabelecida e hipótese não testada em colunas separadas. Um documento de design que não faz isso vira um folheto de vendas para o próprio autor em uns três meses: você lê o seu plano, seu cérebro arquiva aquilo como "pronto", e você começa a construir em cima de uma coisa que nunca foi construída.

This is the same instinct as the one that makes me want a postmortem to name a cause. It is cheap to write down what you know versus what you hope, and expensive to find out later which was which.

É o mesmo instinto que me faz querer que um postmortem aponte uma causa. É barato anotar o que você sabe contra o que você espera, e caro descobrir depois qual era qual.

What you can actually walk through today

O que dá para percorrer hoje de verdade

Since I just spent a section praising honesty, here is the status without any.

Já que eu acabei de gastar uma seção elogiando honestidade, aqui está o status sem nenhuma.

  • One town. Brindlecross, the market town, with its residents, wildlife and the approach trail. It is the only map you can stand in.
  • The city the game is named after does not exist yet. Vila Antena, the contemporary dimension on the other side of the gates, was removed as a playable map; characters who were saved there now log in at Brindlecross carrying everything they had. It is a design for later.
  • The kit is a placeholder wearing a costume. Sixteen item kinds, four skills and the first two special actions are the prototype's, renamed in medieval language until the real medieval items, trades and weapons replace them.
  • Balance is not balance yet. The combat pilot is in the client and playable; the numbers behind it, the wider economy and most of the action interface are proposals waiting to be implemented and tested.
  • Uma cidade. Brindlecross, a cidade-mercado, com os moradores, os bichos e a trilha de chegada. É o único mapa em que dá para pisar.
  • A cidade que dá nome ao jogo ainda não existe. Vila Antena, a dimensão contemporânea do outro lado dos portais, foi removida como mapa jogável; personagens que estavam salvos lá agora entram em Brindlecross carregando tudo o que tinham. É um desenho para depois.
  • O kit é um provisório fantasiado. Dezesseis tipos de item, quatro habilidades e as duas primeiras ações especiais são as do protótipo, renomeadas em linguagem medieval até os itens, ofícios e armas medievais de verdade substituírem elas.
  • Balanceamento ainda não é balanceamento. O piloto de combate está no cliente e dá para jogar; os números por trás dele, a economia maior e boa parte da interface de ações são propostas esperando implementação e teste.

The world map window is the part I keep opening for no reason. It draws Brindlecross from the game's own data onto parchment, in your language, with your arrow on it and the ground you have not walked yet faded out, and a padlock on every place that is still only a plan. The map is honest too.

A janela do mapa-múndi é a parte que eu fico abrindo sem motivo. Ela desenha Brindlecross a partir dos dados do próprio jogo sobre pergaminho, no seu idioma, com a sua seta em cima e o chão que você ainda não andou apagado, e um cadeado em todo lugar que ainda é só plano. O mapa também é honesto.

Why this one, after all the others

Por que esse, depois de todos os outros

I have written a UO-compatible server engine before. I have spent most of that time making other people's systems stay up. Oddside is the first time I am building the world instead of the thing underneath the world, and it is strange to be the one deciding what a stamina bar means rather than why the node holding it ran out of memory.

Eu já escrevi uma engine de servidor compatível com UO. Passei a maior parte desse tempo fazendo os sistemas dos outros ficarem de pé. O Oddside é a primeira vez que eu construo o mundo em vez da coisa embaixo do mundo, e é estranho ser quem decide o que uma barra de stamina significa em vez de por que o nó que a segurava ficou sem memória.

It is in active development and it is not open for you to play yet. What there is lives at playoddside.com; the source is private. When Brindlecross has a second town to trade with, that will be worth its own post.

Ele está em desenvolvimento ativo e ainda não está aberto para você jogar. O que existe mora em playoddside.com; o código é privado. Quando Brindlecross tiver uma segunda cidade com quem comerciar, isso vai merecer um post próprio.