Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

* Kompressionsflag innerhalb von demos wird jetzt nicht mehr ignorie…

…rt. Damit beschraenkt sich das clientseitige Demospeichern auf ein 'netcat' und 'save-demo.rb' ist nicht mehr notwendig. Um alte Demos weiterhin abzuspielen, kann die Environmentvariable UNCOMPRESSED_DEMO_COMPATIBILITY gesetzt werden.

 * Die Unkomprimierten Serverdemos koennen mit 'demo-compress.rb' nachtraeglich komprimiert werden.


git-svn-id: http://infon.googlecode.com/svn/trunk@115 8171fb75-e542-0410-96e4-03d5dd800671
  • Loading branch information...
commit b4f20aa5fa702123990d19498ae860b9454daa46 1 parent 7fd3421
Florian Wesch authored
113 client.c
View
@@ -106,9 +106,7 @@ static void client_start_compression() {
if (compression)
PROTOCOL_ERROR();
- // Bei Demofiles Kompressionstart ignorieren,
- // da diese unkomprimiert abgelegt werden.
- if (is_file_source)
+ if (getenv("UNCOMPRESSED_DEMO_COMPATIBILITY") && is_file_source)
return;
strm.zalloc = Z_NULL;
@@ -171,20 +169,10 @@ static void client_handle_packet(packet_t *packet) {
}
}
-static void client_readable(int fd, short event, void *arg) {
- struct event *cb_event = arg;
-
- int ret = evbuffer_read(in_buf, fd, 8192);
- if (ret < 0) {
- client_destroy(strerror(errno));
- return;
- } else if (ret == 0) {
- client_destroy("eof reached");
- return;
- }
-
- traffic += ret;
-
+// returns 0 on error
+// returns 1 if more data is needed
+// returns 2 if more time is needed
+static int client_parse_in_buf() {
restart:
if (compression) {
char buf[8192];
@@ -197,13 +185,13 @@ static void client_readable(int fd, short event, void *arg) {
int ret = inflate(&strm, Z_SYNC_FLUSH);
if (ret != Z_OK && ret != Z_BUF_ERROR) {
client_destroy("decompression error");
- return;
+ return 0;
}
evbuffer_add(packet_buf, buf, sizeof(buf) - strm.avail_out);
if (EVBUFFER_LENGTH(packet_buf) > 1024 * 1024) {
- client_destroy("too much to decompress. funny server?");
- return;
+ client_destroy("too much to decompress. funny data?");
+ return 0;
}
} while (strm.avail_out == 0);
evbuffer_drain(in_buf, EVBUFFER_LENGTH(in_buf) - strm.avail_in);
@@ -215,9 +203,9 @@ static void client_readable(int fd, short event, void *arg) {
while (EVBUFFER_LENGTH(packet_buf) >= PACKET_HEADER_SIZE) {
int packet_len = PACKET_HEADER_SIZE + EVBUFFER_DATA(packet_buf)[0];
- // Genuegend Daten da?
+ // Nicht genuegend Daten da?
if (EVBUFFER_LENGTH(packet_buf) < packet_len)
- break;
+ return 1;
// Alten Kompressionszustand merken
int old_compression = compression;
@@ -227,11 +215,13 @@ static void client_readable(int fd, short event, void *arg) {
memcpy(&packet, EVBUFFER_DATA(packet_buf), packet_len);
packet_rewind(&packet);
client_handle_packet(&packet);
- evbuffer_drain(packet_buf, packet_len);
// Disconnect Packet?
if (!client_is_connected())
- return;
+ return 0;
+
+ // Weg damit
+ evbuffer_drain(packet_buf, packet_len);
// Wurde Kompression aktiviert? Dann Rest des packet_buf zurueck
// in den in_buf, da es sich dabei bereits um komprimierte Daten
@@ -241,9 +231,31 @@ static void client_readable(int fd, short event, void *arg) {
evbuffer_drain(packet_buf, EVBUFFER_LENGTH(packet_buf));
goto restart;
}
+
+ // Beim Demo abspielen muss erst pausiert werden
+ if (is_file_source && next_packet_countdown > 0)
+ return 2;
}
+
+ return 1;
+}
- event_add(cb_event, NULL);
+static void client_readable(int fd, short event, void *arg) {
+ struct event *cb_event = arg;
+
+ int ret = evbuffer_read(in_buf, fd, 8192);
+ if (ret < 0) {
+ client_destroy(strerror(errno));
+ return;
+ } else if (ret == 0) {
+ client_destroy("eof reached");
+ return;
+ }
+
+ traffic += ret;
+
+ if (client_parse_in_buf())
+ event_add(cb_event, NULL);
}
static void client_writable(int fd, short event, void *arg) {
@@ -274,34 +286,33 @@ int client_is_connected() {
}
void file_loop(int delta) {
- static packet_t packet;
- static char errbuf[128];
int ret;
+
next_packet_countdown -= delta;
+
while (next_packet_countdown <= 0) {
- ret = read(clientfd, &packet, PACKET_HEADER_SIZE);
- if (ret != PACKET_HEADER_SIZE) {
- snprintf(errbuf, sizeof(errbuf), "eof, reading header: want %d, got %d", PACKET_HEADER_SIZE, ret);
- client_destroy(errbuf);
- return;
- }
+ switch (client_parse_in_buf()) {
+ // error -> disconnected
+ case 0:
+ return;
- traffic += ret;
-
- ret = read(clientfd, &packet.data, packet.len);
- if (ret != packet.len) {
- snprintf(errbuf, sizeof(errbuf), "eof, reading packet: want %d, got %d", packet.len, ret);
- client_destroy(errbuf);
- return;
+ // more data needed?
+ case 1:
+ ret = evbuffer_read(in_buf, clientfd, 4096);
+
+ if (ret < 0) {
+ client_destroy(strerror(errno));
+ return;
+ } else if (ret == 0) {
+ client_destroy("eof");
+ return;
+ }
+
+ traffic += ret;
+ break;
+ case 2: // call again later
+ return;
}
-
- traffic += ret;
-
- packet_rewind(&packet);
- client_handle_packet(&packet);
-
- if (!client_is_connected())
- return;
}
}
@@ -394,8 +405,12 @@ int client_open_file(char *filename) {
return fd;
}
-void client_init(char *source, char *demo_save_name) {
+void client_init(char *source) {
struct stat stat_buf;
+
+ if (!strcmp(source, "-"))
+ source = "/dev/stdin";
+
if (stat(source, &stat_buf) < 0) {
#ifdef WIN32
WSADATA wsa;
2  client.h
View
@@ -26,7 +26,7 @@ int client_is_connected();
int client_traffic();
-void client_init(char *source, char *demo_save_name);
+void client_init(char *source);
void client_shutdown();
#endif
5 demo-compress.rb
View
@@ -0,0 +1,5 @@
+require 'zlib'
+File.open(ARGV[1], "wb") do |out|
+ out.write("\x00\xFE")
+ out.write(Zlib::Deflate.deflate(File.read(ARGV[0]), Zlib::BEST_COMPRESSION))
+end
2  demo2graph.rb
View
@@ -169,7 +169,7 @@ def tick
when 32:
welcome = @file.read(len).delete("\n").strip
when 254:
- # puts "compression start (ignored for demos)"
+ @file.compress = true
when 255:
version = @file.read8
# puts "server protocol version %d" % @file.read8
BIN  example.demo
View
Binary file not shown
35 game.c
View
@@ -152,7 +152,7 @@ void game_init() {
lua_setglobal(L, "GAME_NAME");
}
-void game_one_round() {
+void game_one_game() {
should_end_round = 0;
game_time = 0;
@@ -175,28 +175,16 @@ void game_one_round() {
int lasttick = 0;
gettimeofday(&start, NULL);
- server_round_start();
- player_round_start();
+ server_game_start();
+ player_game_start();
- // Demo Aufnahme starten
- client_t *demowriter = NULL;
-
- lua_pushliteral(L, "onNewGameDemoStart");
+ // Spiel gestartet
+ lua_pushliteral(L, "onNewGameStarted");
lua_rawget(L, LUA_GLOBALSINDEX);
- if (lua_pcall(L, 0, 1, 0) != 0) {
- fprintf(stderr, "error calling onNewGameDemoStart: %s\n", lua_tostring(L, -1));
- } else {
- const char *demoname = lua_tostring(L, -1);
- if (demoname) {
- demowriter = server_start_demo_writer(demoname);
- if (demowriter) {
- fprintf(stderr, "started recording demo %s\n", demoname);
- } else {
- fprintf(stderr, "couldn't start demo file %s\n", demoname);
- }
- }
- }
- lua_pop(L, 1);
+ if (lua_pcall(L, 0, 0, 0) != 0) {
+ fprintf(stderr, "error calling onNewGameStarted: %s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ }
while (!game_exit && !should_end_round) {
int tick = get_tick();
@@ -240,10 +228,9 @@ void game_one_round() {
// IO Lesen/Schreiben
server_tick();
}
-
- if (demowriter)
- server_destroy(demowriter, "game ended");
+ server_game_end();
+
creature_shutdown();
world_shutdown();
}
2  game.h
View
@@ -24,7 +24,7 @@
#include "server.h"
void game_init();
-void game_one_round();
+void game_one_game();
void game_send_initial_update(client_t *client);
#endif
2  infon.c
View
@@ -96,7 +96,7 @@ int main(int argc, char *argv[]) {
if (!renderer_open(width, height, fullscreen))
die("cannot open renderer. sorry");
- client_init(host, NULL);
+ client_init(host);
client_game_init();
int lastticks = get_tick();
5 infond.c
View
@@ -61,6 +61,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "no coredump possible. enable them to help debug crashes.\n");
#endif
+ signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
signal(SIGPIPE, SIG_IGN);
@@ -70,7 +71,7 @@ int main(int argc, char *argv[]) {
luaL_openlibs(L);
if (luaL_dofile(L, "infond.lua"))
- die("cannot read 'infond.lua'");
+ die("cannot read 'infond.lua': ", lua_tostring(L, -1));
game_init();
server_init();
@@ -81,7 +82,7 @@ int main(int argc, char *argv[]) {
#endif
while (!game_exit) {
- game_one_round();
+ game_one_game();
}
player_shutdown();
10 infond.lua
View
@@ -264,7 +264,7 @@ function on_client_close(fd, reason)
clients[fd] = nil
end
-function server_new_round()
+function server_new_game()
server_tick = coroutine.wrap(ServerMain)
end
@@ -275,13 +275,11 @@ end
-- Game C Callbacks
-----------------------------------------------------------
-function onNewGameDemoStart()
+function onNewGameStarted()
if type(demo) == "string" then
- return string.format("%s-%08X.demo", demo, os.time());
+ server_start_demo(string.format("%s-%08X.demo", demo, os.time()));
elseif type(demo) == "function" then
- return demo()
- else
- return nil
+ server_start_demo(demo())
end
end
21 listener.c
View
@@ -18,6 +18,7 @@
*/
+#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
@@ -60,7 +61,25 @@ static void listener_cb(int fd, short event, void *arg) {
goto error;
}
- if (!server_accept(clientfd, &peer))
+ /* TCP_NODELAY setzen. Dadurch werden Daten fruehestmoeglich versendet */
+ static const int one = 1;
+ if (setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
+ fprintf(stderr, "cannot enable TCP_NODELAY: %s\n", strerror(errno));
+ goto error;
+ }
+
+ /* SO_LINGER setzen. Falls sich noch Daten in der Sendqueue der Verbindung
+ befinden, werden diese verworfen. */
+ static const struct linger l = { 1, 0 };
+ if (setsockopt(clientfd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) {
+ fprintf(stderr, "cannot set SO_LINGER: %s\n", strerror(errno));
+ goto error;
+ }
+
+ static char address[128];
+ sprintf(address, "ip:%s:%d", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));
+
+ if (!server_accept(clientfd, address))
goto error;
event_add(cb_event, NULL);
26 lua-5.1.1/src/lvm.c
View
@@ -56,6 +56,28 @@ int luaV_tostring (lua_State *L, StkId obj) {
}
}
+static StkId traceexec (lua_State *L, const Instruction *pc) {
+ lu_byte mask = L->hookmask;
+ const Instruction *oldpc = GETPC(L);
+ SAVEPC(L, pc);
+ if (mask > LUA_MASKLINE) { /* instruction-hook set? */
+ if (L->hookcount == 0) {
+ resethookcount(L);
+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
+ }
+ }
+ if (mask & LUA_MASKLINE) {
+ Proto *p = ci_func(L->ci)->l.p;
+ int npc = pcRel(pc, p);
+ int newline = getline(p, npc);
+ /* call linehook when enter a new function, when jump back (loop),
+ or when enter a new line */
+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
+ luaD_callhook(L, LUA_HOOKLINE, newline);
+ }
+ return L->base;
+}
+
static void callTMres (lua_State *L, StkId res, const TValue *f,
const TValue *p1, const TValue *p2) {
ptrdiff_t result = savestack(L, res);
@@ -384,6 +406,10 @@ int luaV_execute (lua_State *L) {
SAVEPC(L, pc);
cpu_limit_exceeded(L); // never returns
}
+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
+ base = traceexec(L, pc);
+
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
lua_assert(base == L->base && L->base == L->ci->base);
11 player.c
View
@@ -679,8 +679,13 @@ player_t *player_create(const char *pass) {
lua_set_cycles(player->L, player->max_cycles);
player_init_events(player);
- if (luaL_dofile(player->L, "player.lua"))
- die("cannot read 'player.lua'");
+ // player.lua sourcen
+ if (luaL_dofile(player->L, "player.lua")) {
+ fprintf(stderr, "cannot source 'player.lua': %s\n", lua_tostring(player->L, -1));
+ lua_close(player->L);
+ player->L = NULL;
+ return NULL;
+ }
player_to_network(player, PLAYER_DIRTY_ALL, SEND_BROADCAST);
@@ -1160,7 +1165,7 @@ void player_init() {
lua_setglobal(L, "CREATURE_FLYER");
}
-void player_round_start() {
+void player_game_start() {
int playerno;
for (playerno = 0; playerno < MAXPLAYERS; playerno++) {
if (PLAYER_USED(&players[playerno]))
2  player.h
View
@@ -97,7 +97,7 @@ void player_send_initial_update(client_t *client);
void player_to_network(player_t *player, int dirtymask, client_t *client);
void player_init();
-void player_round_start();
+void player_game_start();
void player_shutdown();
#endif
40 player.lua
View
@@ -33,7 +33,6 @@ dofile = nil -- would allow file loading
loadfile = nil -- no file loading
_VERSION = nil -- who cares
newproxy = nil -- huh?
-debug = nil -- no debugging function
gcinfo = nil -- no access to the garbage collector
os = nil -- no os access
package = nil -- package support is not needed
@@ -45,6 +44,7 @@ module = nil -- module support not needed
do
local orig_loadstring = loadstring
local check_code_size = string.len
+ local error = error
loadstring = function(code, name)
if check_code_size(code) > 16384 then
error("code too large")
@@ -54,6 +54,31 @@ do
end
end
+-- provide thread tracing function
+do
+ local sethook = debug.sethook
+ local getinfo = debug.getinfo
+ local type, error, print = type, error, print
+ thread_trace = function(thread, text)
+ if type(thread) ~= "thread" then
+ error("arg #1 is not a thread")
+ end
+ local dumper = function(what, where)
+ local info = getinfo(2, "nlS")
+ print(text .. ":" .. info.source .. ":" .. info.currentline)
+ end
+ sethook(thread, dumper, "l")
+ end
+ thread_untrace = function(thread)
+ if type(thread) ~= "thread" then
+ error("arg #1 is not a thread")
+ end
+ sethook(thread)
+ end
+end
+
+debug = nil -- no debugging functions
+
collectgarbage()
collectgarbage = nil -- no access to the garbage collector
@@ -367,11 +392,7 @@ function player_think(events)
local parent = other ~= -1 and other or nil
local creature = {}
setmetatable(creature, {
- __index = function(self, what)
- if Creature[what] then
- return Creature[what]
- end
- end,
+ __index = Creature,
__tostring = function(self)
local x, y = get_pos(self.id)
local states = { [0]="idle", [1]="walk", [2]="heal", [3]="eat",
@@ -442,6 +463,11 @@ function player_think(events)
creature.message = 'main() terminated (maybe it was killed for using too much cpu/memory?)'
end
else
+ if creature.debug then
+ thread_trace(creature.thread, creature.id)
+ else
+ thread_untrace(creature.thread)
+ end
local ok, msg = coroutine.resume(creature.thread, creature)
if not ok then
creature.message = msg
@@ -457,7 +483,7 @@ function player_think(events)
can_yield = false
- -- Nach jeder Runde eventuell vorhandene Funktion onRoundStart aufrufen
+ -- Nach jeder Runde eventuell vorhandene Funktion onRoundEnd aufrufen
if onRoundEnd then
local ok, msg = pcall(onRoundEnd)
if not ok then
76 save-demo.rb
View
@@ -1,76 +0,0 @@
-require 'socket'
-require 'zlib'
-
-raise "#$0 <server> <demofile>" unless ARGV.size == 2
-
-TCPSocket.open(ARGV[0], 1234) { |socket|
-
- class << socket
- alias_method :orig_read, :read
- attr_accessor :traffic
- attr_accessor :compress
- attr_accessor :zstream
- attr_accessor :buf
- attr_accessor :dump
-
- def read(x)
- if @compress
- while @buf.size < x
- @buf << @zstream.inflate(orig_read(1))
- @traffic += 1
- end
- ret = @buf[0...x]
- @buf = @buf[x..-1]
- else
- ret = orig_read(x)
- @traffic += x
- end
- @dump.write(ret) if @dump
- ret
- end
-
- def read8
- read(1)[0]
- end
-
- def read16
- ret = read8
- ret = ret & 0x7F | read8 << 7 if ret & 0x80 != 0
- ret
- end
-
- def read32
- read(4).unpack("N")[0]
- end
-
- def readXX(len)
- read(len).unpack("A*")[0]
- end
- end
-
- socket.traffic = 0
- socket.buf = ""
- socket.compress = false
- socket.zstream = Zlib::Inflate.new
- socket.dump = File.new(ARGV[1], "wb+")
-
- loop do
- len = socket.read8
- case type = socket.read8
- when 4:
- break
- when 32:
- socket.write("guiclient\n")
- puts "welcome: %s" % socket.read(len).delete("\n").strip
- when 254:
- puts "compression start"
- socket.compress = true
- else
- socket.readXX(len)
- end
- print "."
- STDOUT.flush
- end
-
- socket.dump.close
-}
91 server.c
View
@@ -60,11 +60,7 @@ int client_num(client_t *client) {
return client - clients;
}
-client_t *server_accept(int fd, struct sockaddr_in *peer) {
- static struct linger l = { 1, 0 };
- static const int one = 1;
- static char address[128];
-
+client_t *server_accept(int fd, const char *address) {
if (fd >= MAXCLIENTS) {
fprintf(stderr, "cannot accept() new incoming connection: file descriptor too large\n");
return NULL;
@@ -73,21 +69,16 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
memset(&clients[fd], 0, sizeof(client_t));
client_t *client = &clients[fd];
- if (peer) {
- sprintf(address, "ip:%s:%d", inet_ntoa(peer->sin_addr), ntohs(peer->sin_port));
- } else if (fd == STDIN_FILENO) {
- sprintf(address, "special:console");
- } else {
- sprintf(address, "special:demodumper");
- client->is_demo_dumper = 1;
- }
+ // Demo Dumper wird leicht unterschiedlich behandelt
+ client->is_demo_dumper = strstr(address, "special:demodumper") == address;
- /* Non Blocking setzen */
+ // Non Blocking setzen */
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
fprintf(stderr, "cannot set accept()ed socket nonblocking: %s\n", strerror(errno));
return NULL;
}
+ // Soll Verbindung angenommen werden?
lua_pushliteral(L, "on_new_client");/* funcname */
lua_rawget(L, LUA_GLOBALSINDEX); /* func */
lua_pushstring(L, address); /* addr */
@@ -107,22 +98,7 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
lua_pop(L, 2);
- if (peer) {
- /* TCP_NODELAY setzen. Dadurch werden Daten fruehestmoeglich versendet */
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
- fprintf(stderr, "cannot enable TCP_NODELAY: %s\n", strerror(errno));
- return NULL;
- }
-
- /* SO_LINGER setzen. Falls sich noch Daten in der Sendqueue der Verbindung
- befinden, werden diese verworfen. */
- if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) {
- fprintf(stderr, "cannot set SO_LINGER: %s\n", strerror(errno));
- return NULL;
- }
- }
-
- // Aktivieren
+ // Libevent aktivieren
event_set(&client->rd_event, fd, EV_READ, server_readable, &client->rd_event);
event_set(&client->wr_event, fd, EV_WRITE, server_writable, &client->wr_event);
@@ -141,6 +117,7 @@ client_t *server_accept(int fd, struct sockaddr_in *peer) {
client->next_gui = NULL;
client->prev_gui = NULL;
+ // Annehmen
lua_pushliteral(L, "on_client_accepted");
lua_rawget(L, LUA_GLOBALSINDEX);
lua_pushnumber(L, fd);
@@ -238,9 +215,15 @@ static void server_writable(int fd, short event, void *arg) {
}
void server_start_compression(client_t *client) {
+ // Kompression bereits aktiviert?
if (client->compress)
return;
+ // Demos sind immer unkomprimiert. Eine Kompression ueber
+ // die erstellte Datei macht wesentlich mehr Sinn.
+ if (client->is_demo_dumper)
+ return;
+
client->strm.zalloc = Z_NULL;
client->strm.zfree = Z_NULL;
client->strm.opaque = NULL;
@@ -278,7 +261,6 @@ void server_writeto(client_t *client, const void *data, size_t size) {
}
evbuffer_add(client->out_buf, buf, sizeof(buf) - client->strm.avail_out);
}
- // printf("%d => %d\n", client->strm.total_in, client->strm.total_out);
} else {
evbuffer_add(client->out_buf, (void*)data, size);
}
@@ -392,6 +374,18 @@ static void client_turn_into_gui_client(client_t *client) {
initial_update(client);
}
+client_t *server_start_demo_writer(const char *demoname, int one_game) {
+ int server_demo_fd = open(demoname, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, S_IRUSR|S_IWUSR);
+ if (server_demo_fd < 0)
+ return NULL;
+ static char address[512];
+ snprintf(address, sizeof(address), "special:demodumper:%s", demoname);
+ client_t *demowriter = server_accept(server_demo_fd, address);
+ client_turn_into_gui_client(demowriter);
+ demowriter->kick_at_end_of_game = one_game;
+ return demowriter;
+}
+
client_t *client_get_checked_lua(lua_State *L, int idx) {
int clientno = luaL_checklong(L, idx);
if (clientno < 0 || clientno >= MAXCLIENTS)
@@ -402,6 +396,15 @@ client_t *client_get_checked_lua(lua_State *L, int idx) {
return client;
}
+static int luaStartDemoWriter(lua_State *L) {
+ const char *demofile = luaL_checkstring(L, 1);
+ int one_game = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : 1;
+ client_t *demowriter = server_start_demo_writer(demofile, one_game);
+ if (!demowriter) luaL_error(L, "cannot start demo %s", demofile);
+ lua_pushnumber(L, client_num(demowriter));
+ return 1;
+}
+
static int luaClientWrite(lua_State *L) {
size_t msglen; const char *msg = luaL_checklstring(L, 2, &msglen);
client_t *client = client_get_checked_lua(L, 1);
@@ -540,31 +543,31 @@ void server_init() {
lua_register(L, "client_disconnect", luaClientDisconnect);
lua_register(L, "client_print", luaClientPrint);
lua_register(L, "cprint", luaClientPrint);
+ lua_register(L, "server_start_demo", luaStartDemoWriter);
// XXX: HACK: stdin client starten
#ifdef CONSOLE_CLIENT
- server_accept(STDIN_FILENO, NULL);
+ server_accept(STDIN_FILENO, "special:console");
#endif
}
-client_t *server_start_demo_writer(const char *demoname) {
- int server_demo_fd = open(demoname, O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, S_IRUSR|S_IWUSR);
- if (server_demo_fd < 0)
- return NULL;
- client_t *demowriter = server_accept(server_demo_fd, NULL);
- client_turn_into_gui_client(demowriter);
- return demowriter;
-}
-
-void server_round_start() {
- lua_pushliteral(L, "server_new_round");
+void server_game_start() {
+ lua_pushliteral(L, "server_new_game");
lua_rawget(L, LUA_GLOBALSINDEX);
if (lua_pcall(L, 0, 0, 0) != 0) {
- fprintf(stderr, "error calling server_new_round: %s\n", lua_tostring(L, -1));
+ fprintf(stderr, "error calling server_new_game: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
}
+void server_game_end() {
+ int clientno;
+ for (clientno = 0; clientno < MAXCLIENTS; clientno++) {
+ if (CLIENT_USED(&clients[clientno]) && clients[clientno].kick_at_end_of_game)
+ server_destroy(&clients[clientno], "game ended");
+ }
+}
+
void server_shutdown() {
int clientno;
for (clientno = 0; clientno < MAXCLIENTS; clientno++) {
8 server.h
View
@@ -51,6 +51,7 @@ typedef struct client_s {
z_stream strm;
char *kill_me;
+ int kick_at_end_of_game;
// Verbindung von: 1-player <-> N-client
struct player_s *player;
@@ -63,7 +64,7 @@ typedef struct client_s {
struct client_s *prev_gui;
} client_t;
-client_t *server_accept(int fd, struct sockaddr_in *peer);
+client_t *server_accept(int fd, const char *address);
void server_writeto(client_t *client, const void *data, size_t size);
void server_writeto_all_gui_clients(const void *data, size_t size);
void server_destroy(client_t *client, const char *reason);
@@ -72,12 +73,13 @@ client_t *client_get_checked_lua(lua_State *L, int idx);
void server_send_packet(packet_t *packet, client_t *client);
-client_t *server_start_demo_writer(const char *demoname);
+client_t *server_start_demo_writer(const char *demoname, int one_game);
void server_tick();
void server_init();
-void server_round_start();
+void server_game_start();
+void server_game_end();
void server_shutdown();
#endif
Please sign in to comment.
Something went wrong with that request. Please try again.