Last active
February 28, 2018 08:11
-
-
Save jkbz64/d18c62b51b00f1b9ab3f959219eea203 to your computer and use it in GitHub Desktop.
lua-enet 5.3 for C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Slightly modified(at least for lua5.3.4 and C++ compiler) version of love2D's lua-enet | |
// https://bitbucket.org/rude/love/src/6cd71997f82541ae1ef1338c8afe0d47f02f1189/src/libraries/enet/enet.cpp | |
// https://github.com/leafo/lua-enet (original lua-enet which is love2D's version based on) | |
/** | |
* | |
* Copyright (C) 2014 by Leaf Corcoran | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
* THE SOFTWARE. | |
*/ | |
#include <stdlib.h> | |
#include <string.h> | |
extern "C" | |
{ | |
#define LUA_COMPAT_MODULE | |
#include "lua.h" | |
#include "lualib.h" | |
#include "lauxlib.h" | |
#include <enet/enet.h> | |
} | |
#define check_host(l, idx)\ | |
*(ENetHost**)luaL_checkudata(l, idx, "enet_host") | |
#define check_peer(l, idx)\ | |
*(ENetPeer**)luaL_checkudata(l, idx, "enet_peer") | |
/** | |
* Parse address string, eg: | |
* *:5959 | |
* 127.0.0.1:* | |
* website.com:8080 | |
*/ | |
static void parse_address(lua_State *l, const char *addr_str, ENetAddress *address) { | |
int host_i = 0, port_i = 0; | |
char host_str[128] = {0}; | |
char port_str[32] = {0}; | |
int scanning_port = 0; | |
char *c = (char *)addr_str; | |
while (*c != 0) { | |
if (host_i >= 128 || port_i >= 32 ) luaL_error(l, "Hostname too long"); | |
if (scanning_port) { | |
port_str[port_i++] = *c; | |
} else { | |
if (*c == ':') { | |
scanning_port = 1; | |
} else { | |
host_str[host_i++] = *c; | |
} | |
} | |
c++; | |
} | |
host_str[host_i] = '\0'; | |
port_str[port_i] = '\0'; | |
if (host_i == 0) luaL_error(l, "Failed to parse address"); | |
if (port_i == 0) luaL_error(l, "Missing port in address"); | |
if (strcmp("*", host_str) == 0) { | |
address->host = ENET_HOST_ANY; | |
} else { | |
if (enet_address_set_host(address, host_str) != 0) { | |
luaL_error(l, "Failed to resolve host name"); | |
} | |
} | |
if (strcmp("*", port_str) == 0) { | |
address->port = ENET_PORT_ANY; | |
} else { | |
address->port = atoi(port_str); | |
} | |
} | |
/** | |
* Find the index of a given peer for which we only have the pointer. | |
*/ | |
static size_t find_peer_index(lua_State *l, ENetHost *enet_host, ENetPeer *peer) { | |
size_t peer_index; | |
for (peer_index = 0; peer_index < enet_host->peerCount; peer_index++) { | |
if (peer == &(enet_host->peers[peer_index])) | |
return peer_index; | |
} | |
luaL_error (l, "enet: could not find peer id!"); | |
return peer_index; | |
} | |
static void push_peer(lua_State *l, ENetPeer *peer) { | |
// try to find in peer table | |
lua_getfield(l, LUA_REGISTRYINDEX, "enet_peers"); | |
lua_pushlightuserdata(l, peer); | |
lua_gettable(l, -2); | |
if (lua_isnil(l, -1)) { | |
// printf("creating new peer\n"); | |
lua_pop(l, 1); | |
*(ENetPeer**)lua_newuserdata(l, sizeof(void*)) = peer; | |
luaL_getmetatable(l, "enet_peer"); | |
lua_setmetatable(l, -2); | |
lua_pushlightuserdata(l, peer); | |
lua_pushvalue(l, -2); | |
lua_settable(l, -4); | |
} | |
lua_remove(l, -2); // remove enet_peers | |
} | |
static void push_event(lua_State *l, ENetEvent *event) { | |
lua_newtable(l); // event table | |
if (event->peer) { | |
push_peer(l, event->peer); | |
lua_setfield(l, -2, "peer"); | |
} | |
switch (event->type) { | |
case ENET_EVENT_TYPE_CONNECT: | |
lua_pushinteger(l, event->data); | |
lua_setfield(l, -2, "data"); | |
lua_pushstring(l, "connect"); | |
break; | |
case ENET_EVENT_TYPE_DISCONNECT: | |
lua_pushinteger(l, event->data); | |
lua_setfield(l, -2, "data"); | |
lua_pushstring(l, "disconnect"); | |
break; | |
case ENET_EVENT_TYPE_RECEIVE: | |
lua_pushlstring(l, (const char *)event->packet->data, event->packet->dataLength); | |
lua_setfield(l, -2, "data"); | |
lua_pushinteger(l, event->channelID); | |
lua_setfield(l, -2, "channel"); | |
lua_pushstring(l, "receive"); | |
enet_packet_destroy(event->packet); | |
break; | |
case ENET_EVENT_TYPE_NONE: | |
lua_pushstring(l, "none"); | |
break; | |
} | |
lua_setfield(l, -2, "type"); | |
} | |
/** | |
* Read a packet off the stack as a string | |
* idx is position of string | |
*/ | |
static ENetPacket *read_packet(lua_State *l, int idx, enet_uint8 *channel_id) { | |
size_t size; | |
int argc = lua_gettop(l); | |
const void *data = luaL_checklstring(l, idx, &size); | |
ENetPacket *packet; | |
enet_uint32 flags = ENET_PACKET_FLAG_RELIABLE; | |
*channel_id = 0; | |
if (argc >= idx+2 && !lua_isnil(l, idx+2)) { | |
const char *flag_str = luaL_checkstring(l, idx+2); | |
if (strcmp("unsequenced", flag_str) == 0) { | |
flags = ENET_PACKET_FLAG_UNSEQUENCED; | |
} else if (strcmp("reliable", flag_str) == 0) { | |
flags = ENET_PACKET_FLAG_RELIABLE; | |
} else if (strcmp("unreliable", flag_str) == 0) { | |
flags = 0; | |
} else { | |
luaL_error(l, "Unknown packet flag: %s", flag_str); | |
} | |
} | |
if (argc >= idx+1 && !lua_isnil(l, idx+1)) { | |
*channel_id = (int) luaL_checknumber(l, idx+1); | |
} | |
packet = enet_packet_create(data, size, flags); | |
if (packet == NULL) { | |
luaL_error(l, "Failed to create packet"); | |
} | |
return packet; | |
} | |
/** | |
* Create a new host | |
* Args: | |
* address (nil for client) | |
* [peer_count = 64] | |
* [channel_count = 1] | |
* [in_bandwidth = 0] | |
* [out_bandwidth = 0] | |
*/ | |
static int host_create(lua_State *l) { | |
ENetHost *host; | |
size_t peer_count = 64, channel_count = 1; | |
enet_uint32 in_bandwidth = 0, out_bandwidth = 0; | |
int have_address = 1; | |
ENetAddress address; | |
if (lua_gettop(l) == 0 || lua_isnil(l, 1)) { | |
have_address = 0; | |
} else { | |
parse_address(l, luaL_checkstring(l, 1), &address); | |
} | |
switch (lua_gettop(l)) { | |
case 5: | |
if (!lua_isnil(l, 5)) out_bandwidth = (int) luaL_checknumber(l, 5); | |
case 4: | |
if (!lua_isnil(l, 4)) in_bandwidth = (int) luaL_checknumber(l, 4); | |
case 3: | |
if (!lua_isnil(l, 3)) channel_count = (int) luaL_checknumber(l, 3); | |
case 2: | |
if (!lua_isnil(l, 2)) peer_count = (int) luaL_checknumber(l, 2); | |
} | |
// printf("host create, peers=%d, channels=%d, in=%d, out=%d\n", | |
// peer_count, channel_count, in_bandwidth, out_bandwidth); | |
host = enet_host_create(have_address ? &address : NULL, peer_count, | |
channel_count, in_bandwidth, out_bandwidth); | |
if (host == NULL) { | |
lua_pushnil (l); | |
lua_pushstring(l, "enet: failed to create host (already listening?)"); | |
return 2; | |
} | |
*(ENetHost**)lua_newuserdata(l, sizeof(void*)) = host; | |
luaL_getmetatable(l, "enet_host"); | |
lua_setmetatable(l, -2); | |
return 1; | |
} | |
static int linked_version(lua_State *l) { | |
lua_pushfstring(l, "%d.%d.%d", | |
ENET_VERSION_GET_MAJOR(enet_linked_version()), | |
ENET_VERSION_GET_MINOR(enet_linked_version()), | |
ENET_VERSION_GET_PATCH(enet_linked_version())); | |
return 1; | |
} | |
/** | |
* Serice a host | |
* Args: | |
* timeout | |
* | |
* Return | |
* nil on no event | |
* an event table on event | |
*/ | |
static int host_service(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
ENetEvent event; | |
int timeout = 0, out; | |
if (lua_gettop(l) > 1) | |
timeout = (int) luaL_checknumber(l, 2); | |
out = enet_host_service(host, &event, timeout); | |
if (out == 0) return 0; | |
if (out < 0) return luaL_error(l, "Error during service"); | |
push_event(l, &event); | |
return 1; | |
} | |
/** | |
* Dispatch a single event if available | |
*/ | |
static int host_check_events(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
ENetEvent event; | |
int out = enet_host_check_events(host, &event); | |
if (out == 0) return 0; | |
if (out < 0) return luaL_error(l, "Error checking event"); | |
push_event(l, &event); | |
return 1; | |
} | |
/** | |
* Enables an adaptive order-2 PPM range coder for the transmitted data of | |
* all peers. | |
*/ | |
static int host_compress_with_range_coder(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
int result = enet_host_compress_with_range_coder (host); | |
if (result == 0) { | |
lua_pushboolean (l, 1); | |
} else { | |
lua_pushboolean (l, 0); | |
} | |
return 1; | |
} | |
/** | |
* Connect a host to an address | |
* Args: | |
* the address | |
* [channel_count = 1] | |
* [data = 0] | |
*/ | |
static int host_connect(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
ENetAddress address; | |
ENetPeer *peer; | |
enet_uint32 data = 0; | |
size_t channel_count = 1; | |
parse_address(l, luaL_checkstring(l, 2), &address); | |
switch (lua_gettop(l)) { | |
case 4: | |
if (!lua_isnil(l, 4)) data = (int) luaL_checknumber(l, 4); | |
case 3: | |
if (!lua_isnil(l, 3)) channel_count = (int) luaL_checknumber(l, 3); | |
} | |
// printf("host connect, channels=%d, data=%d\n", channel_count, data); | |
peer = enet_host_connect(host, &address, channel_count, data); | |
if (peer == NULL) { | |
return luaL_error(l, "Failed to create peer"); | |
} | |
push_peer(l, peer); | |
return 1; | |
} | |
static int host_flush(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
enet_host_flush(host); | |
return 0; | |
} | |
static int host_broadcast(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
enet_uint8 channel_id; | |
ENetPacket *packet = read_packet(l, 2, &channel_id); | |
enet_host_broadcast(host, channel_id, packet); | |
return 0; | |
} | |
// Args: limit:number | |
static int host_channel_limit(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
int limit = (int) luaL_checknumber(l, 2); | |
enet_host_channel_limit(host, limit); | |
return 0; | |
} | |
static int host_bandwidth_limit(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
enet_uint32 in_bandwidth = (int) luaL_checknumber(l, 2); | |
enet_uint32 out_bandwidth = (int) luaL_checknumber(l, 2); | |
enet_host_bandwidth_limit(host, in_bandwidth, out_bandwidth); | |
return 0; | |
} | |
static int host_get_socket_address(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
ENetAddress address; | |
enet_socket_get_address (host->socket, &address); | |
lua_pushfstring(l, "%d.%d.%d.%d:%d", | |
((address.host) & 0xFF), | |
((address.host >> 8) & 0xFF), | |
((address.host >> 16) & 0xFF), | |
(address.host >> 24& 0xFF), | |
address.port); | |
return 1; | |
} | |
static int host_total_sent_data(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
lua_pushinteger (l, host->totalSentData); | |
return 1; | |
} | |
static int host_total_received_data(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
lua_pushinteger (l, host->totalReceivedData); | |
return 1; | |
} | |
static int host_service_time(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
lua_pushinteger (l, host->serviceTime); | |
return 1; | |
} | |
static int host_peer_count(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
lua_pushinteger (l, host->peerCount); | |
return 1; | |
} | |
static int host_get_peer(lua_State *l) { | |
ENetHost *host = check_host(l, 1); | |
if (!host) { | |
return luaL_error(l, "Tried to index a nil host!"); | |
} | |
int peer_index = (int) luaL_checknumber(l, 2) - 1; | |
if (peer_index < 0 || ((size_t) peer_index) >= host->peerCount) { | |
luaL_argerror (l, 2, "Invalid peer index"); | |
} | |
ENetPeer *peer = &(host->peers[peer_index]); | |
push_peer (l, peer); | |
return 1; | |
} | |
static int host_gc(lua_State *l) { | |
// We have to manually grab the userdata so that we can set it to NULL. | |
ENetHost** host = (ENetHost**)luaL_checkudata(l, 1, "enet_host"); | |
// We don't want to crash by destroying a non-existant host. | |
if (*host) { | |
enet_host_destroy(*host); | |
} | |
*host = NULL; | |
return 0; | |
} | |
static int peer_tostring(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
char host_str[128]; | |
enet_address_get_host_ip(&peer->address, host_str, 128); | |
lua_pushstring(l, host_str); | |
lua_pushstring(l, ":"); | |
lua_pushinteger(l, peer->address.port); | |
lua_concat(l, 3); | |
return 1; | |
} | |
static int peer_ping(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_peer_ping(peer); | |
return 0; | |
} | |
static int peer_throttle_configure(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint32 interval = (int) luaL_checknumber(l, 2); | |
enet_uint32 acceleration = (int) luaL_checknumber(l, 3); | |
enet_uint32 deceleration = (int) luaL_checknumber(l, 4); | |
enet_peer_throttle_configure(peer, interval, acceleration, deceleration); | |
return 0; | |
} | |
static int peer_round_trip_time(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
if (lua_gettop(l) > 1) { | |
enet_uint32 round_trip_time = (int) luaL_checknumber(l, 2); | |
peer->roundTripTime = round_trip_time; | |
} | |
lua_pushinteger (l, peer->roundTripTime); | |
return 1; | |
} | |
static int peer_last_round_trip_time(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
if (lua_gettop(l) > 1) { | |
enet_uint32 round_trip_time = (int) luaL_checknumber(l, 2); | |
peer->lastRoundTripTime = round_trip_time; | |
} | |
lua_pushinteger (l, peer->lastRoundTripTime); | |
return 1; | |
} | |
static int peer_ping_interval(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
if (lua_gettop(l) > 1) { | |
enet_uint32 interval = (int) luaL_checknumber(l, 2); | |
enet_peer_ping_interval (peer, interval); | |
} | |
lua_pushinteger (l, peer->pingInterval); | |
return 1; | |
} | |
static int peer_timeout(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint32 timeout_limit = 0; | |
enet_uint32 timeout_minimum = 0; | |
enet_uint32 timeout_maximum = 0; | |
switch (lua_gettop(l)) { | |
case 4: | |
if (!lua_isnil(l, 4)) timeout_maximum = (int) luaL_checknumber(l, 4); | |
case 3: | |
if (!lua_isnil(l, 3)) timeout_minimum = (int) luaL_checknumber(l, 3); | |
case 2: | |
if (!lua_isnil(l, 2)) timeout_limit = (int) luaL_checknumber(l, 2); | |
} | |
enet_peer_timeout (peer, timeout_limit, timeout_minimum, timeout_maximum); | |
lua_pushinteger (l, peer->timeoutLimit); | |
lua_pushinteger (l, peer->timeoutMinimum); | |
lua_pushinteger (l, peer->timeoutMaximum); | |
return 3; | |
} | |
static int peer_disconnect(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint32 data = lua_gettop(l) > 1 ? (int) luaL_checknumber(l, 2) : 0; | |
enet_peer_disconnect(peer, data); | |
return 0; | |
} | |
static int peer_disconnect_now(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint32 data = lua_gettop(l) > 1 ? (int) luaL_checknumber(l, 2) : 0; | |
enet_peer_disconnect_now(peer, data); | |
return 0; | |
} | |
static int peer_disconnect_later(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint32 data = lua_gettop(l) > 1 ? (int) luaL_checknumber(l, 2) : 0; | |
enet_peer_disconnect_later(peer, data); | |
return 0; | |
} | |
static int peer_index(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
size_t peer_index = find_peer_index (l, peer->host, peer); | |
lua_pushinteger (l, peer_index + 1); | |
return 1; | |
} | |
static int peer_state(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
switch (peer->state) { | |
case (ENET_PEER_STATE_DISCONNECTED): | |
lua_pushstring (l, "disconnected"); | |
break; | |
case (ENET_PEER_STATE_CONNECTING): | |
lua_pushstring (l, "connecting"); | |
break; | |
case (ENET_PEER_STATE_ACKNOWLEDGING_CONNECT): | |
lua_pushstring (l, "acknowledging_connect"); | |
break; | |
case (ENET_PEER_STATE_CONNECTION_PENDING): | |
lua_pushstring (l, "connection_pending"); | |
break; | |
case (ENET_PEER_STATE_CONNECTION_SUCCEEDED): | |
lua_pushstring (l, "connection_succeeded"); | |
break; | |
case (ENET_PEER_STATE_CONNECTED): | |
lua_pushstring (l, "connected"); | |
break; | |
case (ENET_PEER_STATE_DISCONNECT_LATER): | |
lua_pushstring (l, "disconnect_later"); | |
break; | |
case (ENET_PEER_STATE_DISCONNECTING): | |
lua_pushstring (l, "disconnecting"); | |
break; | |
case (ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT): | |
lua_pushstring (l, "acknowledging_disconnect"); | |
break; | |
case (ENET_PEER_STATE_ZOMBIE): | |
lua_pushstring (l, "zombie"); | |
break; | |
default: | |
lua_pushstring (l, "unknown"); | |
} | |
return 1; | |
} | |
static int peer_connect_id(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
lua_pushinteger (l, peer->connectID); | |
return 1; | |
} | |
static int peer_reset(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_peer_reset(peer); | |
return 0; | |
} | |
static int peer_receive(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
ENetPacket *packet; | |
enet_uint8 channel_id = 0; | |
if (lua_gettop(l) > 1) { | |
channel_id = (int) luaL_checknumber(l, 2); | |
} | |
packet = enet_peer_receive(peer, &channel_id); | |
if (packet == NULL) return 0; | |
lua_pushlstring(l, (const char *)packet->data, packet->dataLength); | |
lua_pushinteger(l, channel_id); | |
enet_packet_destroy(packet); | |
return 2; | |
} | |
/** | |
* Send a lua string to a peer | |
* Args: | |
* packet data, string | |
* channel id | |
* flags ["reliable", nil] | |
* | |
*/ | |
static int peer_send(lua_State *l) { | |
ENetPeer *peer = check_peer(l, 1); | |
enet_uint8 channel_id; | |
ENetPacket *packet = read_packet(l, 2, &channel_id); | |
// printf("sending, channel_id=%d\n", channel_id); | |
int ret = enet_peer_send(peer, channel_id, packet); | |
if (ret < 0) { | |
enet_packet_destroy(packet); | |
} | |
lua_pushinteger(l, ret); | |
return 1; | |
} | |
static const struct luaL_Reg enet_funcs [] = { | |
{"host_create", host_create}, | |
{"linked_version", linked_version}, | |
{NULL, NULL} | |
}; | |
static const struct luaL_Reg enet_host_funcs [] = { | |
{"service", host_service}, | |
{"check_events", host_check_events}, | |
{"compress_with_range_coder", host_compress_with_range_coder}, | |
{"connect", host_connect}, | |
{"flush", host_flush}, | |
{"broadcast", host_broadcast}, | |
{"channel_limit", host_channel_limit}, | |
{"bandwidth_limit", host_bandwidth_limit}, | |
// Since ENetSocket isn't part of enet-lua, we should try to keep | |
// naming conventions the same as the rest of the lib. | |
{"get_socket_address", host_get_socket_address}, | |
// We need this function to free up our ports when needed! | |
{"destroy", host_gc}, | |
// additional convenience functions (mostly accessors) | |
{"total_sent_data", host_total_sent_data}, | |
{"total_received_data", host_total_received_data}, | |
{"service_time", host_service_time}, | |
{"peer_count", host_peer_count}, | |
{"get_peer", host_get_peer}, | |
{NULL, NULL} | |
}; | |
static const struct luaL_Reg enet_peer_funcs [] = { | |
{"disconnect", peer_disconnect}, | |
{"disconnect_now", peer_disconnect_now}, | |
{"disconnect_later", peer_disconnect_later}, | |
{"reset", peer_reset}, | |
{"ping", peer_ping}, | |
{"receive", peer_receive}, | |
{"send", peer_send}, | |
{"throttle_configure", peer_throttle_configure}, | |
{"ping_interval", peer_ping_interval}, | |
{"timeout", peer_timeout}, | |
// additional convenience functions to member variables | |
{"index", peer_index}, | |
{"state", peer_state}, | |
{"connect_id", peer_connect_id}, | |
{"round_trip_time", peer_round_trip_time}, | |
{"last_round_trip_time", peer_last_round_trip_time}, | |
{NULL, NULL} | |
}; | |
extern "C" int luaopen_enet(lua_State *l) { | |
enet_initialize(); | |
atexit(enet_deinitialize); | |
// create metatables | |
luaL_newmetatable(l, "enet_host"); | |
lua_newtable(l); // index | |
luaL_openlib(l, NULL, enet_host_funcs, 0); | |
lua_setfield(l, -2, "__index"); | |
lua_pushcfunction(l, host_gc); | |
lua_setfield(l, -2, "__gc"); | |
luaL_newmetatable(l, "enet_peer"); | |
lua_newtable(l); | |
luaL_openlib(l, NULL, enet_peer_funcs, 0); | |
lua_setfield(l, -2, "__index"); | |
lua_pushcfunction(l, peer_tostring); | |
lua_setfield(l, -2, "__tostring"); | |
// set up peer table | |
lua_newtable(l); | |
lua_newtable(l); // metatable | |
lua_pushstring(l, "v"); | |
lua_setfield(l, -2, "__mode"); | |
lua_setmetatable(l, -2); | |
lua_setfield(l, LUA_REGISTRYINDEX, "enet_peers"); | |
luaL_openlib(l, NULL, enet_funcs, 0); | |
// return the enet table created with luaL_register | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment