Save states are now saved to the Gaseous host, making them available anywhere (#255)
* Added ability to save emulator state * Save states can now be fully managed during a game * Save states can also be launched from the game info screen
This commit is contained in:
@@ -58,7 +58,7 @@ namespace gaseous_server.Classes
|
|||||||
public static GameRomMediaGroupItem GetMediaGroup(long Id)
|
public static GameRomMediaGroupItem GetMediaGroup(long Id)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "SELECT * FROM RomMediaGroup WHERE Id=@id;";
|
string sql = "SELECT DISTINCT RomMediaGroup.*, GameState.RomId AS GameStateRomId FROM gaseous.RomMediaGroup LEFT JOIN GameState ON RomMediaGroup.Id = GameState.RomId AND GameState.IsMediaGroup = 1 WHERE RomMediaGroup.Id=@id;";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", Id);
|
dbDict.Add("id", Id);
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ namespace gaseous_server.Classes
|
|||||||
public static List<GameRomMediaGroupItem> GetMediaGroupsFromGameId(long GameId)
|
public static List<GameRomMediaGroupItem> GetMediaGroupsFromGameId(long GameId)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "SELECT * FROM RomMediaGroup WHERE GameId=@gameid;";
|
string sql = "SELECT DISTINCT RomMediaGroup.*, GameState.RomId AS GameStateRomId FROM gaseous.RomMediaGroup LEFT JOIN GameState ON RomMediaGroup.Id = GameState.RomId AND GameState.IsMediaGroup = 1 WHERE RomMediaGroup.GameId=@gameid;";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("gameid", GameId);
|
dbDict.Add("gameid", GameId);
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ namespace gaseous_server.Classes
|
|||||||
public static void DeleteMediaGroup(long Id)
|
public static void DeleteMediaGroup(long Id)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "DELETE FROM RomMediaGroup WHERE Id=@id;";
|
string sql = "DELETE FROM RomMediaGroup WHERE Id=@id; DELETE FROM GameState WHERE RomId=@id AND IsMediaGroup=1;";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", Id);
|
dbDict.Add("id", Id);
|
||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
@@ -170,6 +170,15 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
internal static GameRomMediaGroupItem BuildMediaGroupFromRow(DataRow row)
|
internal static GameRomMediaGroupItem BuildMediaGroupFromRow(DataRow row)
|
||||||
{
|
{
|
||||||
|
bool hasSaveStates = false;
|
||||||
|
if (row.Table.Columns.Contains("GameStateRomId"))
|
||||||
|
{
|
||||||
|
if (row["GameStateRomId"] != DBNull.Value)
|
||||||
|
{
|
||||||
|
hasSaveStates = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameRomMediaGroupItem mediaGroupItem = new GameRomMediaGroupItem();
|
GameRomMediaGroupItem mediaGroupItem = new GameRomMediaGroupItem();
|
||||||
mediaGroupItem.Id = (long)row["Id"];
|
mediaGroupItem.Id = (long)row["Id"];
|
||||||
mediaGroupItem.Status = (GameRomMediaGroupItem.GroupBuildStatus)row["Status"];
|
mediaGroupItem.Status = (GameRomMediaGroupItem.GroupBuildStatus)row["Status"];
|
||||||
@@ -177,6 +186,7 @@ namespace gaseous_server.Classes
|
|||||||
mediaGroupItem.GameId = (long)row["GameId"];
|
mediaGroupItem.GameId = (long)row["GameId"];
|
||||||
mediaGroupItem.RomIds = new List<long>();
|
mediaGroupItem.RomIds = new List<long>();
|
||||||
mediaGroupItem.Roms = new List<Roms.GameRomItem>();
|
mediaGroupItem.Roms = new List<Roms.GameRomItem>();
|
||||||
|
mediaGroupItem.HasSaveStates = hasSaveStates;
|
||||||
|
|
||||||
// get members
|
// get members
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
@@ -397,6 +407,7 @@ namespace gaseous_server.Classes
|
|||||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||||
public List<long> RomIds { get; set; }
|
public List<long> RomIds { get; set; }
|
||||||
public List<Roms.GameRomItem> Roms { get; set; }
|
public List<Roms.GameRomItem> Roms { get; set; }
|
||||||
|
public bool HasSaveStates { get; set; } = false;
|
||||||
private GroupBuildStatus _Status { get; set; }
|
private GroupBuildStatus _Status { get; set; }
|
||||||
public GroupBuildStatus Status {
|
public GroupBuildStatus Status {
|
||||||
get
|
get
|
||||||
|
@@ -15,7 +15,7 @@ namespace gaseous_server.Classes
|
|||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0)
|
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0, string userid = "")
|
||||||
{
|
{
|
||||||
GameRomObject GameRoms = new GameRomObject();
|
GameRomObject GameRoms = new GameRomObject();
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ namespace gaseous_server.Classes
|
|||||||
string sqlPlatform = "";
|
string sqlPlatform = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", GameId);
|
dbDict.Add("id", GameId);
|
||||||
|
dbDict.Add("userid", userid);
|
||||||
|
|
||||||
string NameSearchWhere = "";
|
string NameSearchWhere = "";
|
||||||
if (NameSearch.Length > 0)
|
if (NameSearch.Length > 0)
|
||||||
@@ -38,13 +39,13 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
if (PlatformId == -1) {
|
if (PlatformId == -1) {
|
||||||
// data query
|
// data query
|
||||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||||
|
|
||||||
// count query
|
// count query
|
||||||
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id" + NameSearchWhere + ";";
|
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id" + NameSearchWhere + ";";
|
||||||
} else {
|
} else {
|
||||||
// data query
|
// data query
|
||||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||||
|
|
||||||
// count query
|
// count query
|
||||||
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + ";";
|
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + ";";
|
||||||
@@ -131,7 +132,7 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "DELETE FROM Games_Roms WHERE Id = @id";
|
string sql = "DELETE FROM Games_Roms WHERE Id = @id; DELETE FROM GameState WHERE RomId = @id;";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", RomId);
|
dbDict.Add("id", RomId);
|
||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
@@ -140,6 +141,15 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
private static GameRomItem BuildRom(DataRow romDR)
|
private static GameRomItem BuildRom(DataRow romDR)
|
||||||
{
|
{
|
||||||
|
bool hasSaveStates = false;
|
||||||
|
if (romDR.Table.Columns.Contains("SavedStateRomId"))
|
||||||
|
{
|
||||||
|
if (romDR["SavedStateRomId"] != DBNull.Value)
|
||||||
|
{
|
||||||
|
hasSaveStates = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameRomItem romItem = new GameRomItem
|
GameRomItem romItem = new GameRomItem
|
||||||
{
|
{
|
||||||
Id = (long)romDR["id"],
|
Id = (long)romDR["id"],
|
||||||
@@ -159,6 +169,7 @@ namespace gaseous_server.Classes
|
|||||||
Path = (string)romDR["path"],
|
Path = (string)romDR["path"],
|
||||||
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)romDR["metadatasource"],
|
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
||||||
|
HasSaveStates = hasSaveStates,
|
||||||
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -191,6 +202,7 @@ namespace gaseous_server.Classes
|
|||||||
public long GameId { get; set; }
|
public long GameId { get; set; }
|
||||||
public string? Path { get; set; }
|
public string? Path { get; set; }
|
||||||
public string? SignatureSourceGameTitle { get; set;}
|
public string? SignatureSourceGameTitle { get; set;}
|
||||||
|
public bool HasSaveStates { get; set; } = false;
|
||||||
public GameLibrary.LibraryItem Library { get; set; }
|
public GameLibrary.LibraryItem Library { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,12 +6,14 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Authentication;
|
||||||
using gaseous_server.Classes;
|
using gaseous_server.Classes;
|
||||||
using gaseous_server.Classes.Metadata;
|
using gaseous_server.Classes.Metadata;
|
||||||
using gaseous_server.Models;
|
using gaseous_server.Models;
|
||||||
using IGDB.Models;
|
using IGDB.Models;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.CodeAnalysis.Scripting;
|
using Microsoft.CodeAnalysis.Scripting;
|
||||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||||
@@ -25,6 +27,18 @@ namespace gaseous_server.Controllers
|
|||||||
[ApiController]
|
[ApiController]
|
||||||
public class GamesController : Controller
|
public class GamesController : Controller
|
||||||
{
|
{
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
|
public GamesController(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
SignInManager<ApplicationUser> signInManager
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_signInManager = signInManager;
|
||||||
|
}
|
||||||
|
|
||||||
[MapToApiVersion("1.0")]
|
[MapToApiVersion("1.0")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||||
@@ -830,13 +844,15 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1, string NameSearch = "")
|
public async Task<ActionResult> GameRomAsync(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1, string NameSearch = "")
|
||||||
{
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
|
|
||||||
return Ok(Classes.Roms.GetRoms(GameId, PlatformId, NameSearch, pageNumber, pageSize));
|
return Ok(Classes.Roms.GetRoms(GameId, PlatformId, NameSearch, pageNumber, pageSize, user.Id));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@@ -444,8 +444,6 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder;
|
string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder;
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
//string sql = "SELECT DISTINCT view_Games.* FROM view_Games LEFT JOIN Relation_Game_Platforms ON view_Games.Id = Relation_Game_Platforms.GameId AND (Relation_Game_Platforms.PlatformsId IN (SELECT DISTINCT PlatformId FROM Games_Roms WHERE Games_Roms.GameId = view_Games.Id)) LEFT JOIN Relation_Game_Genres ON view_Games.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON view_Games.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON view_Games.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON view_Games.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
|
||||||
|
|
||||||
string sql = "SELECT DISTINCT Game.Id, Game.`Name`, Game.NameThe, Game.PlatformId, Game.TotalRating, Game.TotalRatingCount, Game.Cover, Game.Artworks, Game.FirstReleaseDate, Game.Category, Game.ParentGame, Game.AgeRatings, Game.AgeGroupId, Game.RomCount FROM (SELECT DISTINCT Game.*, CASE WHEN Game.`Name` LIKE 'The %' THEN CONCAT(TRIM(SUBSTR(Game.`Name` FROM 4)), ', The') ELSE Game.`Name` END AS NameThe, Games_Roms.PlatformId, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId" + platformWhereClause + " LEFT JOIN AlternativeName ON Game.Id = AlternativeName.Game " + nameWhereClause + " GROUP BY Game.Id HAVING RomCount > 0) Game LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
string sql = "SELECT DISTINCT Game.Id, Game.`Name`, Game.NameThe, Game.PlatformId, Game.TotalRating, Game.TotalRatingCount, Game.Cover, Game.Artworks, Game.FirstReleaseDate, Game.Category, Game.ParentGame, Game.AgeRatings, Game.AgeGroupId, Game.RomCount FROM (SELECT DISTINCT Game.*, CASE WHEN Game.`Name` LIKE 'The %' THEN CONCAT(TRIM(SUBSTR(Game.`Name` FROM 4)), ', The') ELSE Game.`Name` END AS NameThe, Games_Roms.PlatformId, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId" + platformWhereClause + " LEFT JOIN AlternativeName ON Game.Id = AlternativeName.Game " + nameWhereClause + " GROUP BY Game.Id HAVING RomCount > 0) Game LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||||
|
|
||||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||||
|
279
gaseous-server/Controllers/V1.1/StateManagerController.cs
Normal file
279
gaseous-server/Controllers/V1.1/StateManagerController.cs
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using gaseous_server.Models;
|
||||||
|
using gaseous_server.Classes;
|
||||||
|
using Authentication;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using System.Data;
|
||||||
|
|
||||||
|
namespace gaseous_server.Controllers.v1_1
|
||||||
|
{
|
||||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
[ApiVersion("1.0")]
|
||||||
|
[ApiVersion("1.1")]
|
||||||
|
[ApiController]
|
||||||
|
public class StateManagerController: ControllerBase
|
||||||
|
{
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
|
public StateManagerController(
|
||||||
|
UserManager<ApplicationUser> userManager,
|
||||||
|
SignInManager<ApplicationUser> signInManager
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_signInManager = signInManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(typeof(Models.GameStateItem), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}")]
|
||||||
|
public async Task<ActionResult> SaveStateAsync(long RomId, UploadStateModel uploadState, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state); SELECT LAST_INSERT_ID();";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "ismediagroup", IsMediaGroup },
|
||||||
|
{ "statedatetime", DateTime.UtcNow },
|
||||||
|
{ "name", "" },
|
||||||
|
{ "screenshot", uploadState.ScreenshotByteArray },
|
||||||
|
{ "state", uploadState.StateByteArray }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
return Ok(await GetStateAsync(RomId, (long)(ulong)data.Rows[0][0], IsMediaGroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(typeof(List<Models.GameStateItem>), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}")]
|
||||||
|
public async Task<ActionResult> GetAllStateAsync(long RomId, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Id, StateDateTime, `Name`, Screenshot FROM GameState WHERE RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid ORDER BY StateDateTime DESC;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
List<Models.GameStateItem> gameStates = new List<GameStateItem>();
|
||||||
|
foreach (DataRow row in data.Rows)
|
||||||
|
{
|
||||||
|
gameStates.Add(BuildGameStateItem(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(gameStates);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(typeof(Models.GameStateItem), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}/{StateId}")]
|
||||||
|
public async Task<ActionResult> GetStateAsync(long RomId, long StateId, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Id, StateDateTime, `Name`, Screenshot FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "id", StateId },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// invalid match - return not found
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameStateItem stateItem = BuildGameStateItem(data.Rows[0]);
|
||||||
|
|
||||||
|
return Ok(stateItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpDelete]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}/{StateId}")]
|
||||||
|
public async Task<ActionResult> DeleteStateAsync(long RomId, long StateId, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "DELETE FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "id", StateId },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup }
|
||||||
|
};
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpPut]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}/{StateId}")]
|
||||||
|
public async Task<ActionResult> EditStateAsync(long RomId, long StateId, GameStateItemUpdateModel model, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "UPDATE GameState SET `Name` = @name WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "id", StateId },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup },
|
||||||
|
{ "name", model.Name }
|
||||||
|
};
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}/{StateId}/Screenshot/")]
|
||||||
|
[Route("{RomId}/{StateId}/Screenshot/image.png")]
|
||||||
|
public async Task<ActionResult> GetStateScreenshotAsync(long RomId, long StateId, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Screenshot FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "id", StateId },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// invalid match - return not found
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filename = "image.jpg";
|
||||||
|
byte[] bytes = (byte[])data.Rows[0][0];
|
||||||
|
string contentType = "image/png";
|
||||||
|
|
||||||
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
|
{
|
||||||
|
FileName = filename,
|
||||||
|
Inline = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||||
|
|
||||||
|
return File(bytes, contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[Route("{RomId}/{StateId}/State/")]
|
||||||
|
[Route("{RomId}/{StateId}/State/savestate.state")]
|
||||||
|
public async Task<ActionResult> GetStateDataAsync(long RomId, long StateId, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT State FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "id", StateId },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// invalid match - return not found
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string filename = "savestate.state";
|
||||||
|
byte[] bytes = (byte[])data.Rows[0][0];
|
||||||
|
string contentType = "application/octet-stream";
|
||||||
|
|
||||||
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
|
{
|
||||||
|
FileName = filename,
|
||||||
|
Inline = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||||
|
|
||||||
|
return File(bytes, contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Models.GameStateItem BuildGameStateItem(DataRow dr)
|
||||||
|
{
|
||||||
|
bool HasScreenshot = true;
|
||||||
|
if (dr["Screenshot"] == DBNull.Value)
|
||||||
|
{
|
||||||
|
HasScreenshot = false;
|
||||||
|
}
|
||||||
|
GameStateItem stateItem = new GameStateItem
|
||||||
|
{
|
||||||
|
Id = (long)dr["Id"],
|
||||||
|
Name = (string)dr["Name"],
|
||||||
|
SaveTime = DateTime.Parse(((DateTime)dr["StateDateTime"]).ToString("yyyy-MM-ddThh:mm:ss") + 'Z'),
|
||||||
|
HasScreenshot = HasScreenshot
|
||||||
|
};
|
||||||
|
|
||||||
|
return stateItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
gaseous-server/Models/GameState.cs
Normal file
35
gaseous-server/Models/GameState.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
namespace gaseous_server.Models
|
||||||
|
{
|
||||||
|
public class UploadStateModel
|
||||||
|
{
|
||||||
|
public string ScreenshotByteArrayBase64 { get; set; }
|
||||||
|
public string StateByteArrayBase64 { get; set; }
|
||||||
|
public byte[] ScreenshotByteArray
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Convert.FromBase64String(ScreenshotByteArrayBase64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public byte[] StateByteArray
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Convert.FromBase64String(StateByteArrayBase64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GameStateItem
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public DateTime SaveTime { get; set; }
|
||||||
|
public bool HasScreenshot { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GameStateItemUpdateModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
11
gaseous-server/Support/Database/MySQL/gaseous-1015.sql
Normal file
11
gaseous-server/Support/Database/MySQL/gaseous-1015.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE `GameState` (
|
||||||
|
`Id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`UserId` VARCHAR(45) NULL,
|
||||||
|
`RomId` BIGINT NULL,
|
||||||
|
`IsMediaGroup` INT NULL,
|
||||||
|
`StateDateTime` DATETIME NULL,
|
||||||
|
`Name` VARCHAR(100) NULL,
|
||||||
|
`Screenshot` LONGBLOB NULL,
|
||||||
|
`State` LONGBLOB NULL,
|
||||||
|
PRIMARY KEY (`Id`),
|
||||||
|
INDEX `idx_UserId` (`UserId` ASC) VISIBLE);
|
@@ -59,6 +59,7 @@
|
|||||||
<None Remove="Support\Database\MySQL\gaseous-1012.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1012.sql" />
|
||||||
<None Remove="Support\Database\MySQL\gaseous-1013.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1013.sql" />
|
||||||
<None Remove="Support\Database\MySQL\gaseous-1014.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1014.sql" />
|
||||||
|
<None Remove="Support\Database\MySQL\gaseous-1015.sql" />
|
||||||
<None Remove="Classes\Metadata\" />
|
<None Remove="Classes\Metadata\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -95,5 +96,6 @@
|
|||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1012.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1012.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1013.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1013.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1014.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1014.sql" />
|
||||||
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1015.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
BIN
gaseous-server/wwwroot/images/SaveStates.png
Normal file
BIN
gaseous-server/wwwroot/images/SaveStates.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@@ -4,6 +4,7 @@
|
|||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<script src="/api/v1.1/System/VersionFile"></script>
|
<script src="/api/v1.1/System/VersionFile"></script>
|
||||||
<link type="text/css" rel="stylesheet" href="/styles/style.css" dat-href="/styles/style.css" />
|
<link type="text/css" rel="stylesheet" href="/styles/style.css" dat-href="/styles/style.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/styles/notifications.css" dat-href="/styles/notifications.css" />
|
||||||
<script src="/scripts/jquery-3.6.0.min.js"></script>
|
<script src="/scripts/jquery-3.6.0.min.js"></script>
|
||||||
<script src="/scripts/moment-with-locales.min.js"></script>
|
<script src="/scripts/moment-with-locales.min.js"></script>
|
||||||
<link href="/styles/select2.min.css" rel="stylesheet" />
|
<link href="/styles/select2.min.css" rel="stylesheet" />
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
<script src="/scripts/dropzone.min.js"></script>
|
<script src="/scripts/dropzone.min.js"></script>
|
||||||
<script src="/scripts/simpleUpload.min.js"></script>
|
<script src="/scripts/simpleUpload.min.js"></script>
|
||||||
<script src="/scripts/main.js" type="text/javascript"></script>
|
<script src="/scripts/main.js" type="text/javascript"></script>
|
||||||
|
<script src="/scripts/notifications.js" type="text/javascript"></script>
|
||||||
<script src="/scripts/filterformating.js" type="text/javascript"></script>
|
<script src="/scripts/filterformating.js" type="text/javascript"></script>
|
||||||
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
|
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||||
@@ -43,6 +45,9 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Notifications -->
|
||||||
|
<div id="notifications_target"></div>
|
||||||
|
|
||||||
<div id="banner_icon" onclick="window.location.href = '/index.html';">
|
<div id="banner_icon" onclick="window.location.href = '/index.html';">
|
||||||
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -18,18 +18,56 @@
|
|||||||
// URL to Game rom
|
// URL to Game rom
|
||||||
EJS_gameUrl = decodeURIComponent(getQueryString('rompath', 'string'));
|
EJS_gameUrl = decodeURIComponent(getQueryString('rompath', 'string'));
|
||||||
|
|
||||||
|
// load state if defined
|
||||||
|
if (StateUrl) {
|
||||||
|
console.log('Loading saved state from: ' + StateUrl);
|
||||||
|
EJS_loadStateURL = StateUrl;
|
||||||
|
EJS_startOnLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Path to the data directory
|
// Path to the data directory
|
||||||
EJS_pathtodata = '/emulators/EmulatorJS/data/';
|
EJS_pathtodata = '/emulators/EmulatorJS/data/';
|
||||||
|
|
||||||
EJS_DEBUG_XX = false;
|
EJS_DEBUG_XX = false;
|
||||||
|
|
||||||
EJS_startOnLoaded = false;
|
|
||||||
|
|
||||||
EJS_backgroundImage = emuBackground;
|
EJS_backgroundImage = emuBackground;
|
||||||
EJS_backgroundBlur = true;
|
EJS_backgroundBlur = true;
|
||||||
|
|
||||||
|
EJS_fullscreenOnLoaded = false;
|
||||||
|
|
||||||
EJS_gameName = emuGameTitle;
|
EJS_gameName = emuGameTitle;
|
||||||
|
|
||||||
EJS_threads = false;
|
EJS_threads = false;
|
||||||
|
|
||||||
|
EJS_onSaveState = function(e) {
|
||||||
|
var returnValue = {
|
||||||
|
"ScreenshotByteArrayBase64": btoa(Uint8ToString(e.screenshot)),
|
||||||
|
"StateByteArrayBase64": btoa(Uint8ToString(e.state))
|
||||||
|
};
|
||||||
|
|
||||||
|
var url = '/api/v1.1/StateManager/' + romId + '?IsMediaGroup=' + IsMediaGroup;
|
||||||
|
|
||||||
|
ajaxCall(
|
||||||
|
url,
|
||||||
|
'POST',
|
||||||
|
function (result) {
|
||||||
|
console.log("Upload complete");
|
||||||
|
console.log(result);
|
||||||
|
|
||||||
|
displayNotification('State Saved', 'Game state has been saved.', '/api/v1.1/StateManager/' + romId + '/' + result.value.id + '/Screenshot/image.png?IsMediaGroup=' + IsMediaGroup);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
console.log("An error occurred");
|
||||||
|
console.log(error);
|
||||||
|
},
|
||||||
|
JSON.stringify(returnValue)
|
||||||
|
);
|
||||||
|
|
||||||
|
returnValue = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
EJS_onLoadState = function(e) {
|
||||||
|
showDialog('emulatorloadstate', { "romId": romId, "IsMediaGroup": IsMediaGroup });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
159
gaseous-server/wwwroot/pages/dialogs/emulatorloadstate.html
Normal file
159
gaseous-server/wwwroot/pages/dialogs/emulatorloadstate.html
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<div id="saved_states">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script text="text/javascript">
|
||||||
|
document.getElementById('modal-heading').innerHTML = "Load saved state";
|
||||||
|
|
||||||
|
console.log(modalVariables);
|
||||||
|
|
||||||
|
var statesUrl = '/api/v1.1/StateManager/' + modalVariables.romId + '?IsMediaGroup=' + modalVariables.IsMediaGroup;
|
||||||
|
console.log(statesUrl);
|
||||||
|
function LoadStates() {
|
||||||
|
ajaxCall(
|
||||||
|
statesUrl,
|
||||||
|
'GET',
|
||||||
|
function(result) {
|
||||||
|
var statesBox = document.getElementById('saved_states');
|
||||||
|
statesBox.innerHTML = '';
|
||||||
|
|
||||||
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
var stateBox = document.createElement('div');
|
||||||
|
stateBox.id = 'stateBox_' + result[i].id;
|
||||||
|
stateBox.className = 'saved_state_box';
|
||||||
|
|
||||||
|
// screenshot panel
|
||||||
|
var stateImageBox = document.createElement('div');
|
||||||
|
stateImageBox.id = 'stateImageBox_' + result[i].id;
|
||||||
|
stateImageBox.className = 'saved_state_image_box';
|
||||||
|
|
||||||
|
if (result[i].hasScreenshot == true) {
|
||||||
|
var stateImage = document.createElement('img');
|
||||||
|
stateImage.className = 'saved_state_image_image';
|
||||||
|
stateImage.src = '/api/v1.1/StateManager/' + modalVariables.romId + '/' + result[i].id + '/Screenshot/image.png?IsMediaGroup=' + modalVariables.IsMediaGroup;
|
||||||
|
stateImageBox.appendChild(stateImage);
|
||||||
|
}
|
||||||
|
stateBox.appendChild(stateImageBox);
|
||||||
|
|
||||||
|
// main panel
|
||||||
|
var stateMainPanel = document.createElement('div');
|
||||||
|
stateMainPanel.id = 'stateMainPanel_' + result[i].id;
|
||||||
|
stateMainPanel.className = 'saved_state_main_box';
|
||||||
|
|
||||||
|
var stateName = document.createElement('input');
|
||||||
|
stateName.id = 'stateName_' + result[i].id;
|
||||||
|
stateName.type = 'text';
|
||||||
|
stateName.className = 'saved_state_name';
|
||||||
|
stateName.setAttribute('onblur', 'UpdateStateSave(' + result[i].id + ', ' + modalVariables.IsMediaGroup + ');');
|
||||||
|
if (result[i].name) {
|
||||||
|
stateName.value = result[i].name;
|
||||||
|
} else {
|
||||||
|
stateName.setAttribute('placeholder', "Untitled");
|
||||||
|
}
|
||||||
|
stateMainPanel.appendChild(stateName);
|
||||||
|
|
||||||
|
var stateTime = document.createElement('div');
|
||||||
|
stateTime.id = 'stateTime_' + result[i].id;
|
||||||
|
stateTime.className = 'saved_state_date';
|
||||||
|
stateTime.innerHTML = moment(result[i].saveTime).format("YYYY-MM-DD h:mm:ss a");
|
||||||
|
stateMainPanel.appendChild(stateTime);
|
||||||
|
|
||||||
|
var stateControls = document.createElement('div');
|
||||||
|
stateControls.id = 'stateControls_' + result[i].id;
|
||||||
|
stateControls.className = 'saved_state_controls';
|
||||||
|
|
||||||
|
var stateControlsLaunch= document.createElement('span');
|
||||||
|
stateControlsLaunch.id = 'stateControlsLaunch_' + result[i].id;
|
||||||
|
stateControlsLaunch.className = 'romstart';
|
||||||
|
var emulatorTarget = '/index.html?page=emulator&engine=@engine&core=@core&platformid=@platformid&gameid=@gameid&romid=@romid&mediagroup=@mediagroup&rompath=@rompath&stateid=' + result[i].id;
|
||||||
|
switch (getQueryString('page', 'string')) {
|
||||||
|
case 'emulator':
|
||||||
|
var mediagroupint = 0;
|
||||||
|
if (modalVariables.IsMediaGroup == true) {
|
||||||
|
mediagroupint = 1;
|
||||||
|
}
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@engine', getQueryString('engine', 'string'));
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@core', getQueryString('core', 'string'));
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@platformid', getQueryString('platformid', 'string'));
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@gameid', getQueryString('gameid', 'string'));
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@romid', getQueryString('romid', 'string'));
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@mediagroup', mediagroupint);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@rompath', getQueryString('rompath', 'string'));
|
||||||
|
stateControlsLaunch.setAttribute("onclick", 'window.location.replace("' + emulatorTarget + '")');
|
||||||
|
break;
|
||||||
|
case 'game':
|
||||||
|
console.log(modalVariables);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@engine', modalVariables.engine);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@core', modalVariables.core);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@platformid', modalVariables.platformid);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@gameid', modalVariables.gameid);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@romid', modalVariables.romId);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@mediagroup', modalVariables.mediagroup);
|
||||||
|
emulatorTarget = emulatorTarget.replaceAll('@rompath', modalVariables.rompath);
|
||||||
|
stateControlsLaunch.setAttribute("onclick", 'window.location.href = "' + emulatorTarget + '"');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stateControlsLaunch.innerHTML = 'Launch';
|
||||||
|
stateControlsLaunch.style.float = 'right';
|
||||||
|
stateControls.appendChild(stateControlsLaunch);
|
||||||
|
|
||||||
|
var stateControlsDownload = document.createElement('a');
|
||||||
|
stateControlsDownload.id = 'stateControlsDownload_' + result[i].id;
|
||||||
|
stateControlsDownload.className = 'saved_state_buttonlink';
|
||||||
|
stateControlsDownload.href = '/api/v1.1/StateManager/' + modalVariables.romId + '/' + result[i].id + '/State/savestate.state?IsMediaGroup=' + modalVariables.IsMediaGroup;
|
||||||
|
stateControlsDownload.innerHTML = '<img src="/images/Download.svg" class="banner_button_image" alt="Download" title="Download" />';
|
||||||
|
stateControls.appendChild(stateControlsDownload);
|
||||||
|
|
||||||
|
var stateControlsDelete = document.createElement('span');
|
||||||
|
stateControlsDelete.id = 'stateControlsDelete_' + result[i].id;
|
||||||
|
stateControlsDelete.className = 'saved_state_buttonlink';
|
||||||
|
stateControlsDelete.setAttribute('onclick', 'DeleteStateSave(' + result[i].id + ', ' + modalVariables.IsMediaGroup + ');');
|
||||||
|
stateControlsDelete.innerHTML = '<img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" />';
|
||||||
|
stateControls.appendChild(stateControlsDelete);
|
||||||
|
|
||||||
|
stateMainPanel.appendChild(stateControls);
|
||||||
|
|
||||||
|
stateBox.appendChild(stateMainPanel);
|
||||||
|
|
||||||
|
statesBox.appendChild(stateBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadStates();
|
||||||
|
|
||||||
|
function DeleteStateSave(StateId, IsMediaGroup) {
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
||||||
|
'DELETE',
|
||||||
|
function(success) {
|
||||||
|
LoadStates();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
LoadStates();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function UpdateStateSave(StateId, IsMediaGroup) {
|
||||||
|
var stateName = document.getElementById('stateName_' + StateId);
|
||||||
|
|
||||||
|
var model = {
|
||||||
|
"name": stateName.value
|
||||||
|
};
|
||||||
|
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
||||||
|
'PUT',
|
||||||
|
function(success) {
|
||||||
|
LoadStates();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
LoadStates();
|
||||||
|
},
|
||||||
|
JSON.stringify(model)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
@@ -1,4 +1,4 @@
|
|||||||
<p>Are you sure you want to delete this media group?</p>
|
<p>Are you sure you want to delete this media group and all associated saved states?</p>
|
||||||
<p><strong>Warning:</strong> This cannot be undone!</p>
|
<p><strong>Warning:</strong> This cannot be undone!</p>
|
||||||
<div style="width: 100%; text-align: center;">
|
<div style="width: 100%; text-align: center;">
|
||||||
<div style="display: inline-block; margin-right: 20px;">
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<p>Are you sure you want to delete this ROM?</p>
|
<p>Are you sure you want to delete this ROM and all associated saved states?</p>
|
||||||
<p><strong>Warning:</strong> This cannot be undone!</p>
|
<p><strong>Warning:</strong> This cannot be undone!</p>
|
||||||
<div style="width: 100%; text-align: center;">
|
<div style="width: 100%; text-align: center;">
|
||||||
<div style="display: inline-block; margin-right: 20px;">
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<p>Are you sure you want to delete the selected ROMs?</p>
|
<p>Are you sure you want to delete the selected ROMs and any associated saved states?</p>
|
||||||
<p><strong>Warning:</strong> This cannot be undone!</p>
|
<p><strong>Warning:</strong> This cannot be undone!</p>
|
||||||
<div style="width: 100%; text-align: center;">
|
<div style="width: 100%; text-align: center;">
|
||||||
<div style="display: inline-block; margin-right: 20px;">
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
|
@@ -6,7 +6,15 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var gameId = getQueryString('gameid', 'int');
|
var gameId = getQueryString('gameid', 'int');
|
||||||
|
var romId = getQueryString('romid', 'int');
|
||||||
var platformId = getQueryString('platformid', 'int');
|
var platformId = getQueryString('platformid', 'int');
|
||||||
|
var IsMediaGroupInt = getQueryString('mediagroup', 'int');
|
||||||
|
var IsMediaGroup = false;
|
||||||
|
if (IsMediaGroupInt == 1) { IsMediaGroup = true; }
|
||||||
|
var StateUrl = undefined;
|
||||||
|
if (getQueryString('stateid', 'int')) {
|
||||||
|
StateUrl = '/api/v1.1/StateManager/' + romId + '/' + getQueryString('stateid', 'int') + '/State/savestate.state?IsMediaGroup=' + IsMediaGroup;
|
||||||
|
}
|
||||||
var gameData;
|
var gameData;
|
||||||
var artworks = null;
|
var artworks = null;
|
||||||
var artworksPosition = 0;
|
var artworksPosition = 0;
|
||||||
|
@@ -97,7 +97,7 @@
|
|||||||
<button value="Search" onclick="loadRoms();">Search</button>
|
<button value="Search" onclick="loadRoms();">Search</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="games_library_controlblock">
|
<div class="games_library_controlblock">
|
||||||
<span class="games_library_label">0 ROMs</span>
|
<span id="games_roms_count" class="games_library_label">0 ROMs</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="gamesummaryromscontent"></div>
|
<div id="gamesummaryromscontent"></div>
|
||||||
@@ -476,7 +476,7 @@
|
|||||||
mgTable.id = 'mediagrouptable';
|
mgTable.id = 'mediagrouptable';
|
||||||
mgTable.className = 'romtable';
|
mgTable.className = 'romtable';
|
||||||
mgTable.setAttribute('cellspacing', 0);
|
mgTable.setAttribute('cellspacing', 0);
|
||||||
mgTable.appendChild(createTableRow(true, ['Platform', 'Images', 'Size', '', '', '']));
|
mgTable.appendChild(createTableRow(true, ['Platform', 'Images', 'Size', '', '', '', '']));
|
||||||
|
|
||||||
lastPlatform = '';
|
lastPlatform = '';
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
@@ -484,9 +484,29 @@
|
|||||||
|
|
||||||
// get rom details including emulator and friendly platform name
|
// get rom details including emulator and friendly platform name
|
||||||
var launchButton = '';
|
var launchButton = '';
|
||||||
|
var saveStatesButton = '';
|
||||||
if (mediaGroup.emulator) {
|
if (mediaGroup.emulator) {
|
||||||
if (mediaGroup.emulator.type.length > 0) {
|
if (mediaGroup.emulator.type.length > 0) {
|
||||||
launchButton = '<a href="/index.html?page=emulator&engine=' + mediaGroup.emulator.type + '&core=' + mediaGroup.emulator.core + '&platformid=' + mediaGroup.platformId + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip') + '" class="romstart">Launch</a>';
|
var romPath = encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip');
|
||||||
|
|
||||||
|
if (mediaGroup.hasSaveStates == true) {
|
||||||
|
var modalVariables = {
|
||||||
|
"romId": mediaGroup.id,
|
||||||
|
"IsMediaGroup": true,
|
||||||
|
"engine": mediaGroup.emulator.type,
|
||||||
|
"core": mediaGroup.emulator.core,
|
||||||
|
"platformid": mediaGroup.platformId,
|
||||||
|
"gameid": gameId,
|
||||||
|
"mediagroup": 1,
|
||||||
|
"rompath": romPath
|
||||||
|
};
|
||||||
|
saveStatesButton = document.createElement('a');
|
||||||
|
saveStatesButton.href = '#';
|
||||||
|
saveStatesButton.setAttribute('onclick', 'showDialog("emulatorloadstate", ' + JSON.stringify(modalVariables) + ');');
|
||||||
|
saveStatesButton.innerHTML = '<img src="/images/SaveStates.png" class="savedstateicon" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
launchButton = '<a href="/index.html?page=emulator&engine=' + mediaGroup.emulator.type + '&core=' + mediaGroup.emulator.core + '&platformid=' + mediaGroup.platformId + '&gameid=' + gameId + '&romid=' + mediaGroup.id + '&mediagroup=1&rompath=' + romPath + '" class="romstart">Launch</a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,15 +552,19 @@
|
|||||||
mediaGroup.romIds.length,
|
mediaGroup.romIds.length,
|
||||||
packageSize,
|
packageSize,
|
||||||
statusText,
|
statusText,
|
||||||
|
saveStatesButton,
|
||||||
launchButtonContent,
|
launchButtonContent,
|
||||||
'<div style="text-align: right;">' + downloadLink + deleteButton + '</div>'
|
'<div style="text-align: right;">' + downloadLink + deleteButton + '</div>'
|
||||||
]
|
]
|
||||||
|
|
||||||
mgTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
var mgRowBody = document.createElement('tbody');
|
||||||
|
mgRowBody.className = 'romrow';
|
||||||
|
|
||||||
|
mgRowBody.appendChild(createTableRow(false, newRow, '', 'romcell'));
|
||||||
|
|
||||||
var mgRomRow = document.createElement('tr');
|
var mgRomRow = document.createElement('tr');
|
||||||
var mgRomCell = document.createElement('td');
|
var mgRomCell = document.createElement('td');
|
||||||
mgRomCell.setAttribute('colspan', 6);
|
mgRomCell.setAttribute('colspan', 7);
|
||||||
mgRomCell.className = 'romGroupTitles';
|
mgRomCell.className = 'romGroupTitles';
|
||||||
|
|
||||||
|
|
||||||
@@ -557,7 +581,9 @@
|
|||||||
}
|
}
|
||||||
mgRomCell.innerHTML = groupMemberNames.join("<br />");
|
mgRomCell.innerHTML = groupMemberNames.join("<br />");
|
||||||
mgRomRow.appendChild(mgRomCell);
|
mgRomRow.appendChild(mgRomCell);
|
||||||
mgTable.appendChild(mgRomRow);
|
mgRowBody.appendChild(mgRomRow);
|
||||||
|
|
||||||
|
mgTable.appendChild(mgRowBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaGroupDiv.appendChild(mgTable);
|
mediaGroupDiv.appendChild(mgTable);
|
||||||
@@ -600,6 +626,13 @@
|
|||||||
var gameRoms = document.getElementById('gamesummaryromscontent');
|
var gameRoms = document.getElementById('gamesummaryromscontent');
|
||||||
var pageSize = 20;
|
var pageSize = 20;
|
||||||
ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform + nameSearchQuery, 'GET', function (result) {
|
ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform + nameSearchQuery, 'GET', function (result) {
|
||||||
|
var romCount = document.getElementById('games_roms_count');
|
||||||
|
if (result.count != 1) {
|
||||||
|
romCount.innerHTML = result.count + ' ROMs';
|
||||||
|
} else {
|
||||||
|
romCount.innerHTML = result.count + ' ROM';
|
||||||
|
}
|
||||||
|
|
||||||
if (result.gameRomItems) {
|
if (result.gameRomItems) {
|
||||||
var gameRomItems = result.gameRomItems;
|
var gameRomItems = result.gameRomItems;
|
||||||
|
|
||||||
@@ -608,7 +641,7 @@
|
|||||||
newTable.id = 'romtable';
|
newTable.id = 'romtable';
|
||||||
newTable.className = 'romtable';
|
newTable.className = 'romtable';
|
||||||
newTable.setAttribute('cellspacing', 0);
|
newTable.setAttribute('cellspacing', 0);
|
||||||
newTable.appendChild(createTableRow(true, [['<input id="rom_mastercheck" type="checkbox" onclick="selectAllChecks(); handleChecks();"/>', 'rom_checkbox_box_hidden', 'rom_edit_checkbox'], 'Name', 'Size', 'Media', '', '', '']));
|
newTable.appendChild(createTableRow(true, [['<input id="rom_mastercheck" type="checkbox" onclick="selectAllChecks(); handleChecks();"/>', 'rom_checkbox_box_hidden', 'rom_edit_checkbox'], 'Name', 'Size', 'Media', '', '', '', '']));
|
||||||
|
|
||||||
var lastPlatform = '';
|
var lastPlatform = '';
|
||||||
for (var i = 0; i < gameRomItems.length; i++) {
|
for (var i = 0; i < gameRomItems.length; i++) {
|
||||||
@@ -622,11 +655,29 @@
|
|||||||
newTable.appendChild(platformRow);
|
newTable.appendChild(platformRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var saveStatesButton = '';
|
||||||
var launchButton = '';
|
var launchButton = '';
|
||||||
if (result.gameRomItems[i].emulator) {
|
if (result.gameRomItems[i].emulator) {
|
||||||
if (gameRomItems[i].emulator.type) {
|
if (gameRomItems[i].emulator.type) {
|
||||||
if (gameRomItems[i].emulator.type.length > 0) {
|
if (gameRomItems[i].emulator.type.length > 0) {
|
||||||
launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItems[i].emulator.type + '&core=' + gameRomItems[i].emulator.core + '&platformid=' + gameRomItems[i].platformId + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/roms/' + gameRomItems[i].id + '/' + encodeURIComponent(gameRomItems[i].name)) + '" class="romstart">Launch</a>';
|
var romPath = encodeURIComponent('/api/v1.1/Games/' + gameId + '/roms/' + gameRomItems[i].id + '/' + gameRomItems[i].name);
|
||||||
|
if (gameRomItems[i].hasSaveStates == true) {
|
||||||
|
var modalVariables = {
|
||||||
|
"romId": gameRomItems[i].id,
|
||||||
|
"IsMediaGroup": false,
|
||||||
|
"engine": gameRomItems[i].emulator.type,
|
||||||
|
"core": gameRomItems[i].emulator.core,
|
||||||
|
"platformid": gameRomItems[i].platformId,
|
||||||
|
"gameid": gameId,
|
||||||
|
"mediagroup": 0,
|
||||||
|
"rompath": romPath
|
||||||
|
};
|
||||||
|
saveStatesButton = document.createElement('a');
|
||||||
|
saveStatesButton.href = '#';
|
||||||
|
saveStatesButton.setAttribute('onclick', 'showDialog("emulatorloadstate", ' + JSON.stringify(modalVariables) + ');');
|
||||||
|
saveStatesButton.innerHTML = '<img src="/images/SaveStates.png" class="savedstateicon" />';
|
||||||
|
}
|
||||||
|
launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItems[i].emulator.type + '&core=' + gameRomItems[i].emulator.core + '&platformid=' + gameRomItems[i].platformId + '&gameid=' + gameId + '&romid=' + gameRomItems[i].id + '&mediagroup=0&rompath=' + romPath + '" class="romstart">Launch</a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -637,10 +688,11 @@
|
|||||||
formatBytes(gameRomItems[i].size, 2),
|
formatBytes(gameRomItems[i].size, 2),
|
||||||
gameRomItems[i].romTypeMedia,
|
gameRomItems[i].romTypeMedia,
|
||||||
gameRomItems[i].mediaLabel,
|
gameRomItems[i].mediaLabel,
|
||||||
|
saveStatesButton,
|
||||||
launchButton,
|
launchButton,
|
||||||
'<div class="properties_button" onclick="showDialog(\'rominfo\', ' + gameRomItems[i].id + ');">i</div>'
|
'<div class="properties_button" onclick="showDialog(\'rominfo\', ' + gameRomItems[i].id + ');">i</div>'
|
||||||
];
|
];
|
||||||
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
newTable.appendChild(createTableRow(false, newRow, 'romrow romrowgamepage', 'romcell'));
|
||||||
}
|
}
|
||||||
|
|
||||||
gameRoms.appendChild(newTable);
|
gameRoms.appendChild(newTable);
|
||||||
|
@@ -495,4 +495,13 @@ function SetPreference_Local(Setting, Value) {
|
|||||||
userProfile.userPreferences.push(model);
|
userProfile.userPreferences.push(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Uint8ToString(u8a){
|
||||||
|
var CHUNK_SZ = 0x8000;
|
||||||
|
var c = [];
|
||||||
|
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
|
||||||
|
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
|
||||||
|
}
|
||||||
|
return c.join("");
|
||||||
}
|
}
|
58
gaseous-server/wwwroot/scripts/notifications.js
Normal file
58
gaseous-server/wwwroot/scripts/notifications.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
function displayNotification(heading, message, image, link) {
|
||||||
|
var noteId = Math.random().toString(36).substr(2, 9);
|
||||||
|
|
||||||
|
var noteBox = document.createElement('div');
|
||||||
|
noteBox.id = noteId;
|
||||||
|
noteBox.className = 'notification';
|
||||||
|
noteBox.style.display = 'none;'
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
noteBox.setAttribute('onclick', 'window.location.href = "' + link + '"');
|
||||||
|
} else {
|
||||||
|
noteBox.setAttribute('onclick', 'closeNotification("' + noteId + '");');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
var noteImageBox = document.createElement('div');
|
||||||
|
noteImageBox.className = 'notification_imagebox';
|
||||||
|
|
||||||
|
var noteImage = document.createElement('img');
|
||||||
|
noteImage.className = 'notification_image';
|
||||||
|
noteImage.src = image;
|
||||||
|
noteImageBox.appendChild(noteImage);
|
||||||
|
|
||||||
|
noteBox.appendChild(noteImageBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
var noteMessageBox = document.createElement('div');
|
||||||
|
noteMessageBox.className = 'notification_messagebox';
|
||||||
|
|
||||||
|
if (heading) {
|
||||||
|
var noteMessageHeading = document.createElement('div');
|
||||||
|
noteMessageHeading.className = 'notification_title';
|
||||||
|
noteMessageHeading.innerHTML = heading;
|
||||||
|
noteMessageBox.appendChild(noteMessageHeading);
|
||||||
|
}
|
||||||
|
|
||||||
|
var noteMessageBody = document.createElement('div');
|
||||||
|
noteMessageBody.className = 'notification_message';
|
||||||
|
noteMessageBody.innerHTML = message;
|
||||||
|
noteMessageBox.appendChild(noteMessageBody);
|
||||||
|
|
||||||
|
noteBox.appendChild(noteMessageBox);
|
||||||
|
|
||||||
|
document.getElementById('notifications_target').appendChild(noteBox);
|
||||||
|
|
||||||
|
$(noteBox).hide().fadeIn(500);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
closeNotification(noteId);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeNotification(id) {
|
||||||
|
var notificationObj = document.getElementById(id);
|
||||||
|
$(notificationObj).fadeOut(1000, function() {
|
||||||
|
notificationObj.parentElement.removeChild(notificationObj);
|
||||||
|
});
|
||||||
|
}
|
58
gaseous-server/wwwroot/styles/notifications.css
Normal file
58
gaseous-server/wwwroot/styles/notifications.css
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#notification_target {
|
||||||
|
position: fixed;
|
||||||
|
top: 40px;
|
||||||
|
width: 400px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column nowrap;
|
||||||
|
top: 55px;
|
||||||
|
right: 15px;
|
||||||
|
width: 350px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 7px;
|
||||||
|
border-color: rgba(0, 22, 56, 0.7);
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
background-color: rgba(0, 22, 56, 0.6);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||||
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||||
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification_imagebox {
|
||||||
|
flex-basis: 70px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification_image {
|
||||||
|
width: 80px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification_messagebox {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification_title {
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgb(160, 160, 186);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification_message {
|
||||||
|
|
||||||
|
}
|
@@ -792,10 +792,20 @@ table .romrow:nth-child(odd) {
|
|||||||
background: rgba(56, 56, 56, 0.3);
|
background: rgba(56, 56, 56, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.romrow.romrowgamepage {
|
||||||
|
height: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
.romcell {
|
.romcell {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.savedstateicon {
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
@@ -1416,4 +1426,49 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#saved_states {
|
||||||
|
overflow-x: scroll;
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column nowrap;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_image_box {
|
||||||
|
flex-basis: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_image_image {
|
||||||
|
width: 128px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_main_box {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_name {
|
||||||
|
font-size: 15px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_date {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_controls {
|
||||||
|
margin-top: 10px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved_state_buttonlink {
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
Reference in New Issue
Block a user