Für die neue Vinyambar-Partie habe ich mir den Spaß gemacht, Lua-bindings für Eresseas wichtigste Funktionen zu machen. Das bedeutet, ass man jetzt den Server aus lua heraus skripten kann. Der Server ist in dem Sinne nicht mal mehr strikt ein Server, er kann auch für programmatische Änderungen am Datenfile benutzt werden. Das ist cool, und sieht z.B. so aus:
function process(infile, outfile, orders)
if read_game(infile)~=0 then
print("could not read game")
return -1
end
read_orders(orders)
process_orders()
write_passwords()
write_reports()
if write_game(outfile)~=0 then
print("could not write game")
return -1
end
end
Das ist eine normale Auswertung: Datenfile laden, Befehle lesen, Befehle abarbeiten, Passworte schreiben, Reports schreiben, Datenfile wieder speichern.
Für WdW müssen wir haufenweise Parteien in Allianzen einordnen, Aussetzen, und eine Menge Einheiten mit Startitems für jede der Parteien machen. Da die Daten dafür in der Datenbank stecken, generiere ich mir einfach ein kleines lua-skript daraus:
alliance = add_alliance(13, "Einwohner von Lummerland")
position = get_position(13)
faction = make_faction(position, alliance, 5,
"bla@fasel.de", "Dämonen")
...
for faction in factions() do
local u = add_unit(faction, position)
u:set_skill("magic", 3)
u:add_item("money", 1000)
end
Das ist nur beispielhaft, das wirkliche Skript ist 200 Zeilen lang.
Das schöne ist, sowas kann ich beliebig weitertreiben. Ich brauche eine Datei, in der der aktuelle Spielstand steht? Kein Problem, einfach eine lua-funktion gemacht, die den in eine Datei rausschriebt.
Das gute daran ist, dass man verschiedene Skripte für verschiedene Vinyambars (oder Eressea) benutzen kann, aber alles den gleichen Server benutzt. Der spielbezogene Teil muss nicht neu kompiliert werden, weil die Skripte zur Laufzeit interpretiert werden.
Das ist toll. Ich kann jedem, der ein eigenes PBEM schreibt, nur empfehlen sich einer Skriptsprache zu bedienen, zumindest um die Kern-Funktionen seines Programmes steuern zu können.
Als Tool benutze ich dazu [url=http://luabind.sf.net]luabind[/url], das erlaubt es sehr einfach, C und C++ Code nach lua zu binden. Dafür ist der ganze Eressea-Server jetzt C++-verträglich geworden (schon vor einer Weile). Der luabind-code sieht in etwa so aus:
void
bind_region(lua_State * L)
{
module(L)[
def("regions", &get_regions, return_stl_iterator),
def("get_region", &findregion),
class_<struct region>("region")
.property("name", ®ion_getname, ®ion_setname)
.property("info", ®ion_getinfo, ®ion_setinfo)
.property("terrain", ®ion_getterrain)
.def_readonly("x", ®ion::x)
.def_readonly("y", ®ion::y)
.def_readwrite("age", ®ion::age)
.property("units", ®ion_units, return_stl_iterator)
.property("buildings", ®ion_buildings, return_stl_iterator)
.property("ships", ®ion_ships, return_stl_iterator)
];
}
Ja, das ist [b]wirklich[/b] reines C++, auch wenn es nicht so ausschaut. Habe ich auch erst nicht glauben können 🙂