Started adding CoopNet

This commit is contained in:
MysterD 2023-04-09 17:20:07 -07:00
parent 2f4008f9c9
commit 04032a14af
14 changed files with 267 additions and 35 deletions

View file

@ -534,7 +534,7 @@ SRC_DIRS := src src/engine src/game src/audio src/bass_audio src/menu src/buffer
BIN_DIRS := bin bin/$(VERSION)
# PC files
SRC_DIRS += src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/pc/mods src/pc/network src/pc/network/packets src/pc/network/socket src/pc/utils src/pc/utils/miniz src/pc/djui src/pc/lua src/pc/lua/utils
SRC_DIRS += src/pc src/pc/gfx src/pc/audio src/pc/controller src/pc/fs src/pc/fs/packtypes src/pc/mods src/pc/network src/pc/network/packets src/pc/network/socket src/pc/network/coopnet src/pc/utils src/pc/utils/miniz src/pc/djui src/pc/lua src/pc/lua/utils
#ifeq ($(DISCORDRPC),1)
# SRC_DIRS += src/pc/discord
@ -794,7 +794,7 @@ INCLUDE_DIRS := include $(BUILD_DIR) $(BUILD_DIR)/include src .
ifeq ($(TARGET_N64),1)
INCLUDE_DIRS += include/libc
else
INCLUDE_DIRS += sound lib/lua/include $(EXTRA_INCLUDES)
INCLUDE_DIRS += sound lib/lua/include lib/coopnet/include $(EXTRA_INCLUDES)
endif
# Connfigure backend flags
@ -971,6 +971,26 @@ else
LDFLAGS += -Llib/lua/linux -l:liblua53.a -ldl
endif
# coopnet
LDFLAGS += -Llib/coopnet/linux -l:libcoopnet.a -l:libjuice.a
#ifeq ($(WINDOWS_BUILD),1)
# ifeq ($(TARGET_BITS), 32)
# LDFLAGS += -Llib/coopnet/win32 -l:libcoopnet.a
# else
# LDFLAGS += -Llib/coopnet/win64 -l:libcoopnet.a
# endif
#else ifeq ($(OSX_BUILD),1)
# LDFLAGS += -L./lib/coopnet/mac/ -l coopnet
#else ifeq ($(TARGET_RPI),1)
# ifneq (,$(findstring aarch64,$(machine)))
# LDFLAGS += -Llib/coopnet/linux -l:libcoopnet-arm64.a
# else
# LDFLAGS += -Llib/coopnet/linux -l:libcoopnet-arm.a
# endif
#else
# LDFLAGS += -Llib/coopnet/linux -l:libcoopnet.a
#endif
# Network/Discord/Bass (ugh, needs cleanup)
ifeq ($(WINDOWS_BUILD),1)
LDFLAGS += -L"ws2_32" -lwsock32

View file

@ -176,6 +176,7 @@ SERVER_TITLE = "SERVER"
HOST_TITLE = "HOST"
DISCORD = "Discord"
DIRECT_CONNECTION = "Direct Connection"
COOPNET = "CoopNet"
NETWORK_SYSTEM = "Network system"
PORT = "Port"
SAVE_SLOT = "Save Slot"

View file

@ -176,6 +176,7 @@ SERVER_TITLE = "SERVEUR"
HOST_TITLE = "HÉBERGER"
DISCORD = "Discord"
DIRECT_CONNECTION = "Connexion Directe"
COOPNET = "CoopNet"
NETWORK_SYSTEM = "Mode d'hébergement"
PORT = "Port"
SAVE_SLOT = "Sauvegarde"

View file

@ -176,6 +176,7 @@ SERVER_TITLE = "SERVER"
HOST_TITLE = "VERANSTALTEN"
DISCORD = "Discord"
DIRECT_CONNECTION = "Direkte Verbindung"
COOPNET = "CoopNet"
NETWORK_SYSTEM = "Netzwerk-System"
PORT = "Port"
SAVE_SLOT = "Save Slot"

View file

@ -175,6 +175,7 @@ AMOUNT_OF_PLAYERS = "Quantidade de jogadores"
SERVER_TITLE = "SERVIDOR"
HOST_TITLE = "HOSTEAR"
DISCORD = "Discord"
COOPNET = "CoopNet"
DIRECT_CONNECTION = "Conexão Direta"
NETWORK_SYSTEM = "Sistema de Rede"
PORT = "Porta"

View file

@ -175,6 +175,7 @@ AMOUNT_OF_PLAYERS = "Número de jugadores"
SERVER_TITLE = "SERVIDOR"
HOST_TITLE = "ALOJAR"
DISCORD = "Discord"
COOPNET = "CoopNet"
DIRECT_CONNECTION = "Conexión Directa"
NETWORK_SYSTEM = "Modo de conexión"
PORT = "Puerto"

View file

@ -0,0 +1,61 @@
#ifndef LIBCOOPNET_H
#define LIBCOOPNET_H
#if defined(__cplusplus)
#include <cstdint>
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
typedef enum {
COOPNET_OK,
COOPNET_FAILED,
COOPNET_DISCONNECTED,
} CoopNetRc;
enum MPacketErrorNumber {
MERR_NONE,
MERR_LOBBY_NOT_FOUND,
MERR_LOBBY_JOIN_FULL,
MERR_LOBBY_JOIN_FAILED,
MERR_MAX,
};
typedef struct {
void (*OnConnected)(uint64_t aUserId);
void (*OnDisconnected)(void);
void (*OnLobbyCreated)(uint64_t aLobbyId, const char* aGame, const char* aVersion, const char* aTitle, uint16_t aMaxConnections);
void (*OnLobbyJoined)(uint64_t aLobbyId, uint64_t aUserId, uint64_t aOwnerId);
void (*OnLobbyLeft)(uint64_t aLobbyId, uint64_t aUserId);
void (*OnLobbyListGot)(uint64_t aLobbyId, uint64_t aOwnerId, uint16_t aConnections, uint16_t aMaxConnections, const char* aGame, const char* aVersion, const char* aTitle);
void (*OnReceive)(uint64_t aFromUserId, const uint8_t* aData, uint64_t aSize);
void (*OnError)(enum MPacketErrorNumber aErrorNumber);
void (*OnPeerConnected)(uint64_t aPeerId);
void (*OnPeerDisconnected)(uint64_t aPeerId);
} CoopNetCallbacks;
typedef struct {
bool SkipWinsockInit;
} CoopNetSettings;
extern CoopNetCallbacks gCoopNetCallbacks;
extern CoopNetSettings gCoopNetSettings;
bool coopnet_is_connected(void);
CoopNetRc coopnet_begin(const char* aHost, uint32_t aPort);
CoopNetRc coopnet_shutdown(void);
CoopNetRc coopnet_update(void);
CoopNetRc coopnet_lobby_create(const char* aGame, const char* aVersion, const char* aTitle, uint16_t aMaxConnections);
CoopNetRc coopnet_lobby_join(uint64_t aLobbyId);
CoopNetRc coopnet_lobby_leave(uint64_t aLobbyId);
CoopNetRc coopnet_lobby_list_get(const char* aGame);
CoopNetRc coopnet_send(const uint8_t* aData, uint64_t aDataLength);
CoopNetRc coopnet_send_to(uint64_t aPeerId, const uint8_t* aData, uint64_t aDataLength);
CoopNetRc coopnet_unpeer(uint64_t aPeerId);
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -12,16 +12,16 @@
#include "pc/configfile.h"
#include "pc/cheats.h"
#ifdef DISCORD_SDK
#define DJUI_HOST_NS_IS_SOCKET (configNetworkSystem == 1)
#else
#define DJUI_HOST_NS_IS_SOCKET (true)
#endif
struct DjuiInputbox* sInputboxPort = NULL;
static void djui_panel_host_network_system_change(UNUSED struct DjuiBase* base) {
djui_base_set_enabled(&sInputboxPort->base, DJUI_HOST_NS_IS_SOCKET);
#ifndef DISCORD_SDK
struct DjuiSelectionbox* selectionbox = (struct DjuiSelectionbox*) base;
if (selectionbox->value == NS_DISCORD) {
selectionbox->value = NS_SOCKET;
}
#endif
djui_base_set_enabled(&sInputboxPort->base, (configNetworkSystem == NS_SOCKET));
}
static bool djui_panel_host_port_valid(void) {
@ -77,15 +77,12 @@ void djui_panel_host_create(struct DjuiBase* caller) {
: DLANG(HOST, HOST_TITLE));
struct DjuiBase* body = djui_three_panel_get_body(panel);
{
#ifdef DISCORD_SDK
char* nChoices[2] = { DLANG(HOST, DISCORD), DLANG(HOST, DIRECT_CONNECTION) };
struct DjuiSelectionbox* selectionbox1 = djui_selectionbox_create(body, DLANG(HOST, NETWORK_SYSTEM), nChoices, 2, &configNetworkSystem, djui_panel_host_network_system_change);
char* nChoices[] = { DLANG(HOST, DISCORD), DLANG(HOST, DIRECT_CONNECTION), DLANG(HOST, COOPNET) };
struct DjuiSelectionbox* selectionbox1 = djui_selectionbox_create(body, DLANG(HOST, NETWORK_SYSTEM), nChoices, 3, &configNetworkSystem, djui_panel_host_network_system_change);
if (gNetworkType == NT_SERVER) {
djui_base_set_enabled(&selectionbox1->base, false);
}
#endif
struct DjuiRect* rect1 = djui_rect_container_create(body, 32);
{
struct DjuiText* text1 = djui_text_create(&rect1->base, DLANG(HOST, PORT));
@ -107,10 +104,8 @@ void djui_panel_host_create(struct DjuiBase* caller) {
djui_interactable_hook_value_change(&inputbox1->base, djui_panel_host_port_text_change);
if (gNetworkType == NT_SERVER) {
djui_base_set_enabled(&inputbox1->base, false);
#ifdef DISCORD_SDK
} else {
djui_base_set_enabled(&inputbox1->base, DJUI_HOST_NS_IS_SOCKET);
#endif
djui_base_set_enabled(&inputbox1->base, (configNetworkSystem == NS_SOCKET));
}
sInputboxPort = inputbox1;
}

View file

@ -22,15 +22,10 @@ void djui_panel_do_host(void) {
update_all_mario_stars();
#ifndef DISCORD_SDK
configNetworkSystem = 1;
network_set_system(NS_SOCKET);
#else
if (configNetworkSystem == 0) {
network_set_system(NS_DISCORD);
} else {
network_set_system(NS_SOCKET);
}
if (configNetworkSystem == NS_DISCORD) { configNetworkSystem = NS_COOPNET; }
#endif
if (configNetworkSystem >= NS_MAX) { configNetworkSystem = NS_MAX; }
network_set_system(configNetworkSystem);
network_init(NT_SERVER);
djui_panel_modlist_create(NULL);
@ -56,14 +51,11 @@ void djui_panel_host_message_create(struct DjuiBase* caller) {
char* warningMessage = NULL;
bool hideHostButton = false;
#ifdef DISCORD_SDK
if (!configNetworkSystem) {
if (configNetworkSystem == NS_DISCORD) {
warningLines = gDiscordFailed ? 5 : 13;
warningMessage = gDiscordFailed ? DLANG(HOST_MESSAGE, WARN_DISCORD2) : DLANG(HOST_MESSAGE, WARN_DISCORD);
hideHostButton = gDiscordFailed;
} else
#endif
{
} else {
warningLines = 5;
warningMessage = calloc(256, sizeof(char));
sprintf(warningMessage, DLANG(HOST_MESSAGE, WARN_SOCKET), configHostPort);
@ -93,10 +85,7 @@ void djui_panel_host_message_create(struct DjuiBase* caller) {
}
djui_panel_add(caller, panel, NULL);
#ifdef DISCORD_SDK
if (configNetworkSystem)
#endif
{
if (configNetworkSystem != NS_DISCORD) {
free(warningMessage);
}
}

View file

@ -143,7 +143,7 @@ void djui_panel_join_do_join(struct DjuiBase* caller) {
}
network_reset_reconnect_and_rehost();
djui_panel_join_ip_text_set_new();
network_set_system(NS_SOCKET);
network_set_system(NS_COOPNET); // DO NOT COMMIT
network_init(NT_CLIENT);
djui_panel_join_message_create(caller);
}

View file

@ -0,0 +1,152 @@
#include "libcoopnet.h"
#include "coopnet.h"
#include "pc/network/network.h"
#include "pc/debuglog.h"
#define HOST "localhost"
#define PORT 34197
static uint64_t sLocalUserId = 0;
static uint64_t sLocalLobbyId = 0;
static uint64_t sLocalLobbyOwnerId = 0;
static uint64_t sNetworkUserIds[MAX_PLAYERS] = { 0 };
static enum NetworkType sNetworkType;
static u8 coopnet_user_id_to_local_index(uint64_t userId) {
for (int i = 1; i < MAX_PLAYERS; i++) {
if (gNetworkPlayers[i].connected && sNetworkUserIds[i] == userId) {
return i;
}
}
return UNKNOWN_LOCAL_INDEX;
}
static void coopnet_on_connected(uint64_t userId) {
sLocalUserId = userId;
if (sNetworkType == NT_SERVER) {
coopnet_lobby_create("sm64ex-coop", "beta 999", "n/a", 16);
} else {
coopnet_lobby_join(1);
}
}
static void coopnet_on_peer_connected(UNUSED uint64_t peerId) {
}
static void coopnet_on_peer_disconnected(uint64_t peerId) {
u8 localIndex = coopnet_user_id_to_local_index(peerId);
if (localIndex != UNKNOWN_LOCAL_INDEX && gNetworkPlayers[localIndex].connected) {
network_player_disconnected(gNetworkPlayers[localIndex].globalIndex);
}
}
static void coopnet_on_receive(uint64_t userId, const uint8_t* data, uint64_t dataLength) {
sNetworkUserIds[0] = userId;
u8 localIndex = coopnet_user_id_to_local_index(userId);
network_receive(localIndex, &userId, (u8*)data, dataLength);
}
static void coopnet_on_lobby_joined(uint64_t lobbyId, uint64_t userId, uint64_t ownerId) {
LOG_INFO("coopnet_on_lobby_joined!");
sNetworkUserIds[0] = ownerId;
sLocalLobbyId = lobbyId;
sLocalLobbyOwnerId = ownerId;
if (userId == sLocalUserId && sNetworkType == NT_CLIENT) {
network_send_mod_list_request();
}
}
static void coopnet_on_lobby_left(uint64_t lobbyId, uint64_t userId) {
LOG_INFO("coopnet_on_lobby_left!");
if (lobbyId == sLocalLobbyId && userId == sLocalUserId) {
network_shutdown(false, false, true);
}
}
static bool ns_coopnet_initialize(enum NetworkType networkType) {
if (coopnet_is_connected()) {
coopnet_shutdown();
}
gCoopNetCallbacks.OnConnected = coopnet_on_connected;
gCoopNetCallbacks.OnReceive = coopnet_on_receive;
gCoopNetCallbacks.OnLobbyJoined = coopnet_on_lobby_joined;
gCoopNetCallbacks.OnLobbyLeft = coopnet_on_lobby_left;
gCoopNetCallbacks.OnPeerConnected = coopnet_on_peer_connected;
gCoopNetCallbacks.OnPeerDisconnected = coopnet_on_peer_disconnected;
sNetworkType = networkType;
return (coopnet_begin(HOST, PORT) == COOPNET_OK);
}
static s64 ns_coopnet_get_id(u8 localIndex) {
if (localIndex == 0) { return (s64)sLocalUserId; }
return (s64)sNetworkUserIds[localIndex];
}
static char* ns_coopnet_get_id_str(u8 localIndex) {
static char id_str[22] = { 0 };
if (localIndex == UNKNOWN_LOCAL_INDEX) {
snprintf(id_str, 22, "???");
} else {
snprintf(id_str, 22, "%lld", (long long int)ns_coopnet_get_id(localIndex));
}
return id_str;
}
static void ns_coopnet_save_id(u8 localIndex, s64 networkId) {
SOFT_ASSERT(localIndex > 0);
SOFT_ASSERT(localIndex < MAX_PLAYERS);
sNetworkUserIds[localIndex] = (networkId == 0) ? sNetworkUserIds[0] : (u64)networkId;
}
static void ns_coopnet_clear_id(u8 localIndex) {
if (localIndex == 0) { return; }
SOFT_ASSERT(localIndex < MAX_PLAYERS);
sNetworkUserIds[localIndex] = 0;
}
static void* ns_coopnet_dup_addr(u8 localIndex) {
void* address = malloc(sizeof(u64));
memcpy(address, &sNetworkUserIds[localIndex], sizeof(u64));
return address;
}
static bool ns_coopnet_match_addr(void* addr1, void* addr2) {
return !memcmp(addr1, addr2, sizeof(u64));
}
static void ns_coopnet_update(void) {
coopnet_update();
}
static int ns_coopnet_network_send(u8 localIndex, void* address, u8* data, u16 dataLength) {
if (!coopnet_is_connected()) { return 1; }
//if (gCurLobbyId == 0) { return 2; }
u64 userId = sNetworkUserIds[localIndex];
if (localIndex == 0 && address != NULL) { userId = *(u64*)address; }
coopnet_send_to(userId, data, dataLength);
return 0;
}
static void ns_coopnet_shutdown(void) {
coopnet_shutdown();
}
struct NetworkSystem gNetworkSystemCoopNet = {
.initialize = ns_coopnet_initialize,
.get_id = ns_coopnet_get_id,
.get_id_str = ns_coopnet_get_id_str,
.save_id = ns_coopnet_save_id,
.clear_id = ns_coopnet_clear_id,
.dup_addr = ns_coopnet_dup_addr,
.match_addr = ns_coopnet_match_addr,
.update = ns_coopnet_update,
.send = ns_coopnet_network_send,
.shutdown = ns_coopnet_shutdown,
.requireServerBroadcast = false,
.name = "CoopNet",
};

View file

@ -0,0 +1,6 @@
#ifndef COOPNET_H
#define COOPNET_H
extern struct NetworkSystem gNetworkSystemCoopNet;
#endif

View file

@ -1,4 +1,5 @@
#include "socket/socket.h"
#include "coopnet/coopnet.h"
#include <stdio.h>
#include "network.h"
#include "object_fields.h"
@ -89,6 +90,7 @@ void network_set_system(enum NetworkSystemType nsType) {
#ifdef DISCORD_SDK
case NS_DISCORD: gNetworkSystem = &gNetworkSystemDiscord; break;
#endif
case NS_COOPNET: gNetworkSystem = &gNetworkSystemCoopNet; break;
default: LOG_ERROR("Unknown network system: %d", nsType);
}
}

View file

@ -37,6 +37,8 @@ extern struct MarioState gMarioStates[];
enum NetworkSystemType {
NS_SOCKET,
NS_DISCORD,
NS_COOPNET,
NS_MAX,
};
struct NetworkSystem {