[0.1.1-4] server.port defined. also, heartbeat server starting to take shape, though you can't actually READ the list from another comp yet.
This commit is contained in:
parent
44766398ff
commit
a8119ad35a
@ -55,6 +55,11 @@ common.base_dir @
|
||||
writing to this string will *not* change the base dir,
|
||||
so *don't write to it* or else you'll just screw up your own code!
|
||||
|
||||
server.port @
|
||||
port we are bound to
|
||||
|
||||
there is NO alias to common here! if you want it, do it manually.
|
||||
|
||||
common.version = {cmp={w,x,y,a,z},num,str="w.x.ya-z"} @
|
||||
current engine version
|
||||
|
||||
|
@ -4,74 +4,74 @@ Main heartbeat server:
|
||||
play.iceballga.me port 27790
|
||||
(port is for UDP *and* TCP)
|
||||
|
||||
Iceball clients should connect to:
|
||||
play.iceballga.me port 27795
|
||||
[ NOT IMPLEMENTED ]
|
||||
|
||||
Iceball only supports IPv4 UDP ports at the time of writing, sorry.
|
||||
|
||||
Feel free to host your own heartbeat server, though!
|
||||
|
||||
Note, S = heartbeat server, C = heartbeat client (AKA iceball server).
|
||||
|
||||
You should always confirm you have received a packet from the heartbeat server.
|
||||
To do this correctly, send packets every 3 seconds until you get a response.
|
||||
If you get no response after 60 seconds, give up.
|
||||
You might want to retry after 180 seconds.
|
||||
|
||||
The heartbeat server will terminate your session after 120 seconds of inactivity.
|
||||
|
||||
ALL PROTOCOLS ARE LITTLE ENDIAN WHERE APPROPRIATE, GUYS!
|
||||
|
||||
Iceball servers interface the heartbeat server using this UDP protocol...
|
||||
|
||||
0x01 hbversion.u16 port.u16 addr.z:
|
||||
C->S Request ID (conf 0x02)
|
||||
|
||||
This should be the first thing you send to the heartbeat server.
|
||||
"1CEB" hbversion.u16 ibversion.u32 port.u16 players_current.u16 players_max.u16 name.z[30] mode.z[10] map.z[30]
|
||||
I->H
|
||||
Announce a server.
|
||||
|
||||
At the time of writing, hbversion should be 1.
|
||||
Note, remember to send a burst of 5 of these
|
||||
with a second in between each packet,
|
||||
and do this every 40 seconds
|
||||
|
||||
0x02 id.u32 port.u16 addr.z:
|
||||
S->C Here Is Your ID
|
||||
(that is, a gap of 36 seconds between the last of a burst
|
||||
and the first of the next).
|
||||
|
||||
Every time you receive this packet, CHANGE YOUR ID.
|
||||
Note, the strings are terminated with a NUL (char 0)
|
||||
unless they hit their string limit,
|
||||
in which case there is no NUL. BE WARY OF THIS.
|
||||
|
||||
0x03 id.u32 field.u8 name.z:
|
||||
C->S Set String Field (conf 0x03)
|
||||
S->C This Is Your String Field
|
||||
"MSOK"
|
||||
H->I
|
||||
|
||||
Valid string fields are:
|
||||
0x01: server name
|
||||
0x02: server mode
|
||||
Your packet was accepted.
|
||||
|
||||
0x04 id.u32 field.u8 data.s32:
|
||||
C->S Set Integer Field (conf 0x04)
|
||||
S->C This Is Your Integer Field
|
||||
If your server gets this message, you can stop sending your burst.
|
||||
|
||||
Valid integer fields are:
|
||||
0x01: player count
|
||||
0x02: max players
|
||||
"BADV" hbversion.u16 ibversion.u32
|
||||
H->I
|
||||
|
||||
0x05 id.u32:
|
||||
C->S Hello Me Not Dead
|
||||
Your version of Iceball and/or the heartbeat protocol are too old and/or new.
|
||||
Here's the version we expect.
|
||||
|
||||
Every 30 seconds, send 5 of these at 1 second intervals.
|
||||
If your server gets this message, give up.
|
||||
|
||||
0x06:
|
||||
S->C I'll Need To See Your ID
|
||||
Alternatively, if you support the given heartbeat version, try falling back to it.
|
||||
|
||||
If you send any packets and you don't have an active session
|
||||
(either you didn't initiate one or the server terminated your session),
|
||||
you'll get this. Apply for a new ID.
|
||||
"BADF"
|
||||
H->I
|
||||
|
||||
0x07 version.u16:
|
||||
S->C Version Mismatch
|
||||
The packet you sent was complete horseshit and you should feel bad for writing such bad code.
|
||||
|
||||
You are using the wrong version of the heartbeat protocol.
|
||||
This should give you the correct version.
|
||||
If your server gets this message, crash in shame, because your code is seriously broken.
|
||||
Or alternatively just don't send any more data to the server.
|
||||
|
||||
But crashing with an error is a much better idea.
|
||||
|
||||
OK, so that's the UDP side of the master server.
|
||||
The TCP side is a minimal HTTP server with two interfaces:
|
||||
|
||||
The TCP side is a minimal HTTP server at the same port with these interfaces:
|
||||
[ INCOMPLETE IMPLEMENTATION THAT DOESN'T ACTUALLY WORK ]
|
||||
|
||||
/:
|
||||
/index.html:
|
||||
An HTML page following a template.
|
||||
/style.css:
|
||||
|
||||
A stylesheet you can provide.
|
||||
/master.json:
|
||||
The raw serverlist info in JSON format.
|
||||
Here's the expected format!
|
||||
@ -80,12 +80,14 @@ The TCP side is a minimal HTTP server with two interfaces:
|
||||
"version": int,
|
||||
"servers": [
|
||||
{
|
||||
"name": str,
|
||||
"address": str,
|
||||
"port": int,
|
||||
"basedir": str,
|
||||
"players_current": int,
|
||||
"players_max": int,
|
||||
"name": str,
|
||||
"mode": str,
|
||||
"map": str,
|
||||
"version": str
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -16,6 +16,249 @@
|
||||
# along with Iceball. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import heapq, socket, struct, sys, time
|
||||
|
||||
CONN_PORT = int(sys.argv[1])
|
||||
|
||||
def ib_version_str(n):
|
||||
z = n & ((1<<10)-1); n >>= 10
|
||||
a = n & ((1<<5)-1); n >>= 5
|
||||
y = n & ((1<<7)-1); n >>= 7
|
||||
x = n & ((1<<5)-1); n >>= 5
|
||||
w = n
|
||||
|
||||
s = "%i.%i" % (w, x)
|
||||
if y > 0:
|
||||
s += ".%i" % y
|
||||
if a > 0:
|
||||
s += "." + chr(ord('a')+a-1)
|
||||
if z > 0:
|
||||
s += "-%i" % z
|
||||
|
||||
return s
|
||||
|
||||
def calc_ib_version(w,x,y,a,z):
|
||||
return (((((((w<<5) + x
|
||||
)<<7) + y
|
||||
)<<5) + a
|
||||
)<<10) + z
|
||||
|
||||
HB_LIFETIME = 120
|
||||
HB_VERSION = 1
|
||||
IB_VERSION_CMP = (0,1,1,0,0)
|
||||
IB_VERSION = calc_ib_version(*IB_VERSION_CMP)
|
||||
|
||||
# ignore "Z" version
|
||||
IB_VERSION_MASK = ~((1<<10)-1)
|
||||
# if you wish to ignore "A" version as well, use this instead:
|
||||
# IB_VERSION_MASK = ~((1<<(10+5))-1)
|
||||
|
||||
def stripnul(s):
|
||||
idx = s.find("\x00")
|
||||
return (s if idx == -1 else s[:idx])
|
||||
|
||||
class HTTPClient:
|
||||
def __init__(self, reactor, server, sockfd):
|
||||
self.reactor = reactor
|
||||
self.server = server
|
||||
self.sockfd = sockfd
|
||||
self.buf = ""
|
||||
|
||||
def is_dead(self, ct):
|
||||
return self.sockfd == None
|
||||
|
||||
def update(self, ct):
|
||||
self.get_msgs(ct)
|
||||
|
||||
def collect(self, ct):
|
||||
# TODO!
|
||||
pass
|
||||
|
||||
def get_msgs(self, ct):
|
||||
if not self.sockfd:
|
||||
return
|
||||
|
||||
try:
|
||||
msg = self.sockfd.recv(2048)
|
||||
if msg == None:
|
||||
self.sockfd.close()
|
||||
self.sockfd = None
|
||||
|
||||
self.buf += msg
|
||||
self.collect(ct)
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
class HReactor:
|
||||
def __init__(self):
|
||||
self.evq = []
|
||||
|
||||
def run(self):
|
||||
while len(self.evq) > 0:
|
||||
ct = self.get_time()
|
||||
|
||||
dt = self.evq[0][0] - ct
|
||||
if dt > 0:
|
||||
time.sleep(dt)
|
||||
|
||||
self.update()
|
||||
|
||||
# we've run out of tasks, so exit.
|
||||
|
||||
def update(self):
|
||||
ct = self.get_time()
|
||||
while self.evq and ct >= self.evq[0][0]:
|
||||
et, fn = heapq.heappop(self.evq)
|
||||
fn(et, ct)
|
||||
|
||||
def get_time(self):
|
||||
return time.time()
|
||||
|
||||
def push(self, et, fn):
|
||||
heapq.heappush(self.evq, (et, fn))
|
||||
|
||||
class HServer:
|
||||
def __init__(self, ct, reactor, af, port):
|
||||
self.af = af
|
||||
self.port = port
|
||||
self.reactor = reactor
|
||||
self.clients = {}
|
||||
self.http_clients = {}
|
||||
self.bans = set([]) # TODO: use a proper banlist
|
||||
|
||||
self.http_sockfd = socket.socket(af, socket.SOCK_STREAM)
|
||||
self.http_sockfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.http_sockfd.bind(("", self.port))
|
||||
self.http_sockfd.settimeout(0)
|
||||
|
||||
self.sockfd = socket.socket(af, socket.SOCK_DGRAM)
|
||||
self.sockfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.sockfd.bind(("", self.port))
|
||||
self.sockfd.settimeout(0.05)
|
||||
self.reactor.push(ct, self.update)
|
||||
|
||||
def update(self, et, ct):
|
||||
self.get_hb_packets(ct)
|
||||
self.update_http_clients(ct)
|
||||
self.kill_old_clients(ct)
|
||||
self.reactor.push(ct+0.05, self.update)
|
||||
|
||||
def get_hb_packets(self, ct):
|
||||
try:
|
||||
(msg, adtup) = self.sockfd.recvfrom(2048)
|
||||
|
||||
if msg and adtup:
|
||||
(addr, port) = adtup
|
||||
self.on_msg(ct, self.af, addr, port, msg)
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
def update_http_clients(self, ct):
|
||||
for v in self.http_clients:
|
||||
v.update(ct)
|
||||
|
||||
def kill_old_clients(self, ct):
|
||||
# TODO: use a priority queue for the clients
|
||||
# that'd mean we'd get this running in O(1) time instead of O(n)
|
||||
|
||||
kill = []
|
||||
|
||||
for k,v in self.clients.iteritems():
|
||||
if v.is_dead(ct):
|
||||
kill.append(k)
|
||||
|
||||
for k in kill:
|
||||
self.clients.pop(k)
|
||||
|
||||
def on_msg(self, ct, af, addr, port, msg):
|
||||
client = self.get_client(ct, af, addr, port)
|
||||
if client:
|
||||
client.on_msg(ct, msg)
|
||||
|
||||
def get_client(self, ct, af, addr, port):
|
||||
tup = (af, addr, port)
|
||||
|
||||
if tup in self.bans:
|
||||
return None
|
||||
if tup not in self.clients:
|
||||
self.clients[tup] = HClient(ct, self.reactor, self, af, addr, port)
|
||||
|
||||
return self.clients[tup]
|
||||
|
||||
def get_ib_fields(self):
|
||||
l = []
|
||||
|
||||
for k, v in self.clients.iteritems():
|
||||
d = v.get_fields()
|
||||
if d:
|
||||
l.append(d)
|
||||
|
||||
return l
|
||||
|
||||
class HClient:
|
||||
def __init__(self, ct, reactor, server, af, addr, port):
|
||||
self.reactor = reactor
|
||||
self.server = server
|
||||
self.af = af
|
||||
self.addr = addr
|
||||
self.port = port
|
||||
self.ibdata = None
|
||||
self.not_dead(ct)
|
||||
|
||||
def get_fields(self):
|
||||
return self.ibdata
|
||||
|
||||
def is_dead(self, ct):
|
||||
return ct > self.last_msg + HB_LIFETIME
|
||||
|
||||
def not_dead(self, ct):
|
||||
self.last_msg = ct
|
||||
|
||||
def send_delayed(self, t, msg):
|
||||
self.reactor.push(lambda et, ct : self.send(msg))
|
||||
|
||||
def send(self, msg):
|
||||
self.server.sockfd.sendto(msg, (self.addr, self.port))
|
||||
|
||||
def on_msg(self, ct, msg):
|
||||
if len(msg) < 4:
|
||||
# empty message - do nothing
|
||||
return
|
||||
|
||||
typ = msg[:4]
|
||||
msg = msg[4:]
|
||||
|
||||
if typ == "1CEB" and len(msg) >= 6:
|
||||
hbver, ibver = struct.unpack("<HI", msg[:6])
|
||||
msg = msg[6:]
|
||||
|
||||
if hbver != HB_VERSION or ((ibver^IB_VERSION)&IB_VERSION_MASK) != 0:
|
||||
# version is incorrect
|
||||
self.send("BADV" + struct.pack("<HI", HB_VERSION, IB_VERSION))
|
||||
elif len(msg) != (2+2+2+30+10+30):
|
||||
# bad format
|
||||
print "BADF", len(msg)
|
||||
self.send("BADF")
|
||||
else:
|
||||
# parse this!
|
||||
d = {}
|
||||
d["address"] = str(self.addr)
|
||||
d["port"], d["players_current"], d["players_max"] = struct.unpack("<HHH", msg[:6])
|
||||
msg = msg[6:]
|
||||
d["name"] = stripnul(msg[:30])
|
||||
msg = msg[30:]
|
||||
d["mode"] = stripnul(msg[:10])
|
||||
msg = msg[10:]
|
||||
d["map"] = stripnul(msg[:30])
|
||||
|
||||
d["version"] = ib_version_str(ibver)
|
||||
|
||||
self.ibdata = d
|
||||
self.not_dead(ct)
|
||||
self.send("MSOK")
|
||||
print "MSOK", d
|
||||
|
||||
hb_reactor = HReactor()
|
||||
hb_server = HServer(hb_reactor.get_time(), hb_reactor, socket.AF_INET, CONN_PORT)
|
||||
hb_reactor.run()
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#define VERSION_X 1
|
||||
#define VERSION_Y 1
|
||||
#define VERSION_A 0
|
||||
#define VERSION_Z 3
|
||||
#define VERSION_Z 4
|
||||
// Remember to bump "Z" basically every time you change the engine!
|
||||
// Remember to bump the version in Lua too!
|
||||
// Remember to document API changes in a new version!
|
||||
|
@ -137,6 +137,6 @@ do
|
||||
|
||||
common.map_set(lmap)
|
||||
print("gen finished")
|
||||
return ret
|
||||
return ret, "classic("..mw..","..mh..")"
|
||||
end
|
||||
|
||||
|
@ -36,6 +36,6 @@ do
|
||||
end
|
||||
end
|
||||
print("gen finished")
|
||||
return ret
|
||||
return ret, "flat("..mx..","..mz..","..my..")"
|
||||
end
|
||||
|
||||
|
131
pkg/base/lib_heartbeat.lua
Normal file
131
pkg/base/lib_heartbeat.lua
Normal file
@ -0,0 +1,131 @@
|
||||
--[[
|
||||
This file is part of Ice Lua Components.
|
||||
|
||||
Ice Lua Components is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Ice Lua Components is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with Ice Lua Components. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
HB_VERSION = 1
|
||||
|
||||
heartbeat_sockfd = nil
|
||||
heartbeat_t_nextmsg = nil
|
||||
heartbeat_t_nextburst = nil
|
||||
heartbeat_burstsleft = nil
|
||||
heartbeat_cooloff = true
|
||||
|
||||
local function pad_nul(n, s)
|
||||
while s:len() < n do
|
||||
s = s .. "\0"
|
||||
end
|
||||
|
||||
if s:len() > n then
|
||||
s = s:sub(1, n)
|
||||
end
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
function heartbeat_init()
|
||||
-- check if we have this actually enabled
|
||||
if not server_config.heartbeat_send then return end
|
||||
|
||||
-- open the socket
|
||||
heartbeat_sockfd = common.udp_open()
|
||||
end
|
||||
|
||||
function heartbeat_update(sec_current, sec_delta)
|
||||
-- we need to let the timer "cool off" as the first few values are just plain wrong.
|
||||
if heartbeat_cooloff then
|
||||
if sec_current < 60 and sec_current >= 2 then
|
||||
heartbeat_cooloff = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- if we're using the wrong heartbeat and/or iceball version,
|
||||
-- heartbeat_sockfd will be nil,
|
||||
-- because we have given up.
|
||||
-- (it'll also be nil if we haven't enabled the heartbeat client.)
|
||||
if not heartbeat_sockfd then return end
|
||||
|
||||
-- versions before 0.1.1-4 don't have server.port,
|
||||
-- so we need to rip the port from server.hook_connect.
|
||||
if not server.port then return end
|
||||
|
||||
-- check if we received any messages
|
||||
while true do
|
||||
local msg, host, port = common.udp_recvfrom(heartbeat_sockfd)
|
||||
if msg == "" then
|
||||
break
|
||||
elseif msg == false then
|
||||
error("UDP socket used to connect to master servers broke horribly. What the hell?!")
|
||||
elseif msg == "MSOK" then
|
||||
-- we're ignoring MSOK messages for now,
|
||||
-- until we can track ALL master/heartbeat servers properly
|
||||
elseif msg == "BADF" then
|
||||
error("heartbeat server \""..host.."\" port "..port.." reports bad packet format - FIX ME OR REMOVE THIS SERVER")
|
||||
elseif msg:len() >= 4 and msg:sub(1,4) == "BADV" then
|
||||
error("heartbeat server \""..host.."\" port "..port.." reports bad version - UPGRADE OR REMOVE THIS SERVER")
|
||||
end
|
||||
end
|
||||
|
||||
-- check if we need to send a new burst
|
||||
heartbeat_t_nextburst = heartbeat_t_nextburst or sec_current
|
||||
|
||||
if sec_current >= heartbeat_t_nextburst then
|
||||
heartbeat_t_burstsleft = 5
|
||||
heartbeat_t_nextmsg = heartbeat_t_nextburst
|
||||
heartbeat_t_nextburst = heartbeat_t_nextburst + 40
|
||||
end
|
||||
|
||||
-- check if we need to send a new message
|
||||
if heartbeat_t_burstsleft and heartbeat_t_nextmsg and sec_current >= heartbeat_t_nextmsg then
|
||||
-- get player count
|
||||
local players_max = players.max
|
||||
local players_current = 0
|
||||
local i
|
||||
|
||||
for i=1,players_max do
|
||||
if players[i] then
|
||||
players_current = players_current + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- assemble message
|
||||
local msg = "1CEB" .. common.net_pack("HI", HB_VERSION, common.version.num)
|
||||
msg = msg .. common.net_pack("HHH", server.port, players_current, players_max)
|
||||
msg = msg .. pad_nul(30, server_config.name)
|
||||
msg = msg .. pad_nul(10, game_hb_mode)
|
||||
msg = msg .. pad_nul(30, map_name)
|
||||
|
||||
--print("HEARTBEAT MESSAGE")
|
||||
|
||||
-- send message
|
||||
local i
|
||||
local hbl = server_config.heartbeat
|
||||
for i=1,#hbl do
|
||||
local host, port = hbl[i][1], hbl[i][2]
|
||||
common.udp_sendto(heartbeat_sockfd, msg, host, port)
|
||||
end
|
||||
|
||||
-- give time for next message if necessary
|
||||
heartbeat_t_burstsleft = heartbeat_t_burstsleft - 1
|
||||
if heartbeat_t_burstsleft <= 0 then
|
||||
heartbeat_t_burstsleft = nil
|
||||
heartbeat_t_nextmsg = nil
|
||||
else
|
||||
heartbeat_t_nextmsg = heartbeat_t_nextmsg + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -66,6 +66,7 @@ load_mod_list(getfenv(), mod_data.mods, {"preload", "preload_server"}, server_co
|
||||
|
||||
dofile("pkg/base/common.lua")
|
||||
dofile("pkg/base/commands.lua")
|
||||
dofile("pkg/base/lib_heartbeat.lua")
|
||||
|
||||
client_list = {fdlist={}, banned={}}
|
||||
server_tick_accum = 0
|
||||
@ -161,6 +162,9 @@ function server.hook_connect(neth, addrinfo)
|
||||
addrinfo.addr and addrinfo.addr.ip,
|
||||
addrinfo.addr and addrinfo.addr.cport)
|
||||
|
||||
-- workaround for pre-0.1.1-4 versions
|
||||
server.port = server.port or (addrinfo.addr and addrinfo.addr.sport)
|
||||
|
||||
local source = false
|
||||
if addrinfo.proto == "enet/ip6" or addrinfo.proto == "tcp/ip6" then
|
||||
-- There are two variants:
|
||||
@ -228,6 +232,8 @@ end
|
||||
|
||||
lflush = nil
|
||||
function server.hook_tick(sec_current, sec_delta)
|
||||
heartbeat_update(sec_current, sec_delta)
|
||||
|
||||
--print("tick",sec_current,sec_delta)
|
||||
--[[
|
||||
local xlen,ylen,zlen
|
||||
@ -416,17 +422,38 @@ end
|
||||
|
||||
-- load map
|
||||
if server_settings.gen then
|
||||
map_loaded = loadfile(server_settings.gen)(loose, server_toggles, server_settings)
|
||||
map_loaded, map_name = loadfile(server_settings.gen)(loose, server_toggles, server_settings)
|
||||
elseif map_fname then
|
||||
map_loaded = common.map_load(map_fname, "auto")
|
||||
map_name = map_fname
|
||||
while map_name do
|
||||
local p = map_name:find("/", 1, true)
|
||||
if not p then break end
|
||||
map_name = map_name:sub(p+1)
|
||||
end
|
||||
else
|
||||
map_loaded = loadfile("pkg/base/gen_classic.lua")(loose, server_toggles, server_settings)
|
||||
map_loaded, map_name = loadfile("pkg/base/gen_classic.lua")(loose, server_toggles, server_settings)
|
||||
end
|
||||
|
||||
if not map_name then
|
||||
map_name = "<?>"
|
||||
end
|
||||
|
||||
game_hb_mode = game_mode_file
|
||||
while true do
|
||||
local p = game_hb_mode:find("/", 1, true)
|
||||
if not p then break end
|
||||
game_hb_mode = game_hb_mode:sub(p+1)
|
||||
end
|
||||
|
||||
common.map_set(map_loaded)
|
||||
|
||||
mode_create_server()
|
||||
|
||||
print("pkg/base/main_server.lua: Loading mods...")
|
||||
load_mod_list(getfenv(), mod_data.mods, {"load", "load_server"}, server_config, mod_data)
|
||||
|
||||
print("Starting heartbeat server...")
|
||||
heartbeat_init()
|
||||
print("pkg/base/main_server.lua loaded.")
|
||||
|
||||
|
@ -583,6 +583,11 @@ int icelua_init(void)
|
||||
|
||||
icelua_pushversion(lstate_server, "common");
|
||||
icelua_pushversion(lstate_server, "server");
|
||||
|
||||
lua_getglobal(lstate_server, "server");
|
||||
lua_pushinteger(lstate_server, net_port);
|
||||
lua_setfield(lstate_server, -2, "port");
|
||||
lua_pop(lstate_server, 1);
|
||||
}
|
||||
|
||||
if(lstate_client != NULL)
|
||||
|
Loading…
x
Reference in New Issue
Block a user