Vendetta — herbouwd op PHP 8
Een Nederlandstalig tekst-rollenspel in de onderwereld. Misdaden plegen, auto's
stelen, handelen in drank en drugs, een familie opbouwen, een casino bezitten en
concurrenten uit de weg ruimen.
Dit is een complete herbouw van de oude Black Vendetta-base uit ongeveer 2005.
Niet opgelapt — opnieuw geschreven. Van de oude code is geen regel overgebleven.
Waarom een herbouw en geen reparatie
De oude base start niet meer op moderne hosting, en dat is niet één probleem maar
tien tegelijk: `mysql_*` is uit PHP verdwenen (2.022 aanroepen), 51 van de 91
bestanden gebruikten short open tags, 34 bestanden gebruikten kale woorden als
string wat in PHP 8 een fatale fout is, en het adminpaneel had `register_globals`
nodig. Daarbovenop zat er SQL-injectie in 66 bestanden en kon je via login.php
inloggen als wie je maar wilde.
Repareren betekent elk van die dingen apart aanpakken en dan nóg met een
frameset-interface zitten die niet op een telefoon werkt. Opnieuw beginnen was
sneller en levert iets op dat je over vijf jaar nog kunt onderhouden.
Waarom een herbouw en geen reparatie
De oude base start niet meer op moderne hosting, en dat is niet één probleem maar
tien tegelijk: `mysql_*` is uit PHP verdwenen (2.022 aanroepen), 51 van de 91
bestanden gebruikten short open tags, 34 bestanden gebruikten
string wat in PHP 8 een fatale fout is, en het adminpaneel had `register_globals`
nodig. Daarbovenop zat er SQL-injectie in 66 bestanden en kon
inloggen als wie je maar wilde.
Repareren betekent elk van die dingen apart aanpakken en dan nóg met een
frameset-interface zitten die niet op een telefoon werkt. Opnieuw beginnen was
sneller en levert iets op dat je over vijf jaar nog kunt onder
Hoe dit gemaakt is
De herbouw is geschreven door Claude Opus 5 van Anthropic, via Claude Code.
51 commits verspreid over drie dagen, van 30 juli tot 1 augustus 2026.
Dat is geen "AI heeft een knop ingedrukt". Het werk ging zo: de eisen, de
spelregels en de keuzes kwamen van mij. Claude las de oude base bestand voor
bestand uit, zocht uit wat er werkelijk gebeurde, schreef het opnieuw en
schreef er testscripts bij die controleren wát er is gebeurd — niet of er iets
op het scherm staat. Fouten in het uiterlijk kwamen boven water met
schermafdrukken van mijn kant; die kan een model niet zien.
Ik ben er eerlijk over omdat je het toch merkt: de code is opvallend consequent
en er staat overal commentaar bij dat uitlegt wáárom iets zo is, meestal met
verwijzing naar wat er in het origineel op die plek misging. Dat is de winst.
Beoordeel het gewoon op wat het doet.
Wat er in zit
Misdaad
- Misdaden met afkoeltijden, oplopend in risico en opbrengst
- Organised Crime — samen met anderen een klus draaien
- Route 66 — de grote overval
- Auto's stelen, met een garage om ze in te zetten
Handel en geld
- Drank en drugs kopen en verkopen, met prijzen die per stad verschillen
- Transport tussen acht steden, en een rijschool om beter te kunnen rijden
- Bank, winkel en zwarte markt
- Kogelfabriek, zowel je eigen als die van de familie
- Bloedbank
Gokken
- Fruitmachine, roulette en blackjack
- Spelers kunnen een casino kópen; de kas gaat naar de eigenaar
- Loterij met echte trekking, krasloten, nummerraden en autora
Strijd
- Moorden met kogels, waarbij bescherming en lijfwachten meetellen
- Hitlist
- Detectivebureau om ondergedoken spelers op te sporen
- Gevangenis, met de mogelijkheid jezelf of anderen vrij te kopen
Sociaal
- Families met rangen, promoties, een kas en een eigen kogelfabriek
- Trouwen
- Forum met categorieën, privéberichten, vriendenlijst
- Nieuws, polls, eerpunten, wall of shame, uitnodigingen
- Profielen met eigen tekst en foto
Premium
- Diamanten die je bij toeval vindt tijdens een misdaad (standaard 1 op 500)
- Premium van veertien dagen: voor 250 diamanten of via Ko-fi
- Zonder premium elke 25 paginaweergaven een advertentiepagina
beheerder zelf je HTML in plakt — dus je kiest je eigen advertentienetwerk
- Premium geeft géén spelvoordeel. Dat is een bewuste keuze: het neemt alleen
de advertenties weg
Beheer
Zestien beheerpagina's plus een overzicht, op vier rechtennive
moderator, beheerder, eigenaar): spelers zoeken en aanpassen, bannen op naam of
IP, multi-accounts toestaan, items beheren, gevangenis, forum, nieuws, polls,
waarschuwingen, premium toekennen en instellen hoe ooggetuigen
Wat in het origineel nooit werkte
Dit is het deel waar de meeste tijd in ging. Veel van wat de oude base leek te
hebben, deed niets:
| Onderdeel | Wat er aan de hand was |
|---|---|
| Loterij | Verkocht loten, er vond nooit een trekking plaats. |
| Familiekas | Kon niet gevuld worden |
| Promotie uitbetaling | werd weggeschreven maar nooit uitgelezen |
| Rijbewijs | Onhaalbaar door rekenfouten |
| Zwarte markt | De bijbehorende SQL tabellen ontbraken volledig |
| Polls | Admin poll deed simpelweg gewoon niks |
| Respect overzichten | Werd nooit iets in weergegeven, altijd leeg |
| Forum opruiming | Werd nooit uitgevoerd |
| Vrijgekocht melding | Werd nooit getoond/verzonden |
Dat is allemaal alsnog gebouwd, niet weggelaten.
Nieuwe spelregels
Doodgaan is een doorstart. In het origineel was dood definitief en werd je
naar register.php gestuurd — waarmee doodgaan neerkwam op een
Nu start je account opnieuw op: je verliest rang, geld, wapens, auto's, familie
en bezit, maar houdt je gebruikersnaam, profiel en lopende donaties. Een teller
houdt bij hoe vaak je gestorven bent. Omdat er geen reden meer
tweede account, geldt één account per IP-adres en per e-mailadres, dode
meegeteld — met uitzonderingen die de beheerder zelf kan inste
Moorden is anoniem. Het slachtoffer ziet alleen het afscheidsbericht, niet
wie het deed. Bij elke moord krijgen twee spelers een ooggetuigenbericht, en die
verklaring is als item te koop aan te bieden op de zwarte mark
je omlegde, dan moet je die getuigenis kopen. De beheerder kiest hoe getuigen
worden aangewezen: onder wie op dat moment online is, onder wie in dezelfde stad
is, of volledig willekeurig.
Technieken
Geen frameworks, geen Composer, geen build-stap. Kaal PHP 8 met PDO, en 167
regels vanilla JavaScript. Er is niets te compileren, niets te installeren en
geen `vendor/`-map. Je pakt het uit en het draait.
Eén bestand per pagina, geen router. Wat in de adresbalk staat is een bestand
op schijf. Dat is op shared hosting het meest voorspelbaar en je hebt er geen
rewrite-regels voor nodig. Adressen zónder `.php` kunnen wel, als instelling —
dat vraagt mod_rewrite, dus het staat standaard uit.
PDO met echte prepared statements. `ATTR_EMULATE_PREPARES` staat uit, dus de
database ontvangt query en gegevens gescheiden. Geen enkele variabele komt een
query in.
Geldtransacties die niet lek zijn. Alles gaat via `afboeke
`bijschrijven()`, binnen een transactie met een rijvergrendeling. De voorwaarde
zit in de UPDATE zelf (`WHERE zak >= ?`), zodat twee gelijktijdige verzoeken niet
allebei kunnen slagen. In het origineel werd het saldo uitgelezen, in PHP
berekend en teruggeschreven — precies de manier waarop je geld
Escape-first opmaak. BBCode van spelers wordt eerst volledig onschadelijk
gemaakt, en daarna wordt alleen teruggezet wat uitdrukkelijk mag. Nooit
andersom. De `[inc]`-tag die in het origineel een willekeurige externe pagina in
je postvak zette — kant en klaar voor een nagemaakt inlogscherm — is bewust niet
overgenomen.
CSRF op elk formulier, en geen enkele handeling achter een gewone link. Een
<a href="?actie=verwijder"> is te activeren door een plaatje op een andere
site; dat kwam in het origineel volop voor.
Wachtwoorden met `password_hash()`, niet met MD5.
InnoDB en utf8mb4 door het hele schema, met bigint voor geldbedragen. Het
origineel gebruikte MyISAM en ISO-8859-1, waardoor "knieën" als "knie<?>n"
op het scherm kwam.
Cron die twee kanten op kan. Heeft je host een cronjob, dan gebruik je die.
Heeft hij die niet, dan lift de cron mee op paginabezoek. Dubbel draaien is
uitgesloten via een databaselock.
Mobiel bruikbaar. Donker thema in blauw, met een statusstrook onder de
kopbalk, een vaste onderbalk met vijf tabs en het zijmenu als uitschuifbare la.
Alles werkt ook zonder JavaScript.
Meegeleverd
Vijf testscripts die het spel over HTTP aansturen zoals een speler dat doet:
- elke pagina laadt schoon (alle 71)
- de geldbalans klopt na bank, winkel, casino, moord en cron
- 17 XSS-payloads worden geneutraliseerd, rechten kloppen per niveau, elk
formulier heeft een CSRF-token
- de indeling klopt per toestand (uitgelogd, ingelogd, dood)
- geen enkele link bevat nog een `.php` als je mooie adressen aanzet
Documentatie in `docs/`: installatie, beheer, architectuur, ontwikkelen, en
een verslag dat per onderdeel vertelt wat er in het origineel kapot was en wat
ervoor in de plaats is gekomen.
Vereisten
- PHP 8.1 of nieuwer, met `pdo_mysql` en `mbstring`
- MySQL 5.7+ of MariaDB 10.2+
- De `gd`-uitbreiding wordt aangeraden voor de beveiligingscode; er is een
tekstalternatief als je host hem niet heeft
- Geen SSH nodig. FTP en phpMyAdmin is genoeg
Installeren
Lees hiervoor de laatste Read Me op github.
Licentie
MIT. Gebruiken, aanpassen en verspreiden mag, ook commercieel, zolang de
licentietekst bij je kopie blijft. Er zit geen garantie op.
Let op: het logo en de plaatjes in `images/` en `smilies/` komen deels uit de
originele base uit 2005 en vallen daar niet vanzelfsprekend onder. Wil je het
spel echt live zetten, vervang die dan of controleer zelf of je ze mag gebruiken.
Files
-
Vendetta Github
0 downloads