Lua mod table and download

Mods are now loaded into a table
Clients now request a mod list from the server, then download each file one at a time before joining
Embedded constants.lua into the program
This commit is contained in:
MysterD 2022-01-22 23:14:00 -08:00
parent 348d1509a1
commit 767809f56a
21 changed files with 1747 additions and 21 deletions

View file

@ -0,0 +1,18 @@
import os
in_filename = os.path.dirname(os.path.realpath(__file__)) + "/lua_constants/constants.lua"
out_filename = os.path.dirname(os.path.realpath(__file__)) + '/../src/pc/lua/smlua_constants_autogen.c'
built = "char gSmluaConstants[] = "
with open(in_filename) as fp:
lines = fp.readlines()
for line in lines:
if line.startswith('--'):
continue
if line.strip() == '':
continue
built += '"' + line.replace('\n', '').replace('\r', '') + '\\n"' + "\n"
built += ';'
with open(out_filename, 'w') as out:
out.write(built)

View file

@ -71,7 +71,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>../;../include/;../src/;C:/msys64/mingw64/include;../lib/lua/include/;$(IncludePath)</IncludePath>
<IncludePath>../;../include/;../src/;C:/msys64/mingw64/include;../lib/lua/include/;C:\msys64\mingw64\x86_64-w64-mingw32\include;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)\..\build\us_pc\</OutDir>
<TargetName>sm64.us.f3dex2e</TargetName>
</PropertyGroup>
@ -510,11 +510,13 @@
<ClCompile Include="..\src\pc\ini.c" />
<ClCompile Include="..\src\pc\lua\smlua.c" />
<ClCompile Include="..\src\pc\lua\smlua_cobject.c" />
<ClCompile Include="..\src\pc\lua\smlua_constants_autogen.c" />
<ClCompile Include="..\src\pc\lua\smlua_functions.c" />
<ClCompile Include="..\src\pc\lua\smlua_functions_autogen.c" />
<ClCompile Include="..\src\pc\lua\smlua_hooks.c" />
<ClCompile Include="..\src\pc\lua\smlua_utils.c" />
<ClCompile Include="..\src\pc\mixer.c" />
<ClCompile Include="..\src\pc\mod_list.c" />
<ClCompile Include="..\src\pc\network\discord\activity.c" />
<ClCompile Include="..\src\pc\network\discord\discord.c" />
<ClCompile Include="..\src\pc\network\discord\lobby.c" />
@ -527,6 +529,7 @@
<ClCompile Include="..\src\pc\network\packets\packet_area_request.c" />
<ClCompile Include="..\src\pc\network\packets\packet_change_area.c" />
<ClCompile Include="..\src\pc\network\packets\packet_debug_sync.c" />
<ClCompile Include="..\src\pc\network\packets\packet_download.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_area_inform.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_request.c" />
@ -544,10 +547,12 @@
<ClCompile Include="..\src\pc\network\packets\packet_leaving.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_macro.c" />
<ClCompile Include="..\src\pc\network\packets\packet_level_respawn_info.c" />
<ClCompile Include="..\src\pc\network\packets\packet_mod_list.c" />
<ClCompile Include="..\src\pc\network\packets\packet_network_players.c" />
<ClCompile Include="..\src\pc\network\packets\packet_object.c" />
<ClCompile Include="..\src\pc\network\packets\packet_ordered.c" />
<ClCompile Include="..\src\pc\network\packets\packet_player.c" />
<ClCompile Include="..\src\pc\network\packets\packet_player_settings.c" />
<ClCompile Include="..\src\pc\network\packets\packet_read_write.c" />
<ClCompile Include="..\src\pc\network\packets\packet_reliable.c" />
<ClCompile Include="..\src\pc\network\packets\packet_reservation_list.c" />
@ -961,6 +966,7 @@
<ClInclude Include="..\src\pc\lua\smlua_functions_autogen.h" />
<ClInclude Include="..\src\pc\lua\smlua_hooks.h" />
<ClInclude Include="..\src\pc\lua\smlua_utils.h" />
<ClInclude Include="..\src\pc\mod_list.h" />
<ClInclude Include="..\src\pc\network\branch.h" />
<ClInclude Include="..\src\pc\network\discord\activity.h" />
<ClInclude Include="..\src\pc\network\discord\discord.h" />
@ -970,6 +976,7 @@
<ClInclude Include="..\src\pc\network\discord\user.h" />
<ClInclude Include="..\src\pc\network\network.h" />
<ClInclude Include="..\src\pc\network\network_player.h" />
<ClInclude Include="..\src\pc\network\packets\packet.h" />
<ClInclude Include="..\src\pc\network\reservation_area.h" />
<ClInclude Include="..\src\pc\network\socket\socket.h" />
<ClInclude Include="..\src\pc\network\socket\socket_linux.h" />

View file

@ -4836,6 +4836,21 @@
<ClCompile Include="..\src\pc\lua\smlua_hooks.c">
<Filter>Source Files\src\pc\lua</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\mod_list.c">
<Filter>Source Files\src\pc</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\lua\smlua_constants_autogen.c">
<Filter>Source Files\src\pc\lua</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\network\packets\packet_mod_list.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\network\packets\packet_player_settings.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
<ClCompile Include="..\src\pc\network\packets\packet_download.c">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\actors\common0.h">
@ -5962,5 +5977,11 @@
<ClInclude Include="..\src\pc\lua\smlua_hooks.h">
<Filter>Source Files\src\pc\lua</Filter>
</ClInclude>
<ClInclude Include="..\src\pc\mod_list.h">
<Filter>Source Files\src\pc</Filter>
</ClInclude>
<ClInclude Include="..\src\pc\network\packets\packet.h">
<Filter>Source Files\src\pc\network\packets</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -0,0 +1,60 @@
gMarioStateExtras = {}
for i=0,(MAX_PLAYERS-1) do
gMarioStateExtras[i] = {}
local m = gMarioStates[i]
local e = gMarioStateExtras[i]
e.actionLastFrame = m.action
end
-----------
-- luigi --
-----------
function luigi_action_on_change(m)
local e = gMarioStateExtras[m.playerIndex]
-- extra height to the backflip
if m.action == ACT_BACKFLIP then
m.vel.y = m.vel.y + 25
end
end
function luigi_update(m)
local e = gMarioStateExtras[m.playerIndex]
-- backflip turns into twirl
if m.action == ACT_BACKFLIP and m.marioObj.header.gfx.animInfo.animFrame > 18 then
m.angleVel.y = 0x1800
set_mario_action(m, ACT_TWIRLING, 1)
end
end
----------
-- main --
----------
function mario_action_on_change(m)
-- if luigi then
luigi_update(m)
-- end
end
function mario_update(m)
local e = gMarioStateExtras[m.playerIndex]
-- if luigi then
luigi_update(m)
-- end
-- action change event
if e.actionLastFrame ~= m.action then
mario_action_on_change(m)
end
e.actionLastFrame = m.action
end
-----------
-- hooks --
-----------
hook_event(HOOK_MARIO_UPDATE, mario_update)

View file

@ -1085,10 +1085,10 @@ function mario_update(m)
after_mario_update(m)
end
function update()
end
-----------
-- hooks --
-----------
hook_event(HOOK_UPDATE, update)
hook_event(HOOK_BEFORE_MARIO_UPDATE, before_mario_update)
hook_event(HOOK_MARIO_UPDATE, mario_update)

View file

@ -1,2 +0,0 @@
print('loaded2!')
print(ANGLE_QUEUE_SIZE)

View file

@ -1,8 +1,9 @@
#include "smlua.h"
#include "pc/mod_list.h"
lua_State* gLuaState = NULL;
static void smlua_execfile(char* path) {
static void smlua_exec_file(char* path) {
lua_State* L = gLuaState;
if (luaL_dofile(L, path) != LUA_OK) {
LOG_LUA("LUA: Failed to load lua file '%s'.", path);
@ -11,6 +12,15 @@ static void smlua_execfile(char* path) {
lua_pop(L, lua_gettop(L));
}
static void smlua_exec_str(char* str) {
lua_State* L = gLuaState;
if (luaL_dostring(L, str) != LUA_OK) {
LOG_LUA("LUA: Failed to load lua string.");
puts(lua_tostring(L, lua_gettop(L)));
}
lua_pop(L, lua_gettop(L));
}
static void smlua_load_script(char* path) {
lua_State* L = gLuaState;
if (luaL_loadfile(L, path) != LUA_OK) {
@ -54,6 +64,7 @@ static void smlua_init_mario_states(void) {
}
void smlua_init(void) {
smlua_shutdown();
gLuaState = luaL_newstate();
lua_State* L = gLuaState;
@ -74,17 +85,30 @@ void smlua_init(void) {
smlua_bind_functions();
smlua_bind_functions_autogen();
smlua_execfile("mods/constants.lua");
extern char gSmluaConstants[];
smlua_exec_str(gSmluaConstants);
smlua_init_mario_states();
smlua_load_script("mods/extended-moveset.lua");
smlua_load_script("mods/test.lua");
// load scripts
LOG_INFO("Loading scripts:");
for (int i = 0; i < sModEntryCount; i++) {
struct ModListEntry* entry = &gModEntries[i];
LOG_INFO(" %s", entry->path);
smlua_load_script(entry->path);
}
}
void smlua_update(void) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
smlua_call_event_hooks(HOOK_UPDATE);
}
void smlua_shutdown(void) {
lua_State* L = gLuaState;
lua_close(L);
if (L != NULL) {
lua_close(L);
gLuaState = NULL;
}
}

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@ struct LuaHookedEvent {
static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 };
int smlua_hook_event(lua_State* L) {
if (L == NULL) { return 0; }
u16 hookType = lua_tointeger(L, -2);
if (hookType >= HOOK_MAX) {
LOG_LUA("LUA: Hook Type: %d exceeds max!", hookType);
@ -29,6 +30,7 @@ int smlua_hook_event(lua_State* L) {
void smlua_call_event_hooks(enum LuaHookedEventType hookType) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
// push the callback onto the stack
@ -44,6 +46,7 @@ void smlua_call_event_hooks(enum LuaHookedEventType hookType) {
void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
// push the callback onto the stack
@ -78,6 +81,7 @@ static struct LuaHookedMarioAction sHookedMarioActions[MAX_HOOKED_ACTIONS] = { 0
static int sHookedMarioActionsCount = 0;
int smlua_hook_mario_action(lua_State* L) {
if (L == NULL) { return 0; }
if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) {
LOG_LUA("LUA: Hooked mario actions exceeded maximum references!");
return 0;
@ -93,6 +97,7 @@ int smlua_hook_mario_action(lua_State* L) {
bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) {
lua_State* L = gLuaState;
if (L == NULL) { return false; }
for (int i = 0; i < sHookedMarioActionsCount; i++) {
if (sHookedMarioActions[i].action == m->action) {
// push the callback onto the stack

130
src/pc/mod_list.c Normal file
View file

@ -0,0 +1,130 @@
#include <dirent.h>
#include <stdlib.h>
#include "mod_list.h"
#include "pc/fs/fs.h"
#include "pc/debuglog.h"
#define MAX_SESSION_CHARS 7
struct ModListEntry* gModEntries = NULL;
u16 sModEntryCount = 0;
static char sTmpSession[MAX_SESSION_CHARS] = { 0 };
static char sTmpPath[PATH_MAX] = { 0 };
static bool acceptable_file(char* string) {
string = strrchr(string, '.');
return (string != NULL && !strcmp(string, ".lua"));
}
void mod_list_alloc(u16 count) {
mod_list_clear();
sModEntryCount = count;
gModEntries = (struct ModListEntry*)calloc(sModEntryCount, sizeof(struct ModListEntry));
}
void mod_list_add(u16 index, char* name, size_t size, bool tmpFile) {
if (!acceptable_file(name)) { return; }
struct ModListEntry* entry = &gModEntries[index];
entry->name = name;
entry->size = size;
if (tmpFile) {
snprintf(entry->path, PATH_MAX - 1, "%s/%s-%s", sTmpPath, sTmpSession, name);
} else {
snprintf(entry->path, PATH_MAX - 1, "%s/%s", MOD_PATH, name);
}
entry->fp = fopen(entry->path, tmpFile ? "wb" : "rb");
if (!tmpFile) {
fseek(entry->fp, 0, SEEK_END);
entry->size = ftell(entry->fp);
fseek(entry->fp, 0, SEEK_SET);
}
entry->complete = !tmpFile;
}
void mod_list_load(void) {
struct dirent* dir;
DIR* d = opendir(MOD_PATH);
if (!d) { closedir(d); return; }
u16 count = 0;
while ((dir = readdir(d)) != NULL) {
if (!acceptable_file(dir->d_name)) { continue; }
count++;
}
mod_list_alloc(count);
rewinddir(d);
u16 index = 0;
LOG_INFO("Loading mods:");
while ((dir = readdir(d)) != NULL) {
if (!acceptable_file(dir->d_name)) { continue; }
LOG_INFO(" %s", dir->d_name);
mod_list_add(index++, strdup(dir->d_name), 0, false);
}
closedir(d);
}
void mod_list_clear(void) {
for (int i = 0; i < sModEntryCount; i++) {
struct ModListEntry* entry = &gModEntries[i];
if (entry->name != NULL) {
free(entry->name);
entry->name = NULL;
}
if (entry->fp != NULL) {
fclose(entry->fp);
entry->fp = NULL;
}
entry->size = 0;
}
if (gModEntries != NULL) {
free(gModEntries);
gModEntries = NULL;
}
sModEntryCount = 0;
}
static void mod_list_delete_tmp(void) {
struct dirent* dir;
DIR* d = opendir(sTmpPath);
if (!d) { closedir(d); return; }
static char path[PATH_MAX] = { 0 };
while ((dir = readdir(d)) != NULL) {
if (!acceptable_file(dir->d_name)) { continue; }
snprintf(path, PATH_MAX - 1, "%s/%s", sTmpPath, dir->d_name);
if (!fs_sys_file_exists(path)) { continue; }
#if defined(_WIN32)
// replace slashes
char* p = path;
while (*p) {
if (*p == '/') { *p = '\\'; }
p++;
}
#endif
if (unlink(path) == -1) {
LOG_ERROR("Failed to remove tmp file '%s'", path);
}
}
closedir(d);
}
void mod_list_init(void) {
snprintf(sTmpSession, MAX_SESSION_CHARS, "%06X", (u32)(rand() % 0xFFFFFF));
snprintf(sTmpPath, PATH_MAX - 1, "%s", fs_get_write_path("tmp"));
if (!fs_sys_dir_exists(sTmpPath)) { fs_sys_mkdir(sTmpPath); }
}
void mod_list_shutdown(void) {
mod_list_clear();
mod_list_delete_tmp();
}

32
src/pc/mod_list.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef MOD_LIST_H
#define MOD_LIST_H
#include <stdio.h>
#include "PR/ultratypes.h"
#include <types.h>
#include <stdbool.h>
#define MOD_PATH "./mods"
struct ModListEntry {
char* name;
FILE* fp;
char path[PATH_MAX];
size_t size;
u64 curOffset;
bool tmp;
bool complete;
};
extern struct ModListEntry* gModEntries;
extern u16 sModEntryCount;
void mod_list_alloc(u16 count);
void mod_list_add(u16 index, char* name, size_t size, bool tmpFile);
void mod_list_load(void);
void mod_list_clear(void);
void mod_list_init(void);
void mod_list_shutdown(void);
#endif

View file

@ -12,6 +12,8 @@
#include "pc/cheats.h"
#include "pc/djui/djui.h"
#include "pc/utils/misc.h"
#include "pc/lua/smlua.h"
#include "pc/mod_list.h"
#include "pc/debuglog.h"
// Mario 64 specific externs
@ -89,6 +91,9 @@ bool network_init(enum NetworkType inNetworkType) {
gNetworkType = inNetworkType;
if (gNetworkType == NT_SERVER) {
mod_list_load();
smlua_init();
network_player_connected(NPT_LOCAL, 0, configPlayerModel, configPlayerPalette, configPlayerName);
extern u8* gOverrideEeprom;
gOverrideEeprom = NULL;
@ -125,17 +130,25 @@ void network_on_loaded_area(void) {
}
}
bool network_allow_unknown_local_index(enum PacketType packetType) {
return (packetType == PACKET_JOIN_REQUEST)
|| (packetType == PACKET_KICK)
|| (packetType == PACKET_ACK)
|| (packetType == PACKET_MOD_LIST_REQUEST)
|| (packetType == PACKET_MOD_LIST)
|| (packetType == PACKET_DOWNLOAD_REQUEST)
|| (packetType == PACKET_DOWNLOAD);
}
void network_send_to(u8 localIndex, struct Packet* p) {
// sanity checks
if (gNetworkType == NT_NONE) { LOG_ERROR("network type error none!"); return; }
if (p->error) { LOG_ERROR("packet error!"); return; }
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
if (localIndex == 0) {
if (p->buffer[0] != PACKET_JOIN_REQUEST && p->buffer[0] != PACKET_KICK && p->buffer[0] != PACKET_ACK) {
LOG_ERROR("\n####################\nsending to myself, packetType: %d\n####################\n", p->packetType);
SOFT_ASSERT(false);
return;
}
if (localIndex == 0 && !network_allow_unknown_local_index(p->buffer[0])) {
LOG_ERROR("\n####################\nsending to myself, packetType: %d\n####################\n", p->packetType);
SOFT_ASSERT(false);
return;
}
if (gNetworkType == NT_SERVER) {

View file

@ -108,6 +108,7 @@ void network_set_system(enum NetworkSystemType nsType);
bool network_init(enum NetworkType inNetworkType);
void network_on_init_area(void);
void network_on_loaded_area(void);
bool network_allow_unknown_local_index(enum PacketType packetType);
void network_send_to(u8 localIndex, struct Packet* p);
void network_send(struct Packet* p);
void network_receive(u8 localIndex, u8* data, u16 dataLength);

View file

@ -76,7 +76,12 @@ void packet_process(struct Packet* p) {
case PACKET_LEVEL_AREA_INFORM: network_receive_level_area_inform(p); break;
case PACKET_LEVEL_RESPAWN_INFO: network_receive_level_respawn_info(p); break;
case PACKET_PLAYER_SETTINGS: network_receive_player_settings(p); break;
case PACKET_PLAYER_SETTINGS: network_receive_player_settings(p); break;
case PACKET_MOD_LIST_REQUEST: network_receive_mod_list_request(p); break;
case PACKET_MOD_LIST: network_receive_mod_list(p); break;
case PACKET_DOWNLOAD_REQUEST: network_receive_download_request(p); break;
case PACKET_DOWNLOAD: network_receive_download(p); break;
// custom
case PACKET_CUSTOM: network_receive_custom(p); break;
@ -91,7 +96,7 @@ void packet_receive(struct Packet* p) {
network_send_ack(p);
// refuse packets from unknown players other than join request
if (gNetworkType == NT_SERVER && p->localIndex == UNKNOWN_LOCAL_INDEX && packetType != PACKET_JOIN_REQUEST && packetType != PACKET_ACK) {
if (gNetworkType == NT_SERVER && p->localIndex == UNKNOWN_LOCAL_INDEX && !network_allow_unknown_local_index(packetType)) {
if (packetType != PACKET_PLAYER) {
LOG_INFO("closing connection for packetType: %d", packetType);
network_send_kick(EKT_CLOSE_CONNECTION);

View file

@ -54,6 +54,11 @@ enum PacketType {
PACKET_PLAYER_SETTINGS,
PACKET_MOD_LIST_REQUEST,
PACKET_MOD_LIST,
PACKET_DOWNLOAD_REQUEST,
PACKET_DOWNLOAD,
///
PACKET_CUSTOM = 255,
};
@ -281,4 +286,17 @@ void network_receive_debug_sync(struct Packet* p);
void network_send_player_settings(void);
void network_receive_player_settings(struct Packet* p);
// packet_mod_list.c
void network_send_mod_list_request(void);
void network_receive_mod_list_request(struct Packet* p);
void network_send_mod_list(void);
void network_receive_mod_list(struct Packet* p);
// packet_download.c
void network_send_download_request(u16 index, u64 offset);
void network_receive_download_request(struct Packet* p);
void network_send_download(u16 index, u64 offset);
void network_receive_download(struct Packet* p);
#endif

View file

@ -0,0 +1,145 @@
#include <stdio.h>
#include "../network.h"
#include "pc/mod_list.h"
#include "pc/debuglog.h"
static void network_send_next_download_request(void) {
SOFT_ASSERT(gNetworkType == NT_CLIENT);
for (int i = 0; i < sModEntryCount; i++) {
struct ModListEntry* entry = &gModEntries[i];
if (entry->complete) { continue; }
network_send_download_request(i, entry->curOffset);
return;
}
network_send_join_request();
}
void network_send_download_request(u16 index, u64 offset) {
SOFT_ASSERT(gNetworkType == NT_CLIENT);
struct Packet p;
packet_init(&p, PACKET_DOWNLOAD_REQUEST, true, PLMT_NONE);
packet_write(&p, &index, sizeof(u16));
packet_write(&p, &offset, sizeof(u64));
network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p);
//LOG_INFO("sending download request packet");
}
void network_receive_download_request(struct Packet* p) {
SOFT_ASSERT(gNetworkType == NT_SERVER);
//LOG_INFO("received download request packet");
u16 index;
u64 offset;
packet_read(p, &index, sizeof(u16));
packet_read(p, &offset, sizeof(u64));
network_send_download(index, offset);
}
void network_send_download(u16 index, u64 offset) {
SOFT_ASSERT(gNetworkType == NT_SERVER);
if (index >= sModEntryCount) {
LOG_ERROR("Requested download of invalid index %u:%llu", index, offset);
return;
}
struct ModListEntry* entry = &gModEntries[index];
if (offset >= entry->size) {
LOG_ERROR("Requested download of invalid offset %u:%llu", index, offset);
return;
}
if (entry->fp == NULL) {
LOG_ERROR("Requested download of invalid file pointer %u:%llu", index, offset);
return;
}
u16 chunkSize = 400;
if ((offset + chunkSize) > entry->size) {
chunkSize = entry->size - offset;
}
u8 chunk[400] = { 0 };
fseek(entry->fp, offset, SEEK_SET);
fread(chunk, chunkSize, 1, entry->fp);
struct Packet p;
packet_init(&p, PACKET_DOWNLOAD, true, PLMT_NONE);
packet_write(&p, &index, sizeof(u16));
packet_write(&p, &offset, sizeof(u64));
packet_write(&p, &chunkSize, sizeof(u16));
packet_write(&p, chunk, chunkSize * sizeof(u8));
network_send_to(0, &p);
//LOG_INFO("sending download packet: %u:%llu", index, offset);
}
void network_receive_download(struct Packet* p) {
SOFT_ASSERT(gNetworkType == NT_CLIENT);
u16 index;
u64 offset;
u16 chunkSize;
u8 chunk[400] = { 0 };
packet_read(p, &index, sizeof(u16));
packet_read(p, &offset, sizeof(u64));
packet_read(p, &chunkSize, sizeof(u16));
packet_read(p, chunk, chunkSize * sizeof(u8));
if (index >= sModEntryCount) {
LOG_ERROR("Received download of invalid index %u:%llu", index, offset);
return;
}
struct ModListEntry* entry = &gModEntries[index];
if (offset >= entry->size) {
LOG_ERROR("Received download of invalid offset %u:%llu", index, offset);
return;
}
if (entry->fp == NULL) {
LOG_ERROR("Received download of invalid file pointer %u:%llu", index, offset);
return;
}
if ((offset + chunkSize) > entry->size) {
LOG_ERROR("Received download of invalid chunk size %u:%llu:%u", index, offset, chunkSize);
return;
}
if (entry->curOffset != offset) {
LOG_ERROR("Received download of unexpected offset %llu != %llu", entry->curOffset, offset);
return;
}
entry->curOffset += chunkSize;
//u64 told = ftell(entry->fp);
//if (offset == 0) {
fseek(entry->fp, offset, SEEK_SET);
//}
fwrite(chunk, sizeof(u8) * chunkSize, 1, entry->fp);
/*u64 told2 = ftell(entry->fp);
printf("#################################################\n");
printf("%llu -> %llu -> %llu - %u\n", told, offset, told2, chunkSize);
printf("%s\n", chunk);
printf("#################################################\n");*/
if ((offset + chunkSize) == entry->size) {
LOG_INFO("Finished download of '%s'", entry->name);
fclose(entry->fp);
entry->fp = NULL;
entry->complete = true;
}
network_send_next_download_request();
}

View file

@ -17,6 +17,7 @@
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
#include "pc/utils/misc.h"
#include "pc/lua/smlua.h"
extern u8* gOverrideEeprom;
static u8 eeprom[512] = { 0 };
@ -215,4 +216,6 @@ void network_receive_join(struct Packet* p) {
fake_lvl_init_from_save_file();
extern s16 gChangeLevel;
gChangeLevel = 16;
smlua_init();
}

View file

@ -0,0 +1,86 @@
#include <stdio.h>
#include "../network.h"
#include "pc/mod_list.h"
#include "pc/debuglog.h"
void network_send_mod_list_request(void) {
SOFT_ASSERT(gNetworkType == NT_CLIENT);
struct Packet p;
packet_init(&p, PACKET_MOD_LIST_REQUEST, true, PLMT_NONE);
char version[MAX_VERSION_LENGTH] = { 0 };
snprintf(version, MAX_VERSION_LENGTH, "%s", get_version());
packet_write(&p, &version, sizeof(u8) * MAX_VERSION_LENGTH);
network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p);
LOG_INFO("sending mod list request");
}
void network_receive_mod_list_request(struct Packet* p) {
SOFT_ASSERT(gNetworkType == NT_SERVER);
LOG_INFO("received mod list request");
char version[MAX_VERSION_LENGTH] = { 0 };
snprintf(version, MAX_VERSION_LENGTH, "%s", get_version());
char remoteVersion[MAX_VERSION_LENGTH] = { 0 };
packet_read(p, &remoteVersion, sizeof(u8) * MAX_VERSION_LENGTH);
LOG_INFO("client has version: %s", remoteVersion);
if (memcmp(version, remoteVersion, MAX_VERSION_LENGTH) != 0) {
LOG_INFO("client version mismatch: %s != %s", remoteVersion, version);
// TODO: send version mismatch packet
return;
}
network_send_mod_list();
}
void network_send_mod_list(void) {
SOFT_ASSERT(gNetworkType == NT_SERVER);
struct Packet p;
packet_init(&p, PACKET_MOD_LIST, true, PLMT_NONE);
packet_write(&p, &sModEntryCount, sizeof(u16));
LOG_INFO("sent mod list (%u):", sModEntryCount);
for (int i = 0; i < sModEntryCount; i++) {
struct ModListEntry* entry = &gModEntries[i];
u16 nameLength = strlen(entry->name);
packet_write(&p, &nameLength, sizeof(u16));
packet_write(&p, entry->name, sizeof(u8) * nameLength);
packet_write(&p, &entry->size, sizeof(u16));
LOG_INFO(" '%s': %u", entry->name, (u16)entry->size);
}
network_send_to(0, &p);
}
void network_receive_mod_list(struct Packet* p) {
SOFT_ASSERT(gNetworkType == NT_CLIENT);
u16 modEntryCount = 0;
packet_read(p, &modEntryCount, sizeof(u16));
mod_list_alloc(modEntryCount);
LOG_INFO("received mod list (%u):", modEntryCount);
for (int i = 0; i < modEntryCount; i++) {
u16 nameLength = 0;
packet_read(p, &nameLength, sizeof(u16));
char* name = (char*)calloc(nameLength + 1, sizeof(u8));
packet_read(p, name, nameLength * sizeof(u8));
u16 size = 0;
packet_read(p, &size, sizeof(u16));
mod_list_add(i, name, size, true);
LOG_INFO(" '%s': %u", name, size);
}
if (modEntryCount <= 0) {
network_send_join_request();
} else {
network_send_download_request(0, 0);
}
}

View file

@ -94,7 +94,7 @@ static bool ns_socket_initialize(enum NetworkType networkType) {
LOG_INFO("initialized");
if (networkType == NT_CLIENT) {
network_send_join_request();
network_send_mod_list_request();
}
// success

View file

@ -49,6 +49,8 @@
#include "pc/network/network_player.h"
#include "pc/djui/djui.h"
#include "pc/mod_list.h"
OSMesg D_80339BEC;
OSMesgQueue gSIEventMesgQueue;
@ -169,6 +171,7 @@ void game_deinit(void) {
gfx_shutdown();
network_shutdown(true);
smlua_shutdown();
mod_list_shutdown();
inited = false;
}
@ -301,10 +304,10 @@ void main_func(void) {
} else {
network_init(NT_NONE);
}
smlua_init();
audio_init();
sound_init();
mod_list_init();
network_player_init();
thread5_game_loop(NULL);