ext loading

git-svn-id: https://svn.eduke32.com/eduke32@7850 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2019-07-31 03:39:30 +00:00 committed by Christoph Oelckers
parent ae36202ac7
commit fdaee03dfb
5 changed files with 277 additions and 30 deletions

View file

@ -2348,14 +2348,27 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin)
{ {
videoFadeToBlack(1); videoFadeToBlack(1);
menusave_t & msv = g_menusaves[M_LOAD.currentEntry]; menusave_t & msv = g_menusaves[M_LOAD.currentEntry];
if (msv.isOldVer) if (msv.isOldVer && msv.brief.isExt)
{ {
Bsprintf(tempbuf, "Resume game from sequence point:\n\"%s\""
#ifndef EDUKE32_ANDROID_MENU
"\n(Y/N)"
#endif
, msv.brief.name);
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
}
else if (msv.isOldVer)
{
#if 1
mgametextcenter(origin.x, origin.y + (90<<16), "You're not supposed to be here.");
#else
Bsprintf(tempbuf, "Start new game:\n%s / %s" Bsprintf(tempbuf, "Start new game:\n%s / %s"
#ifndef EDUKE32_ANDROID_MENU #ifndef EDUKE32_ANDROID_MENU
"\n(Y/N)" "\n(Y/N)"
#endif #endif
, g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]);
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
#endif
} }
else else
{ {
@ -2691,7 +2704,11 @@ static void Menu_LoadReadHeaders()
Menu_ReadSaveGameHeaders(); Menu_ReadSaveGameHeaders();
for (int i = 0; i < g_nummenusaves; ++i) for (int i = 0; i < g_nummenusaves; ++i)
MenuEntry_DisableOnCondition(&ME_LOAD[i], g_menusaves[i].isOldVer); {
menusave_t const & msv = g_menusaves[i];
// MenuEntry_LookDisabledOnCondition(&ME_LOAD[i], msv.isOldVer && msv.brief.isExt);
MenuEntry_DisableOnCondition(&ME_LOAD[i], msv.isOldVer && !msv.brief.isExt);
}
} }
static void Menu_SaveReadHeaders() static void Menu_SaveReadHeaders()
@ -2699,7 +2716,10 @@ static void Menu_SaveReadHeaders()
Menu_ReadSaveGameHeaders(); Menu_ReadSaveGameHeaders();
for (int i = 0; i < g_nummenusaves; ++i) for (int i = 0; i < g_nummenusaves; ++i)
MenuEntry_LookDisabledOnCondition(&ME_SAVE[i], g_menusaves[i].isOldVer); {
menusave_t const & msv = g_menusaves[i];
MenuEntry_LookDisabledOnCondition(&ME_SAVE[i], msv.isOldVer && !msv.brief.isExt);
}
} }
static void Menu_PreInput(MenuEntry_t *entry) static void Menu_PreInput(MenuEntry_t *entry)
@ -3472,7 +3492,8 @@ static void Menu_Verify(int32_t input)
case MENU_LOADVERIFY: case MENU_LOADVERIFY:
if (input) if (input)
{ {
savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief; menusave_t & msv = g_menusaves[M_LOAD.currentEntry];
savebrief_t & sv = msv.brief;
if (strcmp(sv.path, g_lastusersave.path) != 0) if (strcmp(sv.path, g_lastusersave.path) != 0)
{ {
@ -3489,9 +3510,10 @@ static void Menu_Verify(int32_t input)
KB_FlushKeyboardQueue(); KB_FlushKeyboardQueue();
KB_ClearKeysDown(); KB_ClearKeysDown();
Menu_Change(MENU_CLOSE); if (G_LoadPlayerMaybeMulti(sv))
Menu_Change(MENU_PREVIOUS);
G_LoadPlayerMaybeMulti(sv); else
Menu_Change(MENU_CLOSE);
} }
break; break;

View file

@ -5640,7 +5640,7 @@ HORIZONLY:;
#define SJSON_IMPLEMENT #define SJSON_IMPLEMENT
#include "sjson.h" #include "sjson.h"
int portableBackupSave(const char *path) int portableBackupSave(const char * path)
{ {
if (!FURY) if (!FURY)
return 0; return 0;
@ -5652,14 +5652,14 @@ int portableBackupSave(const char *path)
return 1; return 1;
} }
sjson_context* ctx = sjson_create_context(0, 0, NULL); sjson_context * ctx = sjson_create_context(0, 0, NULL);
if (!ctx) if (!ctx)
{ {
buildprint("Could not create sjson_context\n"); buildprint("Could not create sjson_context\n");
return 1; return 1;
} }
sjson_node* root = sjson_mkobject(ctx); sjson_node * root = sjson_mkobject(ctx);
// sjson_put_string(ctx, root, "map", currentboardfilename); // sjson_put_string(ctx, root, "map", currentboardfilename);
sjson_put_int(ctx, root, "volume", ud.last_stateless_volume); sjson_put_int(ctx, root, "volume", ud.last_stateless_volume);
@ -5686,20 +5686,9 @@ int portableBackupSave(const char *path)
for (int w = 0; w < MAX_WEAPONS; ++w) for (int w = 0; w < MAX_WEAPONS; ++w)
sjson_append_element(gotweapon, sjson_mkbool(ctx, !!(ps->gotweapon & (1<<w)))); sjson_append_element(gotweapon, sjson_mkbool(ctx, !!(ps->gotweapon & (1<<w))));
int ammo_amount[MAX_WEAPONS]; sjson_put_int16s(ctx, player, "ammo_amount", ps->ammo_amount, MAX_WEAPONS);
for (int w = 0; w < MAX_WEAPONS; ++w) sjson_put_int16s(ctx, player, "max_ammo_amount", ps->max_ammo_amount, MAX_WEAPONS);
ammo_amount[w] = ps->ammo_amount[w]; sjson_put_int16s(ctx, player, "inv_amount", ps->inv_amount, GET_MAX);
sjson_put_ints(ctx, player, "ammo_amount", ammo_amount, MAX_WEAPONS);
int max_ammo_amount[MAX_WEAPONS];
for (int w = 0; w < MAX_WEAPONS; ++w)
max_ammo_amount[w] = ps->max_ammo_amount[w];
sjson_put_ints(ctx, player, "max_ammo_amount", max_ammo_amount, MAX_WEAPONS);
int inv_amount[GET_MAX];
for (int i = 0; i < GET_MAX; ++i)
inv_amount[i] = ps->inv_amount[i];
sjson_put_ints(ctx, player, "inv_amount", inv_amount, GET_MAX);
sjson_put_int(ctx, player, "max_shield_amount", ps->max_shield_amount); sjson_put_int(ctx, player, "max_shield_amount", ps->max_shield_amount);
@ -5751,7 +5740,7 @@ int portableBackupSave(const char *path)
return 1; return 1;
} }
char* encoded = sjson_stringify(ctx, root, " "); char * encoded = sjson_stringify(ctx, root, " ");
buildvfs_FILE fil = buildvfs_fopen_write(fn); buildvfs_FILE fil = buildvfs_fopen_write(fn);
if (!fil) if (!fil)
@ -5763,6 +5752,7 @@ int portableBackupSave(const char *path)
buildvfs_fwrite(encoded, strlen(encoded), 1, fil); buildvfs_fwrite(encoded, strlen(encoded), 1, fil);
buildvfs_fclose(fil); buildvfs_fclose(fil);
sjson_free_string(ctx, encoded);
sjson_destroy_context(ctx); sjson_destroy_context(ctx);
return 0; return 0;

View file

@ -426,4 +426,6 @@ static inline int P_Get(int32_t spriteNum) { return P_GetP((uspriteptr_t)&sprite
} }
#endif #endif
extern int portableBackupSave(const char *);
#endif #endif

View file

@ -160,11 +160,27 @@ static void ReadSaveGameHeaders_CACHE1D(CACHE1D_FIND_REC *f)
menusave_t & msv = g_internalsaves[g_numinternalsaves]; menusave_t & msv = g_internalsaves[g_numinternalsaves];
msv.brief.isExt = 0;
int32_t k = sv_loadheader(fil, 0, &h); int32_t k = sv_loadheader(fil, 0, &h);
if (k) if (k)
{ {
if (k < 0) if (k < 0)
msv.isUnreadable = 1; msv.isUnreadable = 1;
else
{
if (FURY)
{
char extfn[BMAX_PATH];
snprintf(extfn, ARRAY_SIZE(extfn), "%s.ext", fn);
buildvfs_kfd fil = kopen4loadfrommod(extfn, 0);
if (fil != buildvfs_kfd_invalid)
{
msv.brief.isExt = 1;
kclose(fil);
}
}
}
msv.isOldVer = 1; msv.isOldVer = 1;
} }
else else
@ -330,9 +346,223 @@ static void sv_postudload();
// hack // hack
static int different_user_map; static int different_user_map;
#include "sjson.h"
// XXX: keyboard input 'blocked' after load fail? (at least ESC?) // XXX: keyboard input 'blocked' after load fail? (at least ESC?)
int32_t G_LoadPlayer(savebrief_t & sv) int32_t G_LoadPlayer(savebrief_t & sv)
{ {
if (sv.isExt)
{
char extfn[BMAX_PATH];
snprintf(extfn, ARRAY_SIZE(extfn), "%s.ext", sv.path);
buildvfs_kfd fil = kopen4loadfrommod(extfn, 0);
if (fil == buildvfs_kfd_invalid)
{
return -1;
}
int32_t len = kfilelength(fil);
auto text = (char *)Xmalloc(len+1);
text[len] = '\0';
if (kread_and_test(fil, text, len))
{
kclose(fil);
Xfree(text);
return -1;
}
kclose(fil);
sjson_context * ctx = sjson_create_context(0, 0, NULL);
sjson_node * root = sjson_decode(ctx, text);
Xfree(text);
int volume = sjson_get_int(root, "volume", -1);
int level = sjson_get_int(root, "level", -1);
int skill = sjson_get_int(root, "skill", -1);
if (volume == -1 || level == -1 || skill == -1)
{
sjson_destroy_context(ctx);
return -1;
}
sjson_node * players = sjson_find_member(root, "players");
int numplayers = sjson_child_count(players);
if (numplayers != ud.multimode)
{
P_DoQuote(QUOTE_SAVE_BAD_PLAYERS, g_player[myconnectindex].ps);
sjson_destroy_context(ctx);
return 1;
}
{
// CODEDUP from non-isExt branch, with simplifying assumptions
VM_OnEvent(EVENT_PRELOADGAME, g_player[screenpeek].ps->i, screenpeek);
ud.multimode = numplayers;
Net_WaitForServer();
FX_StopAllSounds();
S_ClearSoundLocks();
ud.m_volume_number = volume;
ud.m_level_number = level;
ud.m_player_skill = skill;
boardfilename[0] = '\0';
int const mapIdx = volume*MAXLEVELS + level;
if (boardfilename[0])
Bstrcpy(currentboardfilename, boardfilename);
else if (g_mapInfo[mapIdx].filename)
Bstrcpy(currentboardfilename, g_mapInfo[mapIdx].filename);
if (currentboardfilename[0])
{
artSetupMapArt(currentboardfilename);
append_ext_UNSAFE(currentboardfilename, ".mhk");
engineLoadMHK(currentboardfilename);
}
currentboardfilename[0] = '\0';
// G_NewGame_EnterLevel();
}
{
// CODEDUP from G_NewGame
auto & p0 = *g_player[0].ps;
ready2send = 0;
ud.from_bonus = 0;
ud.last_level = -1;
ud.level_number = level;
ud.player_skill = skill;
ud.secretlevel = 0;
ud.skill_voice = -1;
ud.volume_number = volume;
g_lastAutoSaveArbitraryID = -1;
#ifdef EDUKE32_TOUCH_DEVICES
p0.zoom = 360;
#else
p0.zoom = 768;
#endif
p0.gm = 0;
Menu_Close(0);
#if !defined LUNATIC
Gv_ResetVars();
Gv_InitWeaponPointers();
Gv_RefreshPointers();
#endif
Gv_ResetSystemDefaults();
for (int i=0; i < (MAXVOLUMES*MAXLEVELS); i++)
G_FreeMapState(i);
if (ud.m_coop != 1)
p0.last_weapon = -1;
display_mirror = 0;
}
int p = 0;
for (sjson_node * player = sjson_first_child(players); player != nullptr; player = player->next)
{
playerdata_t * playerData = &g_player[p];
DukePlayer_t * ps = playerData->ps;
auto pSprite = &sprite[ps->i];
pSprite->extra = sjson_get_int(player, "extra", -1);
ps->max_player_health = sjson_get_int(player, "max_player_health", -1);
sjson_node * gotweapon = sjson_find_member(player, "gotweapon");
int w_end = min<int>(MAX_WEAPONS, sjson_child_count(gotweapon));
ps->gotweapon = 0;
for (int w = 0; w < w_end; ++w)
{
sjson_node * ele = sjson_find_element(gotweapon, w);
if (ele->tag == SJSON_BOOL && ele->bool_)
ps->gotweapon |= 1<<w;
}
/* bool flag_ammo_amount = */ sjson_get_int16s(ps->ammo_amount, MAX_WEAPONS, player, "ammo_amount");
/* bool flag_max_ammo_amount = */ sjson_get_int16s(ps->max_ammo_amount, MAX_WEAPONS, player, "max_ammo_amount");
/* bool flag_inv_amount = */ sjson_get_int16s(ps->inv_amount, GET_MAX, player, "inv_amount");
ps->max_shield_amount = sjson_get_int(player, "max_shield_amount", -1);
ps->curr_weapon = sjson_get_int(player, "curr_weapon", -1);
ps->subweapon = sjson_get_int(player, "subweapon", -1);
ps->inven_icon = sjson_get_int(player, "inven_icon", -1);
sjson_node * vars = sjson_find_member(player, "vars");
for (int j=0; j<g_gameVarCount; j++)
{
gamevar_t & var = aGameVars[j];
if (!(var.flags & GAMEVAR_SERIALIZE))
continue;
if ((var.flags & (GAMEVAR_PERPLAYER|GAMEVAR_PERACTOR)) != GAMEVAR_PERPLAYER)
continue;
Gv_SetVar(j, sjson_get_int(vars, var.szLabel, var.defaultValue), ps->i, p);
}
++p;
}
{
sjson_node * vars = sjson_find_member(root, "vars");
for (int j=0; j<g_gameVarCount; j++)
{
gamevar_t & var = aGameVars[j];
if (!(var.flags & GAMEVAR_SERIALIZE))
continue;
if (var.flags & (GAMEVAR_PERPLAYER|GAMEVAR_PERACTOR))
continue;
Gv_SetVar(j, sjson_get_int(vars, var.szLabel, var.defaultValue));
}
}
sjson_destroy_context(ctx);
if (G_EnterLevel(MODE_GAME|MODE_EOL))
G_BackToMenu();
// postloadplayer(1);
// sv_postudload();
VM_OnEvent(EVENT_LOADGAME, g_player[screenpeek].ps->i, screenpeek);
return 0;
}
buildvfs_kfd const fil = kopen4loadfrommod(sv.path, 0); buildvfs_kfd const fil = kopen4loadfrommod(sv.path, 0);
if (fil == buildvfs_kfd_invalid) if (fil == buildvfs_kfd_invalid)
@ -540,6 +770,8 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave)
goto saveproblem; goto saveproblem;
} }
sv.isExt = 0;
// temporary hack // temporary hack
ud.user_map = G_HaveUserMap(); ud.user_map = G_HaveUserMap();
@ -550,7 +782,6 @@ int32_t G_SavePlayer(savebrief_t & sv, bool isAutoSave)
VM_OnEvent(EVENT_SAVEGAME, g_player[screenpeek].ps->i, screenpeek); VM_OnEvent(EVENT_SAVEGAME, g_player[screenpeek].ps->i, screenpeek);
extern int portableBackupSave(const char *);
portableBackupSave(sv.path); portableBackupSave(sv.path);
// SAVE! // SAVE!

View file

@ -83,11 +83,13 @@ struct savebrief_t
char name[MAXSAVEGAMENAMESTRUCT]; char name[MAXSAVEGAMENAMESTRUCT];
char path[BMAX_PATH]; char path[BMAX_PATH];
uint8_t isExt = 0;
void reset() void reset()
{ {
name[0] = '\0'; name[0] = '\0';
path[0] = '\0'; path[0] = '\0';
isExt = 0;
} }
bool isValid() const bool isValid() const
{ {
@ -103,10 +105,10 @@ struct menusave_t
uint8_t isAutoSave = 0; uint8_t isAutoSave = 0;
void clear() void clear()
{ {
brief.reset(); brief.reset();
isOldVer = 0; isOldVer = 0;
isUnreadable = 0; isUnreadable = 0;
isAutoSave = 0; isAutoSave = 0;
} }
}; };