Compare commits

..

4 Commits

Author SHA1 Message Date
Michael Green
df58fb8817 fix: updated PlatformMap.json file with more platforms and fixed SNES extensions 2023-08-21 08:21:46 +10:00
Michael Green
0e4cfccee0 fix: added check for selected items (#58) 2023-08-14 22:05:47 +10:00
Michael Green
014c33d46c fix: missing files from ci (#56) 2023-08-14 21:03:08 +10:00
Michael Green
1dd6a8f71a fix: Update not working after edit (#55)
* Improve metadata first load performance (#46)

* fix: reduces the number of full metadata calls - speeding up imports #45

* chore(deps): update EmulatorJS

* fix: added visual feed back
2023-08-14 18:41:27 +10:00
62 changed files with 723 additions and 3472 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -14,12 +14,6 @@ jobs:
uses: actions/checkout@v3
with:
submodules: 'true'
-
name: Install dotnet tool
run: dotnet tool install -g dotnetCampus.TagToVersion
-
name: Set tag to version
run: dotnet TagToVersion -t ${{ github.ref }}
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2

View File

@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
michael.green@mrgtech.net.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,3 +0,0 @@
<Project>
<Import Project="build\Version.props" />
</Project>

View File

@@ -5,7 +5,6 @@ This is the server for the Gaseous system. All your games and metadata are store
## Screenshots
![Library](./screenshots/Library.png)
![Game](./screenshots/Game.png)
![Emulator](./screenshots/Emulator.png)
## Requirements
* MySQL Server 8+
@@ -19,9 +18,6 @@ The following projects are used by Gaseous
* https://github.com/kamranayub/igdb-dotnet
* https://github.com/EmulatorJS/EmulatorJS
## Discord Server
[![Join our Discord server!](https://invite.casperiv.dev/?inviteCode=Nhu7wpT3k4&format=svg)](https://discord.gg/Nhu7wpT3k4)
## Configuration File
When Gaseous-Server is started for the first time, it creates a configuration file at ~/.gaseous-server/config.json if it doesn't exist. Some values can be filled in using environment variables (such as in the case of using docker).

View File

@@ -1,5 +0,0 @@
<Project>
<PropertyGroup>
<Version>1.5.0</Version>
</PropertyGroup>
</Project>

Binary file not shown.

Binary file not shown.

View File

@@ -1,607 +0,0 @@
using System;
using System.Data;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using gaseous_server.Classes.Metadata;
using gaseous_server.Controllers;
using gaseous_tools;
using IGDB.Models;
using Newtonsoft.Json;
namespace gaseous_server.Classes
{
public class Collections
{
public Collections()
{
}
public static List<CollectionItem> GetCollections() {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM RomCollections ORDER BY `Name`";
DataTable data = db.ExecuteCMD(sql);
List<CollectionItem> collectionItems = new List<CollectionItem>();
foreach(DataRow row in data.Rows) {
collectionItems.Add(BuildCollectionItem(row));
}
return collectionItems;
}
public static CollectionItem GetCollection(long Id) {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM RomCollections WHERE Id = @id ORDER BY `Name`";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
DataTable romDT = db.ExecuteCMD(sql, dbDict);
if (romDT.Rows.Count > 0)
{
DataRow row = romDT.Rows[0];
CollectionItem collectionItem = BuildCollectionItem(row);
return collectionItem;
}
else
{
throw new Exception("Unknown Collection Id");
}
}
public static CollectionItem NewCollection(CollectionItem item)
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, BuiltStatus) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @builtstatus); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("name", item.Name);
dbDict.Add("description", item.Description);
dbDict.Add("platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())));
dbDict.Add("genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())));
dbDict.Add("players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())));
dbDict.Add("playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())));
dbDict.Add("themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())));
dbDict.Add("minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1));
dbDict.Add("maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1));
dbDict.Add("maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1));
dbDict.Add("maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1));
dbDict.Add("maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1));
dbDict.Add("builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild);
DataTable romDT = db.ExecuteCMD(sql, dbDict);
long CollectionId = (long)romDT.Rows[0][0];
CollectionItem collectionItem = GetCollection(CollectionId);
StartCollectionItemBuild(CollectionId);
return collectionItem;
}
public static CollectionItem EditCollection(long Id, CollectionItem item)
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, BuiltStatus=@builtstatus WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
dbDict.Add("name", item.Name);
dbDict.Add("description", item.Description);
dbDict.Add("platforms", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Platforms, new List<long>())));
dbDict.Add("genres", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Genres, new List<long>())));
dbDict.Add("players", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Players, new List<long>())));
dbDict.Add("playerperspectives", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.PlayerPerspectives, new List<long>())));
dbDict.Add("themes", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.Themes, new List<long>())));
dbDict.Add("minimumrating", Common.ReturnValueIfNull(item.MinimumRating, -1));
dbDict.Add("maximumrating", Common.ReturnValueIfNull(item.MaximumRating, -1));
dbDict.Add("maximumromsperplatform", Common.ReturnValueIfNull(item.MaximumRomsPerPlatform, -1));
dbDict.Add("maximumbytesperplatform", Common.ReturnValueIfNull(item.MaximumBytesPerPlatform, -1));
dbDict.Add("maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1));
dbDict.Add("builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild);
db.ExecuteCMD(sql, dbDict);
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
if (File.Exists(CollectionZipFile))
{
File.Delete(CollectionZipFile);
}
CollectionItem collectionItem = GetCollection(Id);
StartCollectionItemBuild(Id);
return collectionItem;
}
public static void DeleteCollection(long Id)
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "DELETE FROM RomCollections WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
db.ExecuteCMD(sql, dbDict);
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
if (File.Exists(CollectionZipFile))
{
File.Delete(CollectionZipFile);
}
}
public static void StartCollectionItemBuild(long Id)
{
CollectionItem collectionItem = GetCollection(Id);
if (collectionItem.BuildStatus != CollectionItem.CollectionBuildStatus.Building)
{
// set collection item to waitingforbuild
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", Id);
dbDict.Add("bs", CollectionItem.CollectionBuildStatus.WaitingForBuild);
db.ExecuteCMD(sql, dbDict);
// start background task
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
{
if (qi.ItemType == ProcessQueue.QueueItemType.CollectionCompiler) {
qi.ForceExecute();
break;
}
}
}
}
public static CollectionContents GetCollectionContent(CollectionItem collectionItem) {
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = new List<CollectionContents.CollectionPlatformItem>();
// get platforms
List<Platform> platforms = new List<Platform>();
if (collectionItem.Platforms.Count > 0) {
foreach (long PlatformId in collectionItem.Platforms) {
platforms.Add(Platforms.GetPlatform(PlatformId));
}
} else {
// get all platforms to pull from
FilterController filterController = new FilterController();
platforms.AddRange((List<Platform>)filterController.Filter()["platforms"]);
}
// build collection
List<CollectionContents.CollectionPlatformItem> platformItems = new List<CollectionContents.CollectionPlatformItem>();
foreach (Platform platform in platforms) {
long TotalRomSize = 0;
long TotalGameCount = 0;
List<Game> games = GamesController.GetGames("",
platform.Id.ToString(),
string.Join(",", collectionItem.Genres),
string.Join(",", collectionItem.Players),
string.Join(",", collectionItem.PlayerPerspectives),
string.Join(",", collectionItem.Themes),
collectionItem.MinimumRating,
collectionItem.MaximumRating
);
CollectionContents.CollectionPlatformItem collectionPlatformItem = new CollectionContents.CollectionPlatformItem(platform);
collectionPlatformItem.Games = new List<CollectionContents.CollectionPlatformItem.CollectionGameItem>();
foreach (Game game in games) {
CollectionContents.CollectionPlatformItem.CollectionGameItem collectionGameItem = new CollectionContents.CollectionPlatformItem.CollectionGameItem(game);
List<Roms.GameRomItem> gameRoms = Roms.GetRoms((long)game.Id, (long)platform.Id);
bool AddGame = false;
// calculate total rom size for the game
long GameRomSize = 0;
foreach (Roms.GameRomItem gameRom in gameRoms) {
GameRomSize += gameRom.Size;
}
if (collectionItem.MaximumBytesPerPlatform > 0) {
if ((TotalRomSize + GameRomSize) < collectionItem.MaximumBytesPerPlatform) {
AddGame = true;
}
}
else
{
AddGame = true;
}
if (AddGame == true) {
TotalRomSize += GameRomSize;
bool AddRoms = false;
if (collectionItem.MaximumRomsPerPlatform > 0) {
if (TotalGameCount < collectionItem.MaximumRomsPerPlatform) {
AddRoms = true;
}
}
else
{
AddRoms = true;
}
if (AddRoms == true) {
TotalGameCount += 1;
collectionGameItem.Roms = gameRoms;
collectionPlatformItem.Games.Add(collectionGameItem);
}
}
}
if (collectionPlatformItem.Games.Count > 0)
{
bool AddPlatform = false;
if (collectionItem.MaximumCollectionSizeInBytes > 0)
{
if (TotalRomSize < collectionItem.MaximumCollectionSizeInBytes)
{
AddPlatform = true;
}
}
else
{
AddPlatform = true;
}
if (AddPlatform == true)
{
collectionPlatformItems.Add(collectionPlatformItem);
}
}
}
CollectionContents collectionContents = new CollectionContents();
collectionContents.Collection = collectionPlatformItems;
return collectionContents;
}
public static void CompileCollections()
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
List<CollectionItem> collectionItems = GetCollections();
foreach (CollectionItem collectionItem in collectionItems)
{
if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild)
{
// set starting
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", collectionItem.Id);
dbDict.Add("bs", CollectionItem.CollectionBuildStatus.Building);
db.ExecuteCMD(sql, dbDict);
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = GetCollectionContent(collectionItem).Collection;
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + ".zip");
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, collectionItem.Id.ToString());
try
{
// clean up if needed
if (File.Exists(ZipFilePath))
{
File.Delete(ZipFilePath);
}
if (Directory.Exists(ZipFileTempPath))
{
Directory.Delete(ZipFileTempPath, true);
}
// gather collection files
Directory.CreateDirectory(ZipFileTempPath);
foreach (CollectionContents.CollectionPlatformItem collectionPlatformItem in collectionPlatformItems)
{
// create platform directory
string ZipPlatformPath = Path.Combine(ZipFileTempPath, collectionPlatformItem.Slug);
if (!Directory.Exists(ZipPlatformPath))
{
Directory.CreateDirectory(ZipPlatformPath);
}
foreach (CollectionContents.CollectionPlatformItem.CollectionGameItem collectionGameItem in collectionPlatformItem.Games)
{
// create game directory
string ZipGamePath = Path.Combine(ZipPlatformPath, collectionGameItem.Slug);
if (!Directory.Exists(ZipGamePath))
{
Directory.CreateDirectory(ZipGamePath);
}
// copy in roms
foreach (Roms.GameRomItem gameRomItem in collectionGameItem.Roms)
{
if (File.Exists(gameRomItem.Path))
{
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name));
}
}
}
}
// compress to zip
ZipFile.CreateFromDirectory(ZipFileTempPath, ZipFilePath, CompressionLevel.SmallestSize, false);
// clean up
if (Directory.Exists(ZipFileTempPath))
{
Directory.Delete(ZipFileTempPath, true);
}
// set completed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Completed;
db.ExecuteCMD(sql, dbDict);
}
catch (Exception ex)
{
// clean up
if (Directory.Exists(ZipFileTempPath))
{
Directory.Delete(ZipFileTempPath, true);
}
if (File.Exists(ZipFilePath))
{
File.Delete(ZipFilePath);
}
// set failed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Failed;
db.ExecuteCMD(sql, dbDict);
Logging.Log(Logging.LogType.Critical, "Collection Builder", "Collection building has failed", ex);
}
}
}
}
private static CollectionItem BuildCollectionItem(DataRow row) {
string strPlatforms = (string)Common.ReturnValueIfNull(row["Platforms"], "[ ]");
string strGenres = (string)Common.ReturnValueIfNull(row["Genres"], "[ ]");
string strPlayers = (string)Common.ReturnValueIfNull(row["Players"], "[ ]");
string strPlayerPerspectives = (string)Common.ReturnValueIfNull(row["PlayerPerspectives"], "[ ]");
string strThemes = (string)Common.ReturnValueIfNull(row["Themes"], "[ ]");
CollectionItem item = new CollectionItem();
item.Id = (long)row["Id"];
item.Name = (string)row["Name"];
item.Description = (string)row["Description"];
item.Platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(strPlatforms);
item.Genres = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(strGenres);
item.Players = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(strPlayers);
item.PlayerPerspectives = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(strPlayerPerspectives);
item.Themes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(strThemes);
item.MinimumRating = (int)Common.ReturnValueIfNull(row["MinimumRating"], -1);
item.MaximumRating = (int)Common.ReturnValueIfNull(row["MaximumRating"], -1);
item.MaximumRomsPerPlatform = (int)Common.ReturnValueIfNull(row["MaximumRomsPerPlatform"], (int)-1);
item.MaximumBytesPerPlatform = (long)Common.ReturnValueIfNull(row["MaximumBytesPerPlatform"], (long)-1);
item.MaximumCollectionSizeInBytes = (long)Common.ReturnValueIfNull(row["MaximumCollectionSizeInBytes"], (long)-1);
item.BuildStatus = (CollectionItem.CollectionBuildStatus)(int)Common.ReturnValueIfNull(row["BuiltStatus"], 0);
return item;
}
public class CollectionItem
{
public CollectionItem()
{
}
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<long>? Platforms { get; set; }
public List<long>? Genres { get; set; }
public List<long>? Players { get; set; }
public List<long>? PlayerPerspectives { get; set; }
public List<long>? Themes { get; set; }
public int MinimumRating { get; set; }
public int MaximumRating { get; set; }
public int? MaximumRomsPerPlatform { get; set; }
public long? MaximumBytesPerPlatform { get; set; }
public long? MaximumCollectionSizeInBytes { get; set; }
[JsonIgnore]
public CollectionBuildStatus BuildStatus
{
get
{
if (_BuildStatus == CollectionBuildStatus.Completed)
{
if (File.Exists(Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip")))
{
return CollectionBuildStatus.Completed;
}
else
{
return CollectionBuildStatus.NoStatus;
}
}
else
{
return _BuildStatus;
}
}
set
{
_BuildStatus = value;
}
}
private CollectionBuildStatus _BuildStatus { get; set; }
[JsonIgnore]
public long CollectionBuiltSizeBytes
{
get
{
if (BuildStatus == CollectionBuildStatus.Completed)
{
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
if (File.Exists(ZipFilePath))
{
FileInfo fi = new FileInfo(ZipFilePath);
return fi.Length;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
public enum CollectionBuildStatus
{
NoStatus = 0,
WaitingForBuild = 1,
Building = 2,
Completed = 3,
Failed = 4
}
}
public class CollectionContents {
[JsonIgnore]
public List<CollectionPlatformItem> Collection { get; set; }
[JsonIgnore]
public long CollectionProjectedSizeBytes
{
get
{
long CollectionSize = 0;
List<CollectionPlatformItem> collectionPlatformItems = new List<CollectionPlatformItem>();
if (Collection != null)
{
collectionPlatformItems = Collection;
}
foreach (CollectionPlatformItem platformItem in collectionPlatformItems)
{
CollectionSize += platformItem.RomSize;
}
return CollectionSize;
}
}
public class CollectionPlatformItem {
public CollectionPlatformItem(IGDB.Models.Platform platform) {
string[] PropertyWhitelist = new string[] { "Id", "Name", "Slug" };
PropertyInfo[] srcProperties = typeof(IGDB.Models.Platform).GetProperties();
PropertyInfo[] dstProperties = typeof(CollectionPlatformItem).GetProperties();
foreach (PropertyInfo srcProperty in srcProperties) {
if (PropertyWhitelist.Contains<string>(srcProperty.Name))
{
foreach (PropertyInfo dstProperty in dstProperties)
{
if (srcProperty.Name == dstProperty.Name)
{
dstProperty.SetValue(this, srcProperty.GetValue(platform));
}
}
}
}
}
public long Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public List<CollectionGameItem> Games { get; set; }
public int RomCount {
get {
int Counter = 0;
foreach (CollectionGameItem Game in Games) {
Counter += 1;
}
return Counter;
}
}
public long RomSize {
get {
long Size = 0;
foreach (CollectionGameItem Game in Games) {
foreach (Roms.GameRomItem Rom in Game.Roms) {
Size += Rom.Size;
}
}
return Size;
}
}
public class CollectionGameItem {
public CollectionGameItem(IGDB.Models.Game game) {
string[] PropertyWhitelist = new string[] { "Id", "Name", "Slug", "Cover" };
PropertyInfo[] srcProperties = typeof(IGDB.Models.Game).GetProperties();
PropertyInfo[] dstProperties = typeof(CollectionPlatformItem.CollectionGameItem).GetProperties();
foreach (PropertyInfo srcProperty in srcProperties) {
if (PropertyWhitelist.Contains<string>(srcProperty.Name))
{
foreach (PropertyInfo dstProperty in dstProperties)
{
if (srcProperty.Name == dstProperty.Name)
{
if (srcProperty.GetValue(game) != null) {
string compareName = srcProperty.PropertyType.Name.ToLower().Split("`")[0];
switch(compareName) {
case "identityorvalue":
string newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(srcProperty.GetValue(game));
Dictionary<string, object> newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
dstProperty.SetValue(this, newDict["Id"]);
break;
default:
dstProperty.SetValue(this, srcProperty.GetValue(game));
break;
}
}
}
}
}
}
}
public long Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public long Cover { get; set;}
public List<Roms.GameRomItem> Roms { get; set; }
public long RomSize {
get {
long Size = 0;
foreach (Roms.GameRomItem Rom in Roms) {
Size += Rom.Size;
}
return Size;
}
}
}
}
}
}
}

View File

@@ -129,7 +129,7 @@ namespace gaseous_server.Classes
{
// file is a zip and less than 1 GiB
// extract the zip file and search the contents
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, Path.GetRandomFileName());
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "Temp", Path.GetRandomFileName());
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);

View File

@@ -1,110 +0,0 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class GameModes
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public GameModes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static GameMode? GetGame_Modes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static GameMode GetGame_Modes(string Slug)
{
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<GameMode> _GetGame_Modes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("GameMode", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("GameMode", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
GameMode returnValue = new GameMode();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<GameMode> GetObjectFromServer(string WhereClause)
{
// get Game_Modes metadata
var results = await igdb.QueryAsync<GameMode>(IGDBClient.Endpoints.GameModes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -205,22 +205,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.GameModes != null)
{
foreach (long gameModeId in Game.GameModes.Ids)
{
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
}
}
if (Game.MultiplayerModes != null)
{
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
{
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
}
}
if (Game.Platforms != null)
{
foreach (long PlatformId in Game.Platforms.Ids)
@@ -229,14 +213,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.PlayerPerspectives != null)
{
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
{
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
}
}
if (Game.Screenshots != null)
{
foreach (long ScreenshotId in Game.Screenshots.Ids)
@@ -245,14 +221,6 @@ namespace gaseous_server.Classes.Metadata
}
}
if (Game.Themes != null)
{
foreach (long ThemeId in Game.Themes.Ids)
{
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
}
}
if (Game.Videos != null)
{
foreach (long GameVideoId in Game.Videos.Ids)

View File

@@ -1,110 +0,0 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class MultiplayerModes
{
const string fieldList = "fields campaigncoop,checksum,dropin,game,lancoop,offlinecoop,offlinecoopmax,offlinemax,onlinecoop,onlinecoopmax,onlinemax,platform,splitscreen,splitscreenonline;";
public MultiplayerModes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static MultiplayerMode? GetGame_MultiplayerModes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static MultiplayerMode GetGame_MultiplayerModes(string Slug)
{
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<MultiplayerMode> _GetGame_MultiplayerModes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
MultiplayerMode returnValue = new MultiplayerMode();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<MultiplayerMode> GetObjectFromServer(string WhereClause)
{
// get Game_MultiplayerModes metadata
var results = await igdb.QueryAsync<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -1,110 +0,0 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class PlayerPerspectives
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public PlayerPerspectives()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static PlayerPerspective? GetGame_PlayerPerspectives(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static PlayerPerspective GetGame_PlayerPerspectives(string Slug)
{
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<PlayerPerspective> _GetGame_PlayerPerspectives(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
PlayerPerspective returnValue = new PlayerPerspective();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<PlayerPerspective> GetObjectFromServer(string WhereClause)
{
// get Game_PlayerPerspectives metadata
var results = await igdb.QueryAsync<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -1,110 +0,0 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
using MySqlX.XDevAPI.Common;
using static gaseous_tools.Config.ConfigFile;
namespace gaseous_server.Classes.Metadata
{
public class Themes
{
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
public Themes()
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Theme? GetGame_Themes(long? Id)
{
if ((Id == 0) || (Id == null))
{
return null;
}
else
{
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static Theme GetGame_Themes(string Slug)
{
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<Theme> _GetGame_Themes(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("Theme", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("Theme", (string)searchValue);
}
// set up where clause
string WhereClause = "";
switch (searchUsing)
{
case SearchUsing.id:
WhereClause = "where id = " + searchValue;
break;
case SearchUsing.slug:
WhereClause = "where slug = " + searchValue;
break;
default:
throw new Exception("Invalid search type");
}
Theme returnValue = new Theme();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<Theme> GetObjectFromServer(string WhereClause)
{
// get Game_Themes metadata
var results = await igdb.QueryAsync<Theme>(IGDBClient.Endpoints.Themes, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
}
}

View File

@@ -6,19 +6,12 @@ namespace gaseous_server.Classes
{
public class Roms
{
public static List<GameRomItem> GetRoms(long GameId, long PlatformId = -1)
public static List<GameRomItem> GetRoms(long GameId)
{
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "";
string sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", GameId);
if (PlatformId == -1) {
sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`";
} else {
sql = "SELECT * FROM Games_Roms WHERE GameId = @id AND PlatformId = @platformid ORDER BY `Name`";
dbDict.Add("platformid", PlatformId);
}
DataTable romDT = db.ExecuteCMD(sql, dbDict);
if (romDT.Rows.Count > 0)

View File

@@ -24,8 +24,6 @@ namespace gaseous_server.Controllers
public ActionResult<ProcessQueue.QueueItem> ForceRun(ProcessQueue.QueueItemType TaskType, Boolean ForceRun)
{
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
{
if (qi.AllowManualStart == true)
{
if (TaskType == qi.ItemType)
{
@@ -36,7 +34,6 @@ namespace gaseous_server.Controllers
return qi;
}
}
}
return NotFound();
}

View File

@@ -1,191 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace gaseous_server.Controllers
{
[ApiController]
[Route("api/v1/[controller]")]
public class CollectionsController : Controller
{
/// <summary>
/// Gets all ROM collections
/// </summary>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
public List<Classes.Collections.CollectionItem> GetCollections()
{
return Classes.Collections.GetCollections();
}
/// <summary>
/// Gets a specific ROM collection
/// </summary>
/// <param name="CollectionId"></param>
/// <param name="Build">Set to true to begin the collection build process</param>
/// <returns></returns>
[HttpGet]
[Route("{CollectionId}")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollection(long CollectionId, bool Build = false)
{
try
{
if (Build == true)
{
Classes.Collections.StartCollectionItemBuild(CollectionId);
}
return Ok(Classes.Collections.GetCollection(CollectionId));
}
catch
{
return NotFound();
}
}
/// <summary>
/// Gets the contents of the specified ROM collection
/// </summary>
/// <param name="CollectionId"></param>
/// <returns></returns>
[HttpGet]
[Route("{CollectionId}/Roms")]
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRoms(long CollectionId)
{
try
{
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
return Ok(Classes.Collections.GetCollectionContent(collectionItem));
}
catch
{
return NotFound();
}
}
/// <summary>
/// Gets a preview of the provided collection item
/// </summary>
/// <param name="Item"></param>
/// <returns></returns>
[HttpPost]
[Route("Preview")]
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRomsPreview(Classes.Collections.CollectionItem Item)
{
//try
//{
return Ok(Classes.Collections.GetCollectionContent(Item));
//}
//catch (Exception ex)
//{
// return NotFound(ex);
//}
}
/// <summary>
/// Gets ROM collection in zip format
/// </summary>
/// <param name="CollectionId"></param>
/// <returns></returns>
[HttpGet]
[Route("{CollectionId}/Roms/Zip")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GetCollectionRomsZip(long CollectionId)
{
try
{
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
string ZipFilePath = Path.Combine(gaseous_tools.Config.LibraryConfiguration.LibraryCollectionsDirectory, CollectionId + ".zip");
if (System.IO.File.Exists(ZipFilePath))
{
var stream = new FileStream(ZipFilePath, FileMode.Open);
return File(stream, "application/zip", collectionItem.Name + ".zip");
}
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
/// <summary>
/// Creates a new ROM collection
/// </summary>
/// <param name="Item"></param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult NewCollection(Classes.Collections.CollectionItem Item)
{
try
{
return Ok(Classes.Collections.NewCollection(Item));
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
/// <summary>
/// Edits an existing collection
/// </summary>
/// <param name="CollectionId"></param>
/// <param name="Item"></param>
/// <returns></returns>
[HttpPatch]
[Route("{CollectionId}")]
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
{
try
{
return Ok(Classes.Collections.EditCollection(CollectionId, Item));
}
catch
{
return NotFound();
}
}
/// <summary>
/// Deletes the specified ROM collection
/// </summary>
/// <param name="CollectionId"></param>
[HttpDelete]
[Route("{CollectionId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult DeleteCollection(long CollectionId)
{
try
{
Classes.Collections.DeleteCollection(CollectionId);
return Ok();
}
catch
{
return NotFound();
}
}
}
}

View File

@@ -45,39 +45,6 @@ namespace gaseous_server.Controllers
}
FilterSet.Add("genres", genres);
// game modes
List<GameMode> gameModes = new List<GameMode>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM GameMode AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.GameModes, CAST(t1.Id AS char), '$') ORDER BY t1.Id";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
gameModes.Add(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"]));
}
FilterSet.Add("gamemodes", gameModes);
// player perspectives
List<PlayerPerspective> playerPerspectives = new List<PlayerPerspective>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM PlayerPerspective AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.PlayerPerspectives, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
playerPerspectives.Add(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"]));
}
FilterSet.Add("playerperspectives", playerPerspectives);
// themes
List<Theme> themes = new List<Theme>();
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Theme AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Themes, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows)
{
themes.Add(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"]));
}
FilterSet.Add("themes", themes);
return FilterSet;
}
}

View File

@@ -23,31 +23,7 @@ namespace gaseous_server.Controllers
{
[HttpGet]
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
public ActionResult Game(
string name = "",
string platform = "",
string genre = "",
string gamemode = "",
string playerperspective = "",
string theme = "",
int minrating = -1,
int maxrating = -1,
bool sortdescending = false)
{
return Ok(GetGames(name, platform, genre, gamemode, playerperspective, theme, minrating, maxrating, sortdescending));
}
public static List<Game> GetGames(
string name = "",
string platform = "",
string genre = "",
string gamemode = "",
string playerperspective = "",
string theme = "",
int minrating = -1,
int maxrating = -1,
bool sortdescending = false)
public ActionResult Game(string name = "", string platform = "", string genre = "", bool sortdescending = false)
{
string whereClause = "";
string havingClause = "";
@@ -65,20 +41,6 @@ namespace gaseous_server.Controllers
havingClauses.Add(tempVal);
}
if (minrating != -1)
{
string ratingTempMinVal = "totalRating >= @totalMinRating";
whereParams.Add("@totalMinRating", minrating);
havingClauses.Add(ratingTempMinVal);
}
if (maxrating != -1)
{
string ratingTempMaxVal = "totalRating <= @totalMaxRating";
whereParams.Add("@totalMaxRating", maxrating);
havingClauses.Add(ratingTempMaxVal);
}
if (platform.Length > 0)
{
tempVal = "Games_Roms.PlatformId IN (";
@@ -115,60 +77,6 @@ namespace gaseous_server.Controllers
whereClauses.Add(tempVal);
}
if (gamemode.Length > 0)
{
tempVal = "(";
string[] gameModeClauseItems = gamemode.Split(",");
for (int i = 0; i < gameModeClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string gameModeLabel = "@GameMode" + i;
tempVal += "JSON_CONTAINS(Game.GameModes, " + gameModeLabel + ", '$')";
whereParams.Add(gameModeLabel, gameModeClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
if (playerperspective.Length > 0)
{
tempVal = "(";
string[] playerPerspectiveClauseItems = playerperspective.Split(",");
for (int i = 0; i < playerPerspectiveClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string playerPerspectiveLabel = "@PlayerPerspective" + i;
tempVal += "JSON_CONTAINS(Game.PlayerPerspectives, " + playerPerspectiveLabel + ", '$')";
whereParams.Add(playerPerspectiveLabel, playerPerspectiveClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
if (theme.Length > 0)
{
tempVal = "(";
string[] themeClauseItems = theme.Split(",");
for (int i = 0; i < themeClauseItems.Length; i++)
{
if (i > 0)
{
tempVal += " AND ";
}
string themeLabel = "@Theme" + i;
tempVal += "JSON_CONTAINS(Game.Themes, " + themeLabel + ", '$')";
whereParams.Add(themeLabel, themeClauseItems[i]);
}
tempVal += ")";
whereClauses.Add(tempVal);
}
// build where clause
if (whereClauses.Count > 0)
{
@@ -216,7 +124,7 @@ namespace gaseous_server.Controllers
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
}
return RetVal;
return Ok(RetVal);
}
[HttpGet]

View File

@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using gaseous_tools;
using Microsoft.AspNetCore.Mvc;
@@ -51,22 +49,6 @@ namespace gaseous_server.Controllers
return ReturnValue;
}
[HttpGet]
[Route("Version")]
[ProducesResponseType(StatusCodes.Status200OK)]
public Version GetSystemVersion() {
return Assembly.GetExecutingAssembly().GetName().Version;
}
[HttpGet]
[Route("VersionFile")]
[ProducesResponseType(StatusCodes.Status200OK)]
public FileContentResult GetSystemVersionAsFile() {
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\"";
byte[] bytes = Encoding.UTF8.GetBytes(ver);
return File(bytes, "text/javascript");
}
private SystemInfo.PathItem GetDisk(string Path)
{
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
@@ -81,12 +63,6 @@ namespace gaseous_server.Controllers
public class SystemInfo
{
public Version ApplicationVersion {
get
{
return Assembly.GetExecutingAssembly().GetName().Version;
}
}
public List<PathItem>? Paths { get; set; }
public long DatabaseSize { get; set; }
public List<PlatformStatisticsItem>? PlatformStatistics { get; set; }

View File

@@ -9,22 +9,20 @@ namespace gaseous_server
public class QueueItem
{
public QueueItem(QueueItemType ItemType, int ExecutionInterval, bool AllowManualStart = true)
public QueueItem(QueueItemType ItemType, int ExecutionInterval)
{
_ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
_Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart;
}
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks, bool AllowManualStart = true)
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks)
{
_ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
_Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart;
_Blocks = Blocks;
}
@@ -36,7 +34,6 @@ namespace gaseous_server
private string _LastResult = "";
private string? _LastError = null;
private bool _ForceExecute = false;
private bool _AllowManualStart = true;
private List<QueueItemType> _Blocks = new List<QueueItemType>();
public QueueItemType ItemType => _ItemType;
@@ -53,7 +50,6 @@ namespace gaseous_server
public string LastResult => _LastResult;
public string? LastError => _LastError;
public bool Force => _ForceExecute;
public bool AllowManualStart => _AllowManualStart;
public List<QueueItemType> Blocks => _Blocks;
public void Execute()
@@ -100,10 +96,6 @@ namespace gaseous_server
Classes.ImportGame.LibraryScan();
break;
case QueueItemType.CollectionCompiler:
Logging.Log(Logging.LogType.Information, "Timered Event", "Starting Collection Compiler");
Classes.Collections.CompileCollections();
break;
}
}
catch (Exception ex)
@@ -133,8 +125,7 @@ namespace gaseous_server
TitleIngestor,
MetadataRefresh,
OrganiseLibrary,
LibraryScan,
CollectionCompiler
LibraryScan
}
public enum QueueItemState

View File

@@ -1,13 +1,11 @@
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using gaseous_server;
using gaseous_tools;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.OpenApi.Models;
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version);
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server");
// set up db
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
@@ -85,31 +83,7 @@ builder.Services.Configure<FormOptions>(options =>
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Gaseous Server API",
Description = "An API for managing the Gaseous Server",
TermsOfService = new Uri("https://github.com/gaseous-project/gaseous-server"),
Contact = new OpenApiContact
{
Name = "GitHub Repository",
Url = new Uri("https://github.com/gaseous-project/gaseous-server")
},
License = new OpenApiLicense
{
Name = "Gaseous Server License",
Url = new Uri("https://github.com/gaseous-project/gaseous-server/blob/main/LICENSE")
}
});
// using System.Reflection;
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
}
);
builder.Services.AddSwaggerGen();
builder.Services.AddHostedService<TimedHostedService>();
var app = builder.Build();
@@ -171,7 +145,6 @@ ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.OrganiseLibrary
})
);
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.CollectionCompiler, 5, false));
// start the app
app.Run();

View File

@@ -13,14 +13,10 @@
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\net7.0\gaseous-server.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.9" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.8" />
<PackageReference Include="IGDB" Version="2.3.2" />
</ItemGroup>
@@ -119,6 +115,9 @@
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Remove="Support\PlatformMap.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="249.44 647.1 1461.24 702.85">
<title>IGDB logo</title>
<g id="text_logo">
<path fill="#000000" d=" M 249.44 647.14 C 736.51 647.13 1223.59 647.21 1710.67 647.10 C 1710.68 881.38 1710.69 1115.67 1710.66 1349.95 C 1615.86 1334.68 1520.63 1321.89 1425.05 1312.53 C 1080.16 1278.28 731.31 1284.02 387.73 1329.60 C 341.52 1335.59 295.47 1342.74 249.44 1349.92 C 249.43 1115.66 249.45 881.40 249.44 647.14 M 292.45 690.16 C 292.47 893.35 292.45 1096.55 292.45 1299.74 C 747.32 1230.12 1212.80 1230.06 1667.66 1299.76 C 1667.69 1096.55 1667.67 893.34 1667.67 690.13 C 1209.26 690.20 750.85 690.15 292.45 690.16 Z"/>
<path fill="#000000" d=" M 606.98 849.96 C 636.79 820.94 678.61 805.48 720.03 806.13 C 748.31 806.03 777.18 810.46 802.61 823.37 C 815.72 829.91 827.70 838.49 838.88 847.92 C 824.81 864.91 810.62 881.79 796.71 898.90 C 788.34 892.63 780.20 885.94 770.94 880.98 C 752.35 870.49 730.45 866.86 709.32 868.40 C 683.46 870.61 659.80 886.20 645.79 907.79 C 627.73 934.91 624.92 970.60 635.86 1000.97 C 642.48 1019.42 655.12 1035.79 671.77 1046.24 C 688.33 1056.88 708.44 1061.15 727.96 1059.98 C 747.98 1059.21 768.36 1053.75 784.66 1041.78 C 784.50 1027.38 784.66 1012.97 784.58 998.57 C 762.15 998.63 739.71 998.55 717.28 998.61 C 717.23 979.29 717.40 959.97 717.20 940.66 C 761.32 940.38 805.45 940.76 849.57 940.47 C 849.84 984.58 849.54 1028.70 849.72 1072.81 C 819.35 1099.03 781.02 1116.23 740.99 1120.14 C 701.91 1124.43 660.71 1117.24 627.40 1095.69 C 600.71 1078.68 580.09 1052.59 569.30 1022.87 C 558.65 993.63 556.55 961.41 562.53 930.93 C 568.76 900.29 584.34 871.56 606.98 849.96 Z"/>
<path fill="#000000" d=" M 412.22 811.37 C 434.59 811.42 456.96 811.33 479.33 811.42 C 479.28 912.90 479.33 1014.39 479.31 1115.88 C 456.95 1115.87 434.59 1115.84 412.23 1115.89 C 412.22 1014.39 412.24 912.88 412.22 811.37 Z"/>
<path fill="#000000" d=" M 931.25 811.38 C 972.17 811.39 1013.09 811.38 1054.01 811.39 C 1091.21 811.80 1128.88 823.34 1157.99 846.93 C 1183.44 867.28 1201.49 896.55 1208.37 928.40 C 1216.70 966.86 1211.27 1008.80 1190.62 1042.63 C 1174.23 1069.90 1148.49 1091.13 1119.07 1103.04 C 1098.46 1111.41 1076.23 1115.81 1053.98 1115.87 C 1013.08 1115.87 972.17 1115.85 931.26 1115.88 C 931.26 1014.38 931.28 912.88 931.25 811.38 M 998.55 871.86 C 998.45 933.04 998.56 994.22 998.49 1055.41 C 1011.33 1055.39 1024.18 1055.40 1037.02 1055.40 C 1047.36 1055.32 1057.79 1055.89 1068.03 1053.99 C 1088.10 1050.87 1107.44 1041.22 1120.71 1025.65 C 1132.31 1012.31 1139.05 995.20 1141.08 977.75 C 1142.97 960.03 1141.47 941.67 1134.60 925.11 C 1127.53 907.51 1114.31 892.45 1097.61 883.42 C 1082.53 875.02 1065.11 871.85 1047.99 871.84 C 1031.51 871.88 1015.03 871.84 998.55 871.86 Z"/>
<path fill="#000000" d=" M 1288.80 811.57 C 1330.15 811.13 1371.54 811.51 1412.90 811.38 C 1424.26 811.54 1435.65 810.91 1446.97 812.08 C 1467.08 813.95 1487.46 819.82 1503.55 832.45 C 1517.54 843.24 1527.36 859.35 1530.07 876.86 C 1532.03 893.42 1531.12 911.06 1522.97 925.99 C 1516.04 939.38 1504.10 949.32 1491.26 956.78 C 1508.37 963.22 1525.29 972.72 1535.94 988.04 C 1545.87 1002.19 1548.77 1020.07 1547.80 1037.03 C 1547.40 1054.27 1541.09 1071.56 1529.28 1084.27 C 1517.35 1097.30 1500.95 1105.31 1484.12 1109.96 C 1470.05 1113.75 1455.50 1115.70 1440.94 1115.84 C 1390.26 1115.88 1339.58 1115.89 1288.90 1115.84 C 1288.82 1014.41 1289.01 912.99 1288.80 811.57 M 1354.30 870.27 C 1354.37 891.67 1354.24 913.08 1354.36 934.49 C 1376.56 934.35 1398.76 934.52 1420.96 934.40 C 1431.03 933.86 1441.46 932.43 1450.36 927.35 C 1457.39 923.37 1462.73 916.24 1463.78 908.14 C 1465.26 899.01 1463.69 888.76 1457.02 881.93 C 1449.00 873.67 1437.04 871.03 1425.95 870.37 C 1402.07 870.17 1378.18 870.37 1354.30 870.27 M 1354.29 990.41 C 1354.32 1012.64 1354.35 1034.89 1354.27 1057.13 C 1375.50 1057.33 1396.74 1057.15 1417.98 1057.21 C 1428.58 1057.08 1439.29 1057.80 1449.79 1055.91 C 1458.99 1054.43 1468.48 1050.97 1474.69 1043.71 C 1480.95 1036.44 1482.26 1026.10 1480.69 1016.93 C 1479.44 1009.15 1474.55 1002.16 1467.79 998.15 C 1458.62 992.57 1447.64 990.81 1437.06 990.45 C 1409.47 990.37 1381.88 990.45 1354.29 990.41 Z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.0656 8.00389L11.25 7.99875H18.75C20.483 7.99875 21.8992 9.3552 21.9949 11.0643L22 11.2487V18.7487C22 20.4818 20.6435 21.898 18.9344 21.9936L18.75 21.9987H11.25C9.51697 21.9987 8.10075 20.6423 8.00515 18.9332L8 18.7487V11.2487C8 9.51571 9.35646 8.0995 11.0656 8.00389ZM18.75 9.49875H11.25C10.3318 9.49875 9.57881 10.2059 9.5058 11.1052L9.5 11.2487V18.7487C9.5 19.6669 10.2071 20.4199 11.1065 20.4929L11.25 20.4987H18.75C19.6682 20.4987 20.4212 19.7916 20.4942 18.8923L20.5 18.7487V11.2487C20.5 10.2822 19.7165 9.49875 18.75 9.49875ZM15 11C15.4142 11 15.75 11.3358 15.75 11.75V14.248L18.25 14.2487C18.6642 14.2487 19 14.5845 19 14.9987C19 15.413 18.6642 15.7487 18.25 15.7487L15.75 15.748V18.25C15.75 18.6642 15.4142 19 15 19C14.5858 19 14.25 18.6642 14.25 18.25V15.748L11.75 15.7487C11.3358 15.7487 11 15.413 11 14.9987C11 14.5845 11.3358 14.2487 11.75 14.2487L14.25 14.248V11.75C14.25 11.3358 14.5858 11 15 11ZM15.5818 4.23284L15.6345 4.40964L16.327 6.998H14.774L14.1856 4.79787C13.9355 3.86431 12.9759 3.31029 12.0423 3.56044L4.79787 5.50158C3.91344 5.73856 3.36966 6.61227 3.52756 7.49737L3.56044 7.64488L5.50158 14.8893C5.69372 15.6064 6.30445 16.0996 7.00045 16.1764L7.00056 17.6816C5.69932 17.6051 4.52962 16.7445 4.10539 15.4544L4.05269 15.2776L2.11155 8.03311C1.66301 6.35913 2.6067 4.6401 4.23284 4.10539L4.40964 4.05269L11.6541 2.11155C13.3281 1.66301 15.0471 2.6067 15.5818 4.23284Z" fill="#212121"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M960 160h-291.2a160 160 0 0 0-313.6 0H64a32 32 0 0 0 0 64h896a32 32 0 0 0 0-64zM512 96a96 96 0 0 1 90.24 64h-180.48A96 96 0 0 1 512 96zM844.16 290.56a32 32 0 0 0-34.88 6.72A32 32 0 0 0 800 320a32 32 0 1 0 64 0 33.6 33.6 0 0 0-9.28-22.72 32 32 0 0 0-10.56-6.72zM832 416a32 32 0 0 0-32 32v96a32 32 0 0 0 64 0v-96a32 32 0 0 0-32-32zM832 640a32 32 0 0 0-32 32v224a32 32 0 0 1-32 32H256a32 32 0 0 1-32-32V320a32 32 0 0 0-64 0v576a96 96 0 0 0 96 96h512a96 96 0 0 0 96-96v-224a32 32 0 0 0-32-32z" fill="#231815" /><path d="M384 768V352a32 32 0 0 0-64 0v416a32 32 0 0 0 64 0zM544 768V352a32 32 0 0 0-64 0v416a32 32 0 0 0 64 0zM704 768V352a32 32 0 0 0-64 0v416a32 32 0 0 0 64 0z" fill="#231815" /></svg>

Before

Width:  |  Height:  |  Size: 946 B

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M24 12a5 5 0 0 1-5 5h-2v-1h2a3.99 3.99 0 0 0 .623-7.934l-.79-.124-.052-.798a5.293 5.293 0 0 0-10.214-1.57L8.17 6.59l-.977-.483A2.277 2.277 0 0 0 6.19 5.87a2.18 2.18 0 0 0-1.167.339 2.206 2.206 0 0 0-.98 1.395l-.113.505-.476.2A4 4 0 0 0 5 16h3v1H5a5 5 0 0 1-1.934-9.611 3.21 3.21 0 0 1 1.422-2.025 3.17 3.17 0 0 1 1.702-.493 3.268 3.268 0 0 1 1.446.34 6.293 6.293 0 0 1 12.143 1.867A4.988 4.988 0 0 1 24 12zm-11-1h-1v10.292l-2.646-2.646-.707.707 3.854 3.854 3.853-3.852-.707-.707L13 21.294z"/><path fill="none" d="M0 0h24v24H0z"/></svg>

Before

Width:  |  Height:  |  Size: 752 B

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.2799 6.40005L11.7399 15.94C10.7899 16.89 7.96987 17.33 7.33987 16.7C6.70987 16.07 7.13987 13.25 8.08987 12.3L17.6399 2.75002C17.8754 2.49308 18.1605 2.28654 18.4781 2.14284C18.7956 1.99914 19.139 1.92124 19.4875 1.9139C19.8359 1.90657 20.1823 1.96991 20.5056 2.10012C20.8289 2.23033 21.1225 2.42473 21.3686 2.67153C21.6147 2.91833 21.8083 3.21243 21.9376 3.53609C22.0669 3.85976 22.1294 4.20626 22.1211 4.55471C22.1128 4.90316 22.0339 5.24635 21.8894 5.5635C21.7448 5.88065 21.5375 6.16524 21.2799 6.40005V6.40005Z" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 4H6C4.93913 4 3.92178 4.42142 3.17163 5.17157C2.42149 5.92172 2 6.93913 2 8V18C2 19.0609 2.42149 20.0783 3.17163 20.8284C3.92178 21.5786 4.93913 22 6 22H17C19.21 22 20 20.2 20 18V13" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>library</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Combined-Shape" fill="#000000" transform="translate(42.666667, 85.333333)">
<path d="M3.55271368e-14,298.666667 L426.666667,298.666667 L426.666667,341.333333 L3.55271368e-14,341.333333 L3.55271368e-14,298.666667 Z M42.6666667,1.42108547e-14 L106.666667,1.42108547e-14 L106.666667,277.333333 L42.6666667,277.333333 L42.6666667,1.42108547e-14 Z M128,21.3333333 L192,21.3333333 L192,277.333333 L128,277.333333 L128,21.3333333 Z M288.933802,36.9522088 L351.961498,25.8387255 L399.909944,277.333333 L330.641827,277.70319 L288.933802,36.9522088 Z M213.333333,21.3333333 L277.333333,21.3333333 L277.333333,277.333333 L213.333333,277.333333 L213.333333,21.3333333 Z">
</path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 3V8M3 8H8M3 8L6 5.29168C7.59227 3.86656 9.69494 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.71683 21 4.13247 18.008 3.22302 14" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -2,12 +2,11 @@
<html>
<head>
<meta charset="utf-8" />
<script src="/api/v1/System/VersionFile"></script>
<link type="text/css" rel="stylesheet" dat-href="/styles/style.css" />
<link type="text/css" rel="stylesheet" href="/styles/style.css" />
<script src="/scripts/jquery-3.6.0.min.js"></script>
<script src="/scripts/moment.js"></script>
<link href="/styles/select2.min.css" rel="stylesheet" />
<link href="/styles/dropzone.min.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="/styles/dropzone.min.css" type="text/css" />
<script src="/scripts/jquery.lazy.min.js"></script>
<script src="/scripts/jquery.lazy.plugins.min.js"></script>
<script src="/scripts/select2.min.js"></script>
@@ -20,54 +19,22 @@
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<title>Gaseous Games</title>
<script type="text/javascript">
var head = document.getElementsByTagName('head')[0];
// update links
var headLinks = document.getElementsByTagName('link');
for (var i = 0; i < headLinks.length; i++) {
if (headLinks[i].getAttribute('dat-href') && headLinks[i].rel == "stylesheet") {
var newLink = document.createElement('link');
newLink.rel = "stylesheet";
newLink.href = headLinks[i].getAttribute('dat-href') + '?v=' + AppVersion;
newLink.type = "text/css";
headLinks[i].parentElement.removeChild(headLinks[i]);
head.appendChild(newLink);
}
}
</script>
</head>
<body>
<div id="banner_icon" onclick="window.location.href = '/index.html';">
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
</div>
<div id="banner_header">
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';" class="banner_button">
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" class="banner_button_image" />
<span id="banner_system_label">Settings</span>
<div id="banner_header_label">Gaseous Games</div>
</div>
<div id="banner_upload" onclick="showDialog('upload');" class="banner_button">
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" class="banner_button_image" />
<span id="banner_upload_label">Upload</span>
<div id="banner_upload" onclick="showDialog('upload');">
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" />
<span id="banner_upload_label">Upload Games</span>
</div>
<div id="banner_collections" onclick="window.location.href = '/index.html?page=collections';" class="banner_button">
<img src="/images/collections.svg" alt="Collections" title="Collections" id="banner_collections_image" class="banner_button_image" />
<span id="banner_collections_label">Collections</span>
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';">
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" />
</div>
<div id="banner_library" onclick="window.location.href = '/index.html';" class="banner_button">
<img src="/images/library.svg" alt="Library" title="Library" id="banner_library_image" class="banner_button_image" />
<span id="banner_library_label">Library</span>
</div>
<div id="banner_header_label" onclick="window.location.href = '/index.html';">Gaseous Games</div>
</div>
<div id="content">
</div>
@@ -97,7 +64,6 @@
<script type="text/javascript">var modalVariables = null;
$(document).ready(function () {
var myParam = getQueryString('page', 'string');
@@ -105,8 +71,7 @@
myParam = 'home';
}
$('#content').load('/pages/' + myParam + '.html?v=' + AppVersion);
});
</script>
$('#content').load('/pages/' + myParam + '.html');
});</script>
</body>
</html>

View File

@@ -23,8 +23,5 @@
EJS_DEBUG_XX = false;
EJS_startOnLoaded = false;
EJS_backgroundImage = emuBackground;
EJS_backgroundBlur = true;
</script>
<script src='/emulators/EmulatorJS/data/loader.js'></script>

View File

@@ -1,80 +0,0 @@
<div id="bgImage" style="background-image: url('/images/CollectionsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="gamepage">
<div id="gametitle">
<h1 id="gametitle_label">Collections</h1>
</div>
<button id="collection_new" style="float: right;" onclick="showDialog('collectionedit');">New Collection</button>
<div id="collection_table_location">
</div>
</div>
<div id="settings_photocredit">
Wallpaper by <a href="https://wallpapercave.com/u/andrea16" class="romlink">andrea16</a> / <a href="https://wallpapercave.com/w/wp5206111" class="romlink">Wallpaper Cave</a>
</div>
<script type="text/javascript">
GetCollections();
function GetCollections() {
ajaxCall('/api/v1/Collections', 'GET', function (result) {
if (result) {
var targetDiv = document.getElementById('collection_table_location');
targetDiv.innerHTML = '';
var newTable = document.createElement('table');
newTable.id = 'romtable';
newTable.className = 'romtable';
newTable.setAttribute('cellspacing', 0);
newTable.appendChild(createTableRow(true, [ 'Name', 'Description', 'Download Status', 'Size', '' ]));
for (var i = 0; i < result.length; i++) {
var statusText = result[i].buildStatus;
var downloadLink = '';
var packageSize = '-';
switch (result[i].buildStatus) {
case 'NoStatus':
statusText = '-';
break;
case "WaitingForBuild":
statusText = 'Build pending';
break;
case "Building":
statusText = 'Building';
break;
case "Completed":
statusText = 'Available';
downloadLink = '<a href="/api/v1/Collections/' + result[i].id + '/Roms/Zip" class="romlink"><img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" /></a>';
packageSize = formatBytes(result[i].collectionBuiltSizeBytes);
break;
case "Failed":
statusText = 'Build error';
break;
default:
statusText = result[i].buildStatus;
break;
}
var editButton = '<a href="#" onclick="showDialog(\'collectionedit\', ' + result[i].id + ');" class="romlink"><img src="/images/edit.svg" class="banner_button_image" alt="Edit" title="Edit" /></a>';
var deleteButton = '<a href="#" onclick="showSubDialog(\'collectiondelete\', ' + result[i].id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
var newRow = [
result[i].name,
result[i].description,
statusText,
packageSize,
'<div style="text-align: right;">' + downloadLink + editButton + deleteButton + '</div>'
];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
}
targetDiv.appendChild(newTable);
}
});
}
</script>

View File

@@ -1,27 +0,0 @@
<p>Are you sure you want to delete this collection?</p>
<p><strong>Warning:</strong> This cannot be undone!</p>
<div style="width: 100%; text-align: center;">
<div style="display: inline-block; margin-right: 20px;">
<button class="redbutton" value="Delete" onclick="deleteCollection();">Delete</button>
</div>
<div style="display: inline-block; margin-left: 20px;">
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
</div>
</div>
<script type="text/javascript">
function deleteCollection() {
ajaxCall(
'/api/v1/Collections/' + subModalVariables,
'DELETE',
function (result) {
GetCollections();
closeSubDialog();
},
function (error) {
GetCollections();
closeSubDialog();
}
);
}
</script>

View File

@@ -1,494 +0,0 @@
<input id="collection_name" type="text" placeholder="Collection Name" style="width: 80%; font-size: 2em;" />
<input id="collection_description" type="text" placeholder="Description" style="width: 80%; margin-top: 5px;" />
<div style="position: absolute; top: 90px; right: 5px; left: 10px; bottom: 5px;">
<div style="position: relative; width: 100%; height: 100%;">
<table style="position: absolute; top: 0px; left: 0px; bottom: 0px; width: 40%;">
<tr>
<td>
<h3>Filter</h3>
</td>
</tr>
</table>
<div id="collection_filter_box" style="position: absolute; top: 40px; left: 0px; bottom: 5px; width: 40%; max-width: 40%; overflow-x: scroll;">
<table style="width: 100%;">
<tr>
<th style="width: 25%;">Platforms</th>
<td><select id="collection_platform" style="width: 100%;" multiple="multiple"></select></td>
</tr>
<tr>
<th>Genres</th>
<td><select id="collection_genres" style="width: 100%;" multiple="multiple"></select></td>
</tr>
<tr>
<th>Players</th>
<td><select id="collection_players" style="width: 100%;" multiple="multiple"></select></td>
</tr>
<tr>
<th>Player Perspectives</th>
<td><select id="collection_playerperspectives" style="width: 100%;" multiple="multiple"></select></td>
</tr>
<tr>
<th>Themes</th>
<td><select id="collection_themes" style="width: 100%;" multiple="multiple"></select></td>
</tr>
<tr>
<th>Rating</th>
<td>
<input id="collection_userrating_min" type="number" placeholder="0" min="0" max="100">
<input id="collection_userrating_max" type="number" placeholder="100" min="0" max="100">
</td>
</tr>
<tr>
<td colspan="2">
<h3>Options</h3>
</td>
</tr>
<tr>
<th>Maximum ROMs per platform</th>
<td><input id="collection_maxroms" type="number" placeholder="0"></td>
</tr>
<tr>
<th>Maximum size per platform (bytes)</th>
<td><input id="collection_maxplatformsize" type="number" placeholder="0" step="1048576" oninput="DisplayFormattedBytes('collection_maxplatformsize', 'maxplatformsize_label');"><span id="maxplatformsize_label" style="margin-left: 10px;"></span></td>
</tr>
<tr>
<th>Maximum collection size (bytes)</th>
<td><input id="collection_maxcollectionsize" type="number" placeholder="0" step="1048576" oninput="DisplayFormattedBytes('collection_maxcollectionsize', 'maxcollectionsize_label');"><span id="maxcollectionsize_label" style="margin-left: 10px;"></span></td></td>
</tr>
</table>
</div>
<table style="position: absolute; top: 0px; right: 0px; bottom: 0px; width: 60%;">
<tr>
<td>
<h3>Collection</h3>
</td>
</tr>
</table>
<div id="collectionedit_previewbox" style="position: absolute; top: 40px; right: 0px; bottom: 60px; width: 60%; overflow-x: scroll;">
<div id="collectionedit_previewbox_content" style="margin: 5px;">
</div>
</div>
<div id="collectionedit_previewbox_size" style="position: absolute; right: 10px; bottom: 30px; width: 60%; height: 20px; text-align: right;">
</div>
<div id="collectionedit_previewbox_controls" style="position: absolute; right: 10px; bottom: 0px; width: 60%; height: 25px; text-align: right;">
<button id="collectionedit_preview" onclick="GetPreview();">Preview</button>
<button id="collectionedit_cancel" onclick="closeDialog();">Cancel</button>
<button id="collectionedit_ok" onclick="SaveCollection();">Ok</button>
</div>
</div>
</div>
<script type="text/javascript">
var headerToRemove = document.getElementById('modal-heading');
if (headerToRemove) {
headerToRemove.parentNode.removeChild(headerToRemove);
}
var modalContent = document.getElementsByClassName('modal-content');
if (!modalContent[0].classList.contains('collections_modal')) {
modalContent[0].classList.add('collections_modal');
}
// setup dropdowns
$('#collection_platform').select2({
ajax: {
url: '/api/v1/Filter',
processResults: function (data) {
var filter = data['platforms'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
text: filter[i].name
});
}
return {
results: arr
};
}
}
});
$('#collection_genres').select2({
ajax: {
url: '/api/v1/Filter',
processResults: function (data) {
var filter = data['genres'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
text: filter[i].name
});
}
return {
results: arr
};
}
}
});
$('#collection_players').select2({
ajax: {
url: '/api/v1/Filter',
processResults: function (data) {
var filter = data['gamemodes'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
text: filter[i].name
});
}
return {
results: arr
};
}
}
});
$('#collection_playerperspectives').select2({
ajax: {
url: '/api/v1/Filter',
processResults: function (data) {
var filter = data['playerperspectives'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
text: filter[i].name
});
}
return {
results: arr
};
}
}
});
$('#collection_themes').select2({
ajax: {
url: '/api/v1/Filter',
processResults: function (data) {
var filter = data['themes'];
var arr = [];
for (var i = 0; i < filter.length; i++) {
arr.push({
id: filter[i].id,
text: filter[i].name
});
}
return {
results: arr
};
}
}
});
if (modalVariables) {
// edit mode
ajaxCall(
'/api/v1/Collections/' + modalVariables,
'GET',
function(result) {
if (result.name) { document.getElementById('collection_name').value = result.name; }
if (result.description) { document.getElementById('collection_description').value = result.description; }
if (result.minimumRating != -1) { document.getElementById('collection_userrating_min').value = result.minimumRating; }
if (result.maximumRating != -1) { document.getElementById('collection_userrating_max').value = result.maximumRating; }
if (result.maximumRomsPerPlatform != -1) { document.getElementById('collection_maxroms').value = result.maximumRomsPerPlatform; }
if (result.maximumBytesPerPlatform != -1) { document.getElementById('collection_maxplatformsize').value = result.maximumBytesPerPlatform; }
if (result.maximumCollectionSizeInBytes != -1) { document.getElementById('collection_maxcollectionsize').value = result.maximumCollectionSizeInBytes; }
// fill select2 controls
$.ajax(
{
url: '/api/v1/Filter',
type: 'GET',
indexValue: result,
dataType: 'json',
contentType: 'application/json',
success: function (data) {
// platforms
for (var i = 0; i < data.platforms.length; i++) {
if (this.indexValue.platforms.includes(data.platforms[i].id)) {
var newOption = new Option(data.platforms[i].name, data.platforms[i].id, true, true);
$('#collection_platform').append(newOption).trigger('change');
}
}
// genres
for (var i = 0; i < data.genres.length; i++) {
if (this.indexValue.genres.includes(data.genres[i].id)) {
var newOption = new Option(data.genres[i].name, data.genres[i].id, true, true);
$('#collection_genres').append(newOption).trigger('change');
}
}
// players
for (var i = 0; i < data.gamemodes.length; i++) {
if (this.indexValue.players.includes(data.gamemodes[i].id)) {
var newOption = new Option(data.gamemodes[i].name, data.gamemodes[i].id, true, true);
$('#collection_players').append(newOption).trigger('change');
}
}
// playerperspectives
for (var i = 0; i < data.playerperspectives.length; i++) {
if (this.indexValue.playerPerspectives.includes(data.playerperspectives[i].id)) {
var newOption = new Option(data.playerperspectives[i].name, data.playerperspectives[i].id, true, true);
$('#collection_playerperspectives').append(newOption).trigger('change');
}
}
// themes
for (var i = 0; i < data.themes.length; i++) {
if (this.indexValue.themes.includes(data.themes[i].id)) {
var newOption = new Option(data.themes[i].name, data.themes[i].id, true, true);
$('#collection_themes').append(newOption).trigger('change');
}
}
// generate preview
GetPreview();
},
error: function (error) {
console.log(`Error ${error}`);
}
}
);
}
);
} else {
// new mode
}
function SaveCollection() {
var item = GenerateCollectionItem();
if (modalVariables) {
// existing object - save over the top
item.id = modalVariables;
ajaxCall(
'/api/v1/Collections/' + modalVariables,
'PATCH',
function(result) {
location.reload();
},
function(error) {
alert(error);
},
JSON.stringify(item)
);
} else {
// new object
ajaxCall(
'/api/v1/Collections',
'POST',
function(result) {
location.reload();
},
function(error) {
alert(error);
},
JSON.stringify(item)
);
}
}
function GenerateCollectionItem() {
var platforms = GetDropDownIds('#collection_platform');
var genres = GetDropDownIds('#collection_genres');
var players = GetDropDownIds('#collection_players');
var playerperspectives = GetDropDownIds('#collection_playerperspectives');
var themes = GetDropDownIds('#collection_themes');
var item = {
"name": document.getElementById('collection_name').value,
"description": document.getElementById('collection_description').value,
"platforms": platforms,
"genres": genres,
"players": players,
"playerPerspectives": playerperspectives,
"themes": themes,
"minimumRating": GetNumberFieldValue('collection_userrating_min'),
"maximumRating": GetNumberFieldValue('collection_userrating_max'),
"maximumRomsPerPlatform": GetNumberFieldValue('collection_maxroms'),
"maximumBytesPerPlatform": GetNumberFieldValue('collection_maxplatformsize'),
"maximumCollectionSizeInBytes": GetNumberFieldValue('collection_maxcollectionsize')
}
return item;
}
function GetPreview() {
var item = GenerateCollectionItem();
console.log(JSON.stringify(item));
ajaxCall(
'/api/v1/Collections/Preview',
'POST',
function(result) {
DisplayPreview(result, 'collectionedit_previewbox_content');
},
function(error) {
console.log(JSON.stringify(error));
},
JSON.stringify(item)
);
}
function GetDropDownIds(objectName) {
var obj = $(objectName).select2('data');
if (obj.length > 0) {
var ids = [];
for (var i = 0; i < obj.length; i++) {
ids.push(obj[i].id);
}
return ids;
} else {
return [];
}
}
function GetNumberFieldValue(objectName) {
var obj = document.getElementById(objectName);
var objVal = obj.value;
if (objVal) {
return objVal;
} else {
return -1;
}
}
function DisplayPreview(data, targetDiv) {
var container = document.getElementById(targetDiv);
container.innerHTML = '';
if (data.collection) {
var collectionTable = document.createElement('table');
collectionTable.setAttribute('cellspacing', 0);
collectionTable.style.width = '100%';
// loop the platforms
for (var p = 0; p < data.collection.length; p++) {
var platformItem = data.collection[p];
var platformLabelRow = document.createElement('tr');
var platformLabelCell = document.createElement('th');
platformLabelCell.setAttribute('colspan', 2);
platformLabelCell.className = 'collections_preview_platform_header';
platformLabelCell.innerHTML = '<span style="float: right;">' + formatBytes(platformItem.romSize) + '</span>' + platformItem.name;
platformLabelRow.appendChild(platformLabelCell);
collectionTable.appendChild(platformLabelRow);
var bgaltindex = 0;
// loop the games
for (var g = 0; g < platformItem.games.length; g++) {
var gameItem = platformItem.games[g];
var bgalt = '';
if (bgaltindex == 1) {
bgaltindex = 0;
bgalt = 'bgalt1';
} else {
bgaltindex = 1;
bgalt = 'bgalt0';
}
var gameItemRow = document.createElement('tr');
gameItemRow.className = bgalt;
// game title
var gameTitleCell = document.createElement('th');
gameTitleCell.setAttribute('colspan', 2);
gameTitleCell.className = 'collections_preview_gametitlecell';
gameTitleCell.innerHTML = gameItem.name;
gameItemRow.appendChild(gameTitleCell);
// game cover
var gameDetailRow = document.createElement('tr');
gameDetailRow.className = bgalt;
var gameCoverCell = document.createElement('td');
gameCoverCell.className = 'collections_preview_gamecovercell';
var gameImage = document.createElement('img');
gameImage.className = 'game_tile_image game_tile_image_small';
if (gameItem.cover) {
gameImage.src = '/api/v1/Games/' + gameItem.id + '/cover/image';
} else {
gameImage.src = '/images/unknowngame.png';
gameImage.className = 'game_tile_image game_tile_image_small unknown';
}
gameCoverCell.appendChild(gameImage);
gameDetailRow.appendChild(gameCoverCell);
// game detail
var gameDetailCell = document.createElement('td');
gameDetailCell.className = 'collections_preview_gamedetailcell';
// loop roms
for (var r = 0; r < gameItem.roms.length; r++) {
var romItem = gameItem.roms[r];
var romLabel = document.createElement('p');
romLabel.innerHTML = romItem.name;
gameDetailCell.appendChild(romLabel);
}
gameDetailRow.appendChild(gameDetailCell);
collectionTable.appendChild(gameItemRow);
collectionTable.appendChild(gameDetailRow);
}
}
container.appendChild(collectionTable);
var collectionSize = document.getElementById('collectionedit_previewbox_size');
collectionSize.innerHTML = "Collection size: " + formatBytes(data.collectionProjectedSizeBytes);
}
}
function DisplayFormattedBytes(inputElement, labelElement) {
var src = document.getElementById(inputElement);
var label = document.getElementById(labelElement);
if (src.value) {
label.innerHTML = formatBytes(src.value);
} else {
label.innerHTML = '';
}
}
</script>

View File

@@ -55,7 +55,7 @@
subModalVariables = modalVariables;
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html?v=' + AppVersion);
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html');
}
function closeSubDialog() {

View File

@@ -12,7 +12,6 @@
var artworksPosition = 0;
var emuBios = '';
var emuBackground = '';
ajaxCall('/api/v1/Games/' + gameId, 'GET', function (result) {
gameData = result;
@@ -29,10 +28,6 @@
bg.setAttribute('style', 'background-image: url("/api/v1/Games/' + gameId + '/cover/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
}
}
if (result.cover) {
emuBackground = '/api/v1/Games/' + gameId + '/cover/image';
}
});
ajaxCall('/api/v1/Bios/' + platformId, 'GET', function (result) {
@@ -44,7 +39,7 @@
switch (getQueryString('engine', 'string')) {
case 'EmulatorJS':
$('#emulator').load('/pages/EmulatorJS.html?v=' + AppVersion);
$('#emulator').load('/pages/EmulatorJS.html');
break;
}
});

View File

@@ -17,19 +17,11 @@
<div id="gamepage">
<div id="gametitle">
<div id="gametitle_criticrating">
<div>
<span id="gametitle_criticrating_value"></span>
<span id="gametitle_criticrating_label"></span>
</div>
</div>
<h1 id="gametitle_label"></h1>
<p id="gamedeveloper_label"></p>
<p id="gametitle_alts">
<span>Also known as: </span><span id="gametitle_alts_label"></span>
</p>
<p id="gamedeveloper_label"></p>
</div>
@@ -80,10 +72,10 @@
</div>
</div>
</div>
</div>
<script type="text/javascript">
var gameId = getQueryString('id', 'int');
</div>
<script type="text/javascript">var gameId = getQueryString('id', 'int');
var gameData;
var artworks = null;
var artworksPosition = 0;
@@ -98,17 +90,6 @@
var gameTitleLabel = document.getElementById('gametitle_label');
gameTitleLabel.innerHTML = result.name;
// get critic rating
if (gameData.totalRating) {
var criticscoreval = document.getElementById('gametitle_criticrating_value');
criticscoreval.innerHTML = Math.floor(gameData.totalRating) + '%';
if (gameData.totalRatingCount) {
var criticscorelabel = document.getElementById('gametitle_criticrating_label');
criticscorelabel.innerHTML = '<img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 13px; margin-bottom: -5px;" /><span style="font-size: 10px;"> User Rating<br />' + "based on " + gameData.totalRatingCount + " votes</span>"
}
}
// get alt name
var gameTitleAltLabel = document.getElementById('gametitle_alts');
if (result.alternativeNames) {
@@ -155,12 +136,9 @@
artworksPosition = startPos;
rotateBackground();
} else {
var bg = document.getElementById('bgImage');
if (result.cover) {
var bg = document.getElementById('bgImage');
bg.setAttribute('style', 'background-image: url("/api/v1/Games/' + gameId + '/cover/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
} else {
var randomInt = randomIntFromInterval(1, 3);
bg.setAttribute('style', 'background-image: url("/images/gamebg' + randomInt + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
}
}
@@ -329,8 +307,6 @@
gameScreenshots_vGallery.appendChild(itemsArr[i]);
}
selectScreenshot(0);
}, function(error) {
selectScreenshot(0);
});
} else {
@@ -582,7 +558,6 @@
var remapCallCounter = 0;
var remapCallCounterMax = 0;
function remapTitles() {
var fixplatform = $('#rom_edit_fixplatform').select2('data');
var fixgame = $('#rom_edit_fixgame').select2('data');
@@ -603,6 +578,7 @@
if (rom_checks[i].checked == true) {
var romId = rom_checks[i].getAttribute('data-romid');
remapCallCounter += 1;
ajaxCall('/api/v1/Games/' + gameId + '/roms/' + romId + '?NewPlatformId=' + fixplatform[0].id + '&NewGameId=' + fixgame[0].id, 'PATCH', function (result) {
remapTitlesCallback();
}, function (result) {
@@ -643,6 +619,8 @@
var rom_checks = document.getElementsByName('rom_checkbox');
for (var i = 0; i < rom_checks.length; i++) {
if (rom_checks[i].checked == true) {
remapCallCounterMax += 1;
var romId = rom_checks[i].getAttribute('data-romid');
remapCallCounter += 1;
ajaxCall('/api/v1/Games/' + gameId + '/roms/' + romId, 'DELETE', function (result) {

View File

@@ -1,8 +1,4 @@
<div id="bgImage" style="background-image: url('/images/librarybg.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
<div id="bgImage_Opacity"></div>
</div>
<div id="games_home">
<div id="games_home">
<div id="games_filter"></div>
<div id="games_library"></div>
</div>
@@ -11,7 +7,10 @@
ajaxCall('/api/v1/Filter', 'GET', function (result) {
var filterElement = document.getElementById('games_filter');
formatFilterPanel(filterElement, result);
});
executeFilter();
ajaxCall('/api/v1/Games', 'GET', function (result) {
var gameElement = document.getElementById('games_library');
formatGamesPanel(gameElement, result);
});
</script>

View File

@@ -42,6 +42,6 @@
}
}
$('#properties_bodypanel').load('/pages/settings/' + TabName + '.html?v=' + AppVersion);
$('#properties_bodypanel').load('/pages/settings/' + TabName + '.html');
}
</script>

View File

@@ -2,7 +2,7 @@
<h1 id="gametitle_label">About Gaseous</h1>
</div>
<table style="width: 100%;">
<table>
<tr>
<th>Home Page</th>
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
@@ -11,44 +11,4 @@
<th>Bugs and Feature Requests</th>
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
</tr>
<tr>
<th>Server Version</th>
<td id="settings_appversion"></td>
</tr>
<tr>
<td colspan="2">
<h3>Data Sources</h2>
<h4>Game data</h4>
</td>
</tr>
<tr>
<td>
<a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a>
</td>
<td>
The Internet Game Database
</td>
</tr>
<tr>
<td colspan="2">
<h4>Signature data sources</h4>
</td>
</tr>
<tr>
<td>
<a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif" style="height: 36px;" /></a>
</td>
<td>
The Old School Emulation Center
</td>
</tr>
</table>
<script type="text/javascript">
ajaxCall('/api/v1/System/Version', 'GET', function (result) {
if (result) {
var versionBox = document.getElementById('settings_appversion');
versionBox.innerHTML = result;
}
});
</script>

View File

@@ -51,9 +51,6 @@
case 'LibraryScan':
itemTypeName = "Library scan";
break;
case 'CollectionCompiler':
itemTypeName = "Compress collections";
break;
default:
itemTypeName = result[i].itemType;
break;
@@ -81,7 +78,7 @@
}
var startButton = '';
if (result[i].allowManualStart == true && result[i].itemState != "Running") {
if (result[i].itemState != "Running") {
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
}

View File

@@ -7,10 +7,6 @@
var containerPanelSearch = document.createElement('div');
containerPanelSearch.className = 'filter_panel_box';
var containerPanelSearchField = document.createElement('input');
var searchCookie = getCookie('filter_panel_search');
if (searchCookie) {
containerPanelSearchField.value = searchCookie;
}
containerPanelSearchField.id = 'filter_panel_search';
containerPanelSearchField.type = 'text';
containerPanelSearchField.placeholder = 'Search';
@@ -19,136 +15,45 @@
panel.appendChild(containerPanelSearch);
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating'));
var containerPanelUserRating = document.createElement('div');
containerPanelUserRating.className = 'filter_panel_box';
var containerPanelUserRatingMinField = document.createElement('input');
var minRatingCookie = getCookie('filter_panel_userrating_min');
if (minRatingCookie) {
containerPanelUserRatingMinField.value = minRatingCookie;
}
containerPanelUserRatingMinField.id = 'filter_panel_userrating_min';
containerPanelUserRatingMinField.type = 'number';
containerPanelUserRatingMinField.placeholder = '0';
containerPanelUserRatingMinField.setAttribute('onchange', 'executeFilterDelayed();');
containerPanelUserRatingMinField.setAttribute('onkeydown', 'executeFilterDelayed();');
containerPanelUserRatingMinField.setAttribute('min', '0');
containerPanelUserRatingMinField.setAttribute('max', '100');
containerPanelUserRating.appendChild(containerPanelUserRatingMinField);
var containerPanelUserRatingMaxField = document.createElement('input');
var maxRatingCookie = getCookie('filter_panel_userrating_max');
if (maxRatingCookie) {
containerPanelUserRatingMaxField.value = maxRatingCookie;
}
containerPanelUserRatingMaxField.id = 'filter_panel_userrating_max';
containerPanelUserRatingMaxField.type = 'number';
containerPanelUserRatingMaxField.placeholder = '100';
containerPanelUserRatingMaxField.setAttribute('onchange', 'executeFilterDelayed();');
containerPanelUserRatingMaxField.setAttribute('onkeydown', 'executeFilterDelayed();');
containerPanelUserRatingMaxField.setAttribute('min', '0');
containerPanelUserRatingMaxField.setAttribute('max', '100');
containerPanelUserRating.appendChild(containerPanelUserRatingMaxField);
panel.appendChild(containerPanelUserRating);
if (result.platforms) {
buildFilterPanel(panel, 'platform', 'Platforms', result.platforms, true, true);
}
panel.appendChild(buildFilterPanelHeader('platforms', 'Platforms'));
if (result.genres) {
buildFilterPanel(panel, 'genre', 'Genres', result.genres, true, false);
}
if (result.gamemodes) {
buildFilterPanel(panel, 'gamemode', 'Players', result.gamemodes, true, false);
}
if (result.playerperspectives) {
buildFilterPanel(panel, 'playerperspective', 'Player Perspectives', result.playerperspectives, true, false);
}
if (result.themes) {
buildFilterPanel(panel, 'theme', 'Themes', result.themes, true, false);
var containerPanelPlatform = document.createElement('div');
containerPanelPlatform.className = 'filter_panel_box';
for (var i = 0; i < result.platforms.length; i++) {
containerPanelPlatform.appendChild(buildFilterPanelItem('platforms', result.platforms[i].id, result.platforms[i].name));
}
panel.appendChild(containerPanelPlatform);
targetElement.appendChild(panel);
}
function buildFilterPanel(targetElement, headerString, friendlyHeaderString, valueList, showToggle, initialDisplay) {
if (showToggle == false) { initialDisplay = true; }
var displayCookie = getCookie('filter_panel_box_' + headerString);
if (displayCookie) {
initialDisplay = (displayCookie === 'true');
console.log(displayCookie);
}
targetElement.appendChild(buildFilterPanelHeader(headerString, friendlyHeaderString, showToggle, initialDisplay));
if (result.genres) {
panel.appendChild(buildFilterPanelHeader('genres', 'Genres'));
var containerPanel = document.createElement('div');
containerPanel.className = 'filter_panel_box';
containerPanel.id = 'filter_panel_box_' + headerString;
if (initialDisplay == false) {
containerPanel.setAttribute('style', 'display: none;');
var containerPanelGenres = document.createElement('div');
containerPanelGenres.className = 'filter_panel_box';
for (var i = 0; i < result.genres.length; i++) {
containerPanelGenres.appendChild(buildFilterPanelItem('genres', result.genres[i].id, result.genres[i].name));
}
for (var i = 0; i < valueList.length; i++) {
containerPanel.appendChild(buildFilterPanelItem(headerString, valueList[i].id, valueList[i].name));
}
targetElement.appendChild(containerPanel);
panel.appendChild(containerPanelGenres);
targetElement.appendChild(panel);
}
function buildFilterPanelHeader(headerString, friendlyHeaderString, showVisibleToggle, toggleInitialValue) {
var headerToggle = document.createElement('div');
headerToggle.setAttribute('style', 'float: right;');
headerToggle.id = 'filter_panel_header_toggle_' + headerString;
if (toggleInitialValue == true) {
headerToggle.innerHTML = '-';
} else {
headerToggle.innerHTML = '+';
}
var headerLabel = document.createElement('span');
headerLabel.innerHTML = friendlyHeaderString;
function buildFilterPanelHeader(headerString, friendlyHeaderString) {
var header = document.createElement('div');
header.id = 'filter_panel_header_' + headerString;
header.className = 'filter_header';
if (showVisibleToggle == true) {
header.appendChild(headerToggle);
header.setAttribute('onclick', 'toggleFilterPanel("' + headerString + '");');
header.style.cursor = 'pointer';
}
header.appendChild(headerLabel);
header.innerHTML = friendlyHeaderString;
return header;
}
function toggleFilterPanel(panelName) {
var filterPanel = document.getElementById('filter_panel_box_' + panelName);
var filterPanelToggle = document.getElementById('filter_panel_header_toggle_' + panelName);
var cookieVal = '';
if (filterPanel.style.display == 'none') {
filterPanelToggle.innerHTML = '-';
filterPanel.style.display = '';
cookieVal = "true";
} else {
filterPanelToggle.innerHTML = '+';
filterPanel.style.display = 'none';
cookieVal = "false";
}
setCookie("filter_panel_box_" + panelName, cookieVal);
}
function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
var checkCookie = getCookie('filter_panel_item_' + filterType + '_checkbox_' + itemString);
var checkState = false;
if (checkCookie) {
checkState = (checkCookie === 'true');
}
var filterPanelItem = document.createElement('div');
filterPanelItem.id = 'filter_panel_item_' + itemString;
filterPanelItem.className = 'filter_panel_item';
@@ -156,15 +61,12 @@ function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
var filterPanelItemCheckBox = document.createElement('div');
var filterPanelItemCheckBoxItem = document.createElement('input');
filterPanelItemCheckBoxItem.id = 'filter_panel_item_' + filterType + '_checkbox_' + itemString;
filterPanelItemCheckBoxItem.id = 'filter_panel_item_checkbox_' + itemString;
filterPanelItemCheckBoxItem.type = 'checkbox';
filterPanelItemCheckBoxItem.className = 'filter_panel_item_checkbox';
filterPanelItemCheckBoxItem.name = 'filter_' + filterType;
filterPanelItemCheckBoxItem.setAttribute('filter_id', itemString);
filterPanelItemCheckBoxItem.setAttribute('oninput' , 'executeFilter();');
if (checkState == true) {
filterPanelItemCheckBoxItem.checked = true;
}
filterPanelItemCheckBox.appendChild(filterPanelItemCheckBoxItem);
var filterPanelItemLabel = document.createElement('label');
@@ -190,79 +92,33 @@ function executeFilterDelayed() {
function executeFilter() {
// build filter lists
var queries = [];
var platforms = '';
var genres = '';
var searchString = document.getElementById('filter_panel_search');
if (searchString.value.length > 0) {
queries.push('name=' + searchString.value);
var searchString = document.getElementById('filter_panel_search').value;
var platformFilters = document.getElementsByName('filter_platforms');
var genreFilters = document.getElementsByName('filter_genres');
for (var i = 0; i < platformFilters.length; i++) {
if (platformFilters[i].checked) {
if (platforms.length > 0) {
platforms += ',';
}
setCookie(searchString.id, searchString.value);
var minUserRating = 0;
var minUserRatingInput = document.getElementById('filter_panel_userrating_min');
if (minUserRatingInput.value) {
minUserRating = minUserRatingInput.value;
queries.push('minrating=' + minUserRating);
}
setCookie(minUserRatingInput.id, minUserRatingInput.value);
var maxUserRating = 100;
var maxUserRatingInput = document.getElementById('filter_panel_userrating_max');
if (maxUserRatingInput.value) {
maxUserRating = maxUserRatingInput.value;
queries.push('maxrating=' + maxUserRating);
}
setCookie(maxUserRatingInput.id, maxUserRatingInput.value);
queries.push(GetFilterQuery('platform'));
queries.push(GetFilterQuery('genre'));
queries.push(GetFilterQuery('gamemode'));
queries.push(GetFilterQuery('playerperspective'));
queries.push(GetFilterQuery('theme'));
var queryString = '';
for (var i = 0; i < queries.length; i++) {
if (queries[i].length > 0) {
if (queryString.length == 0) {
queryString = '?';
} else {
queryString += '&';
}
queryString += queries[i];
platforms += platformFilters[i].getAttribute('filter_id');
}
}
console.log('Query string = ' + queryString);
for (var i = 0; i < genreFilters.length; i++) {
if (genreFilters[i].checked) {
if (genres.length > 0) {
genres += ',';
}
genres += genreFilters[i].getAttribute('filter_id');
}
}
ajaxCall('/api/v1/Games' + queryString, 'GET', function (result) {
ajaxCall('/api/v1/Games?name=' + searchString + '&platform=' + platforms + '&genre=' + genres, 'GET', function (result) {
var gameElement = document.getElementById('games_library');
formatGamesPanel(gameElement, result);
});
}
function GetFilterQuery(filterName) {
var Filters = document.getElementsByName('filter_' + filterName);
var queryString = '';
for (var i = 0; i < Filters.length; i++) {
if (Filters[i].checked) {
setCookie(Filters[i].id, true);
if (queryString.length > 0) {
queryString += ',';
}
queryString += Filters[i].getAttribute('filter_id');
} else {
setCookie(Filters[i].id, false);
}
}
if (queryString.length > 0) {
queryString = filterName + '=' + queryString;
}
return queryString;
}

View File

@@ -1,4 +1,4 @@
function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
function ajaxCall(endpoint, method, successFunction, errorFunction) {
$.ajax({
// Our sample url to make request
@@ -8,12 +8,6 @@
// Type of Request
type: method,
// data to send to the server
data: body,
dataType: 'json',
contentType: 'application/json',
// Function to call when to
// request is ok
success: function (data) {
@@ -24,7 +18,7 @@
// Error handling
error: function (error) {
console.log(`Error ${JSON.stringify(error)}`);
console.log(`Error ${error}`);
if (errorFunction) {
errorFunction(error);
@@ -57,33 +51,6 @@ function getQueryString(stringName, type) {
}
}
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
if (exdays) {
let expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
} else {
document.cookie = cname + "=" + cvalue + ";path=/";
}
}
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function formatBytes(bytes, decimals = 2) {
if (!+bytes) return '0 Bytes'
@@ -130,19 +97,7 @@ function showDialog(dialogPage, variables) {
modalVariables = variables;
$('#modal-content').load('/pages/dialogs/' + dialogPage + '.html?v=' + AppVersion);
}
function closeDialog() {
// Get the modal
var modal = document.getElementById("myModal");
// Get the modal content
var modalContent = document.getElementById("modal-content");
modal.style.display = "none";
modalContent.innerHTML = "";
modalVariables = null;
$('#modal-content').load('/pages/dialogs/' + dialogPage + '.html');
}
var subModalVariables;
@@ -170,9 +125,9 @@ function showSubDialog(dialogPage, variables) {
subModalVariables = null;
}
subModalVariables = variables;
subModalVariables = modalVariables;
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html?v=' + AppVersion);
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html');
}
function closeSubDialog() {
@@ -260,3 +215,7 @@ function DropDownRenderGameOption(state) {
}
return response;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

View File

@@ -13,10 +13,6 @@
src: url('/fonts/Commodore Pixelized v1.2.ttf');
}
h1 {
margin-bottom: unset;
}
h3 {
border-bottom-style: solid;
/*border-bottom-color: #916b01;*/
@@ -70,9 +66,6 @@ h3 {
border-image: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(251,255,0,1) 16%, rgba(0,255,250,1) 30%, rgba(0,16,255,1) 46%, rgba(250,0,255,1) 62%, rgba(255,0,0,1) 78%, rgba(255,237,0,1) 90%, rgba(20,255,0,1) 100%) 5;
}
#modal-content {
height: 100%;
}
/* The Close Button */
.close {
@@ -112,10 +105,11 @@ h3 {
height: 30px;
}
.banner_button {
background-color: transparent;
float: right;
#banner_upload {
background-color: white;
position: fixed;
top: 0px;
right: 41px;
height: 40px;
align-items: center;
justify-content: center;
@@ -123,24 +117,44 @@ h3 {
padding-right: 10px;
padding-top: 0px;
padding-bottom: 0px;
margin: 0px 0px 0px 0px;
margin: 0px;
display: flex;
color: white;
border-left-color: black;
border-left-width: 1px;
border-left-style: solid;
color: black;
}
.banner_button:hover {
#banner_upload:hover {
cursor: pointer;
background-color: black;
background-color: lightgrey;
}
.banner_button_image {
#banner_cog {
background-color: white;
position: fixed;
top: 0px;
right: 0px;
width: 40px;
height: 40px;
align-items: center;
justify-content: center;
padding: 0px;
margin: 0px;
display: flex;
}
#banner_cog:hover {
cursor: pointer;
background-color: lightgrey;
}
#banner_system_image {
height: 20px;
width: 20px;
}
#banner_upload_image {
height: 20px;
width: 20px;
margin-right: 5px;
filter: invert(100%);
}
#banner_header {
@@ -153,11 +167,12 @@ h3 {
height: 40px;
right: 0px;
align-items: center;
display: flex;
}
#banner_header_label {
font-family: Commodore64;
display: inline-block;
display: inline;
padding: 10px;
font-size: 16pt;
vertical-align: top;
@@ -165,10 +180,6 @@ h3 {
color: #7c70da;
}
#banner_header_label {
cursor: pointer;
}
#content {
margin-top: 35px;
padding-top: 5px;
@@ -195,7 +206,7 @@ h3 {
padding: 10px;
}
input[type='text'], input[type='number'] {
input[type='text'] {
background-color: #2b2b2b;
color: white;
padding: 5px;
@@ -214,15 +225,6 @@ input[id='filter_panel_search'] {
width: 160px;
}
input[id='filter_panel_userrating_min'] {
width: 50px;
margin-right: 5px;
}
input[id='filter_panel_userrating_max'] {
width: 50px;
}
/* width */
::-webkit-scrollbar {
width: 10px;
@@ -284,20 +286,12 @@ input[id='filter_panel_userrating_max'] {
text-align: center;
vertical-align: top;
margin-bottom: 10px;
border-radius: 10px 10px 10px 10px;
-webkit-border-radius: 10px 10px 10px 10px;
-moz-border-radius: 10px 10px 10px 10px;
border: 1px solid transparent;
}
.game_tile:hover {
cursor: pointer;
text-decoration: underline;
background-color: #2b2b2b;
border-radius: 10px 10px 10px 10px;
-webkit-border-radius: 10px 10px 10px 10px;
-moz-border-radius: 10px 10px 10px 10px;
border: 1px solid #2b2b2b;
}
.game_tile_image {
@@ -312,11 +306,6 @@ input[id='filter_panel_userrating_max'] {
background-color: white;
}
.game_tile_image_small {
max-width: 100px;
max-height: 100px;
}
#bgImage {
position: fixed;
top: -30px;
@@ -630,11 +619,6 @@ div[name="properties_toc_item"]:hover {
margin-top: 20px;
}
.select2-container--default .select2-selection--multiple {
background-color: #2b2b2b !important;
color: white !important;
}
.select2-container--open .select2-dropdown--below,
.select2-container--open .select2-dropdown--above {
background: #2b2b2b;
@@ -644,29 +628,6 @@ div[name="properties_toc_item"]:hover {
border: 1px solid #2b2b2b;
}
.select2-selection__choice {
background-color: #2b2b2b !important;
}
.select2-selection__choice__display {
color: white;
}
.select2-results__option--selected {
background-color: black !important;
}
.select2-selection--single .select2-selection__rendered {
background-color: #2b2b2b;
color: white !important;
border: 1px solid #2b2b2b;
}
.select2-search__field {
background-color: #2b2b2b;
color: white;
}
.dropdown-div {
width: 100%;
}
@@ -811,27 +772,6 @@ button:disabled {
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
}
#gametitle_criticrating {
float: right;
}
#gametitle_alts {
margin-top: -2px;
}
#gametitle_criticrating_value {
display: inline-block;
font-family: Commodore64;
font-size: 36px;
text-align: center;
margin-right: 2px;
}
#gametitle_criticrating_label {
display: inline-block;
text-align: left;
}
#rom_edit_progressbar {
width: 100%;
height: 10px;
@@ -843,38 +783,3 @@ button:disabled {
height: 10px;
background-color: cyan;
}
.collections_modal {
width: 1000px;
height: 90%;
margin: 25px auto;
/* overflow-x: scroll;*/
position: relative;
}
.collections_preview_platform_header {
background-color: #2b2b2b;
}
.collections_preview_gamecovercell {
text-align: center;
width: 110px;
vertical-align: top;
padding-bottom: 10px;
}
.collections_preview_gametitlecell {
font-weight: bold;
}
.collections_preview_gamedetailcell {
vertical-align: top;
}
.bgalt0 {
background-color: #414040;
}
.bgalt1 {
background-color: transparent;;
}

View File

@@ -13,7 +13,7 @@ namespace gaseous_tools
/// <returns></returns>
static public object ReturnValueIfNull(object? ObjectToCheck, object IfNullValue)
{
if (ObjectToCheck == null || ObjectToCheck == System.DBNull.Value)
if (ObjectToCheck == null)
{
return IfNullValue;
} else

View File

@@ -359,22 +359,6 @@ namespace gaseous_tools
}
}
public string LibraryTempDirectory
{
get
{
return Path.Combine(LibraryRootDirectory, "Temp");
}
}
public string LibraryCollectionsDirectory
{
get
{
return Path.Combine(LibraryRootDirectory, "Collections");
}
}
public string LibraryMetadataDirectory_Platform(Platform platform)
{
string MetadataPath = Path.Combine(LibraryMetadataDirectory, "Platforms", platform.Slug);
@@ -420,8 +404,6 @@ namespace gaseous_tools
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
if (!Directory.Exists(LibraryTempDirectory)) { Directory.CreateDirectory(LibraryTempDirectory); }
if (!Directory.Exists(LibraryCollectionsDirectory)) { Directory.CreateDirectory(LibraryCollectionsDirectory); }
if (!Directory.Exists(LibrarySignatureImportDirectory)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }
}

View File

@@ -1,86 +0,0 @@
DROP TABLE IF EXISTS `GameMode`;
CREATE TABLE `gaseous`.`GameMode` (
`Id` BIGINT NOT NULL,
`CreatedAt` DATETIME NULL,
`Checksum` VARCHAR(45) NULL,
`Name` VARCHAR(100) NULL,
`Slug` VARCHAR(100) NULL,
`UpdatedAt` DATETIME NULL,
`Url` VARCHAR(255) NULL,
`dateAdded` DATETIME NULL,
`lastUpdated` DATETIME NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `MultiplayerMode`;
CREATE TABLE `MultiplayerMode` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`CampaignCoop` boolean DEFAULT NULL,
`DropIn` boolean DEFAULT NULL,
`Game` bigint DEFAULT NULL,
`LanCoop` boolean DEFAULT NULL,
`OfflineCoop` boolean DEFAULT NULL,
`OfflineCoopMax` int DEFAULT NULL,
`OfflineMax` int DEFAULT NULL,
`OnlineCoop` boolean DEFAULT NULL,
`OnlineCoopMax` int DEFAULT NULL,
`OnlineMax` int DEFAULT NULL,
`Platform` bigint DEFAULT NULL,
`SplitScreen` boolean DEFAULT NULL,
`SplitScreenOnline` boolean DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `PlayerPerspective`;
CREATE TABLE `PlayerPerspective` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Name` varchar(100) DEFAULT NULL,
`Slug` varchar(45) DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `Theme`;
CREATE TABLE `Theme` (
`Id` bigint NOT NULL,
`CreatedAt` datetime DEFAULT NULL,
`Checksum` varchar(45) DEFAULT NULL,
`Name` varchar(100) DEFAULT NULL,
`Slug` varchar(45) DEFAULT NULL,
`UpdatedAt` datetime DEFAULT NULL,
`Url` varchar(255) DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`)
);
DROP TABLE IF EXISTS `RomCollections`;
CREATE TABLE `RomCollections` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(255) NULL,
`Description` LONGTEXT NULL,
`Platforms` JSON NULL,
`Genres` JSON NULL,
`Players` JSON NULL,
`PlayerPerspectives` JSON NULL,
`Themes` JSON NULL,
`MinimumRating` INT NULL,
`MaximumRating` INT NULL,
`MaximumRomsPerPlatform` INT NULL,
`MaximumBytesPerPlatform` BIGINT NULL,
`MaximumCollectionSizeInBytes` BIGINT NULL,
`BuiltStatus` INT NULL,
PRIMARY KEY (`Id`));
ALTER TABLE `gaseous`.`Signatures_Sources`
CHANGE COLUMN `Author` `Author` LONGTEXT NULL DEFAULT NULL ;

View File

@@ -16,7 +16,6 @@
<None Remove="Database\" />
<None Remove="Database\MySQL\" />
<None Remove="Database\MySQL\gaseous-1000.sql" />
<None Remove="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
<ItemGroup>
<Folder Include="Database\" />
@@ -24,6 +23,5 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" />
</ItemGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 6.6 MiB