Added feature to build collections of ROM's based on a filter (#76)
* fix: added visual feed back for mass rom matching * chore(deps): EmulatorJS version bump * chore(deps): nuget package version bump * feat: added cover art to the emulator * ci: updated .gitignore * ci: remove .DS_Store files * feat: updated the about box, and labeled the IGDB user score * chore(deps): EmulatorJS version bump * feat: start of collections build, and styling changes * fix: updated PlatformMap.json file with more platforms and fixed SNES extensions * feat: more progress on romsets * doc: updated readme to include new screenshots and discord link * fix: repairs an issue where the author column in signatures was too narrow * chore(deps): EmulatorJS version bump * feat: Collection build code mostly complete * fix: renamed collection classes to avoid conflicts in Swagger * Re-wrote collection builder to correct major bugs and performance * Completed collection builder and zipper * API changes completed * Fixed some last minute Collections API bugs * Collections mostly complete. Todo: delete button * Completed collections build
810
.gitignore
vendored
@@ -1,405 +1,405 @@
|
|||||||
# globs
|
# globs
|
||||||
Makefile.in
|
Makefile.in
|
||||||
*.userprefs
|
*.userprefs
|
||||||
*.usertasks
|
*.usertasks
|
||||||
config.make
|
config.make
|
||||||
config.status
|
config.status
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
install-sh
|
install-sh
|
||||||
autom4te.cache/
|
autom4te.cache/
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
tarballs/
|
tarballs/
|
||||||
test-results/
|
test-results/
|
||||||
|
|
||||||
# Mac bundle stuff
|
# Mac bundle stuff
|
||||||
*.dmg
|
*.dmg
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
|
# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
|
||||||
# General
|
# General
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.AppleDouble
|
.AppleDouble
|
||||||
.LSOverride
|
.LSOverride
|
||||||
|
|
||||||
# Icon must end with two \r
|
# Icon must end with two \r
|
||||||
Icon
|
Icon
|
||||||
|
|
||||||
|
|
||||||
# Thumbnails
|
# Thumbnails
|
||||||
._*
|
._*
|
||||||
|
|
||||||
# Files that might appear in the root of a volume
|
# Files that might appear in the root of a volume
|
||||||
.DocumentRevisions-V100
|
.DocumentRevisions-V100
|
||||||
.fseventsd
|
.fseventsd
|
||||||
.Spotlight-V100
|
.Spotlight-V100
|
||||||
.TemporaryItems
|
.TemporaryItems
|
||||||
.Trashes
|
.Trashes
|
||||||
.VolumeIcon.icns
|
.VolumeIcon.icns
|
||||||
.com.apple.timemachine.donotpresent
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
# Directories potentially created on remote AFP share
|
# Directories potentially created on remote AFP share
|
||||||
.AppleDB
|
.AppleDB
|
||||||
.AppleDesktop
|
.AppleDesktop
|
||||||
Network Trash Folder
|
Network Trash Folder
|
||||||
Temporary Items
|
Temporary Items
|
||||||
.apdisk
|
.apdisk
|
||||||
|
|
||||||
# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
|
# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
|
||||||
# Windows thumbnail cache files
|
# Windows thumbnail cache files
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
ehthumbs_vista.db
|
ehthumbs_vista.db
|
||||||
|
|
||||||
# Dump file
|
# Dump file
|
||||||
*.stackdump
|
*.stackdump
|
||||||
|
|
||||||
# Folder config file
|
# Folder config file
|
||||||
[Dd]esktop.ini
|
[Dd]esktop.ini
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
# Recycle Bin used on file shares
|
||||||
$RECYCLE.BIN/
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
# Windows Installer files
|
# Windows Installer files
|
||||||
*.cab
|
*.cab
|
||||||
*.msi
|
*.msi
|
||||||
*.msix
|
*.msix
|
||||||
*.msm
|
*.msm
|
||||||
*.msp
|
*.msp
|
||||||
|
|
||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
##
|
##
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
|
|
||||||
# Build results
|
# Build results
|
||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
#wwwroot/
|
#wwwroot/
|
||||||
|
|
||||||
# Visual Studio 2017 auto generated files
|
# Visual Studio 2017 auto generated files
|
||||||
Generated\ Files/
|
Generated\ Files/
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
[Bb]uild[Ll]og.*
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
# NUNIT
|
# NUNIT
|
||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
# Build Results of an ATL Project
|
||||||
[Dd]ebugPS/
|
[Dd]ebugPS/
|
||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
dlldata.c
|
dlldata.c
|
||||||
|
|
||||||
# Benchmark Results
|
# Benchmark Results
|
||||||
BenchmarkDotNet.Artifacts/
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
# .NET Core
|
# .NET Core
|
||||||
project.lock.json
|
project.lock.json
|
||||||
project.fragment.lock.json
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
|
||||||
# StyleCop
|
# StyleCop
|
||||||
StyleCopReport.xml
|
StyleCopReport.xml
|
||||||
|
|
||||||
# Files built by Visual Studio
|
# Files built by Visual Studio
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
*_h.h
|
*_h.h
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
*.iobj
|
*.iobj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
*.ipdb
|
*.ipdb
|
||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
*.sbr
|
*.sbr
|
||||||
*.tlb
|
*.tlb
|
||||||
*.tli
|
*.tli
|
||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
*_wpftmp.csproj
|
*_wpftmp.csproj
|
||||||
*.log
|
*.log
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
.builds
|
.builds
|
||||||
*.pidb
|
*.pidb
|
||||||
*.svclog
|
*.svclog
|
||||||
*.scc
|
*.scc
|
||||||
|
|
||||||
# Chutzpah Test files
|
# Chutzpah Test files
|
||||||
_Chutzpah*
|
_Chutzpah*
|
||||||
|
|
||||||
# Visual C++ cache files
|
# Visual C++ cache files
|
||||||
ipch/
|
ipch/
|
||||||
*.aps
|
*.aps
|
||||||
*.ncb
|
*.ncb
|
||||||
*.opendb
|
*.opendb
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
*.cachefile
|
*.cachefile
|
||||||
*.VC.db
|
*.VC.db
|
||||||
*.VC.VC.opendb
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
*.sap
|
*.sap
|
||||||
|
|
||||||
# Visual Studio Trace Files
|
# Visual Studio Trace Files
|
||||||
*.e2e
|
*.e2e
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
# TFS 2012 Local Workspace
|
||||||
$tf/
|
$tf/
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
# Guidance Automation Toolkit
|
||||||
*.gpState
|
*.gpState
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
# ReSharper is a .NET coding add-in
|
||||||
_ReSharper*/
|
_ReSharper*/
|
||||||
*.[Rr]e[Ss]harper
|
*.[Rr]e[Ss]harper
|
||||||
*.DotSettings.user
|
*.DotSettings.user
|
||||||
|
|
||||||
# JustCode is a .NET coding add-in
|
# JustCode is a .NET coding add-in
|
||||||
.JustCode
|
.JustCode
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
# TeamCity is a build add-in
|
||||||
_TeamCity*
|
_TeamCity*
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
# DotCover is a Code Coverage Tool
|
||||||
*.dotCover
|
*.dotCover
|
||||||
|
|
||||||
# AxoCover is a Code Coverage Tool
|
# AxoCover is a Code Coverage Tool
|
||||||
.axoCover/*
|
.axoCover/*
|
||||||
!.axoCover/settings.json
|
!.axoCover/settings.json
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
# Visual Studio code coverage results
|
||||||
*.coverage
|
*.coverage
|
||||||
*.coveragexml
|
*.coveragexml
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
nCrunchTemp_*
|
nCrunchTemp_*
|
||||||
|
|
||||||
# MightyMoose
|
# MightyMoose
|
||||||
*.mm.*
|
*.mm.*
|
||||||
AutoTest.Net/
|
AutoTest.Net/
|
||||||
|
|
||||||
# Web workbench (sass)
|
# Web workbench (sass)
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
|
|
||||||
# Installshield output folder
|
# Installshield output folder
|
||||||
[Ee]xpress/
|
[Ee]xpress/
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
# DocProject is a documentation generator add-in
|
||||||
DocProject/buildhelp/
|
DocProject/buildhelp/
|
||||||
DocProject/Help/*.HxT
|
DocProject/Help/*.HxT
|
||||||
DocProject/Help/*.HxC
|
DocProject/Help/*.HxC
|
||||||
DocProject/Help/*.hhc
|
DocProject/Help/*.hhc
|
||||||
DocProject/Help/*.hhk
|
DocProject/Help/*.hhk
|
||||||
DocProject/Help/*.hhp
|
DocProject/Help/*.hhp
|
||||||
DocProject/Help/Html2
|
DocProject/Help/Html2
|
||||||
DocProject/Help/html
|
DocProject/Help/html
|
||||||
|
|
||||||
# Click-Once directory
|
# Click-Once directory
|
||||||
publish/
|
publish/
|
||||||
|
|
||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.[Pp]ublish.xml
|
*.[Pp]ublish.xml
|
||||||
*.azurePubxml
|
*.azurePubxml
|
||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
*.pubxml
|
*.pubxml
|
||||||
*.publishproj
|
*.publishproj
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
# in these scripts will be unencrypted
|
# in these scripts will be unencrypted
|
||||||
PublishScripts/
|
PublishScripts/
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
**/[Pp]ackages/*
|
**/[Pp]ackages/*
|
||||||
# except build/, which is used as an MSBuild target.
|
# except build/, which is used as an MSBuild target.
|
||||||
!**/[Pp]ackages/build/
|
!**/[Pp]ackages/build/
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
#!**/[Pp]ackages/repositories.config
|
#!**/[Pp]ackages/repositories.config
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
# Microsoft Azure Build Output
|
||||||
csx/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
# Microsoft Azure Emulator
|
||||||
ecf/
|
ecf/
|
||||||
rcf/
|
rcf/
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
# Windows Store app package directories and files
|
||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
Package.StoreAssociation.xml
|
Package.StoreAssociation.xml
|
||||||
_pkginfo.txt
|
_pkginfo.txt
|
||||||
*.appx
|
*.appx
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
*.[Cc]ache
|
*.[Cc]ache
|
||||||
# but keep track of directories ending in .cache
|
# but keep track of directories ending in .cache
|
||||||
!*.[Cc]ache/
|
!*.[Cc]ache/
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
ClientBin/
|
ClientBin/
|
||||||
~$*
|
~$*
|
||||||
*~
|
*~
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
*.jfm
|
*.jfm
|
||||||
*.pfx
|
*.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
# Including strong name files can present a security risk
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
#*.snk
|
#*.snk
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
#bower_components/
|
#bower_components/
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
# RIA/Silverlight projects
|
||||||
Generated_Code/
|
Generated_Code/
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
# Backup & report files from converting an old project file
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
# because we have git ;-)
|
# because we have git ;-)
|
||||||
_UpgradeReport_Files/
|
_UpgradeReport_Files/
|
||||||
Backup*/
|
Backup*/
|
||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
ServiceFabricBackup/
|
ServiceFabricBackup/
|
||||||
*.rptproj.bak
|
*.rptproj.bak
|
||||||
|
|
||||||
# SQL Server files
|
# SQL Server files
|
||||||
*.mdf
|
*.mdf
|
||||||
*.ldf
|
*.ldf
|
||||||
*.ndf
|
*.ndf
|
||||||
|
|
||||||
# Business Intelligence projects
|
# Business Intelligence projects
|
||||||
*.rdl.data
|
*.rdl.data
|
||||||
*.bim.layout
|
*.bim.layout
|
||||||
*.bim_*.settings
|
*.bim_*.settings
|
||||||
*.rptproj.rsuser
|
*.rptproj.rsuser
|
||||||
|
|
||||||
# Microsoft Fakes
|
# Microsoft Fakes
|
||||||
FakesAssemblies/
|
FakesAssemblies/
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
# GhostDoc plugin setting file
|
||||||
*.GhostDoc.xml
|
*.GhostDoc.xml
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
.ntvs_analysis.dat
|
.ntvs_analysis.dat
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
# Visual Studio 6 build log
|
||||||
*.plg
|
*.plg
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
# Visual Studio 6 workspace options file
|
||||||
*.opt
|
*.opt
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
*.vbw
|
*.vbw
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
# Visual Studio LightSwitch build output
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
**/*.Server/GeneratedArtifacts
|
**/*.Server/GeneratedArtifacts
|
||||||
**/*.Server/ModelManifest.xml
|
**/*.Server/ModelManifest.xml
|
||||||
_Pvt_Extensions
|
_Pvt_Extensions
|
||||||
|
|
||||||
# Paket dependency manager
|
# Paket dependency manager
|
||||||
.paket/paket.exe
|
.paket/paket.exe
|
||||||
paket-files/
|
paket-files/
|
||||||
|
|
||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
.fake/
|
.fake/
|
||||||
|
|
||||||
# JetBrains Rider
|
# JetBrains Rider
|
||||||
.idea/
|
.idea/
|
||||||
*.sln.iml
|
*.sln.iml
|
||||||
|
|
||||||
# CodeRush personal settings
|
# CodeRush personal settings
|
||||||
.cr/personal
|
.cr/personal
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
# Python Tools for Visual Studio (PTVS)
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
# Cake - Uncomment if you are using it
|
||||||
# tools/**
|
# tools/**
|
||||||
# !tools/packages.config
|
# !tools/packages.config
|
||||||
|
|
||||||
# Tabs Studio
|
# Tabs Studio
|
||||||
*.tss
|
*.tss
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
# Telerik's JustMock configuration file
|
||||||
*.jmconfig
|
*.jmconfig
|
||||||
|
|
||||||
# BizTalk build output
|
# BizTalk build output
|
||||||
*.btp.cs
|
*.btp.cs
|
||||||
*.btm.cs
|
*.btm.cs
|
||||||
*.odx.cs
|
*.odx.cs
|
||||||
*.xsd.cs
|
*.xsd.cs
|
||||||
|
|
||||||
# OpenCover UI analysis results
|
# OpenCover UI analysis results
|
||||||
OpenCover/
|
OpenCover/
|
||||||
|
|
||||||
# Azure Stream Analytics local run output
|
# Azure Stream Analytics local run output
|
||||||
ASALocalRun/
|
ASALocalRun/
|
||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
# MSBuild Binary and Structured Log
|
||||||
*.binlog
|
*.binlog
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
# NVidia Nsight GPU debugger configuration file
|
||||||
*.nvuser
|
*.nvuser
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
.mfractor/
|
.mfractor/
|
||||||
|
|
||||||
# Local History for Visual Studio
|
# Local History for Visual Studio
|
||||||
.localhistory/
|
.localhistory/
|
||||||
|
@@ -5,6 +5,7 @@ This is the server for the Gaseous system. All your games and metadata are store
|
|||||||
## Screenshots
|
## Screenshots
|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
* MySQL Server 8+
|
* MySQL Server 8+
|
||||||
@@ -18,6 +19,9 @@ The following projects are used by Gaseous
|
|||||||
* https://github.com/kamranayub/igdb-dotnet
|
* https://github.com/kamranayub/igdb-dotnet
|
||||||
* https://github.com/EmulatorJS/EmulatorJS
|
* https://github.com/EmulatorJS/EmulatorJS
|
||||||
|
|
||||||
|
## Discord Server
|
||||||
|
[](https://discord.gg/Nhu7wpT3k4)
|
||||||
|
|
||||||
## Configuration File
|
## 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).
|
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).
|
||||||
|
|
||||||
|
BIN
gaseous-server/Assets/Ratings/.DS_Store
vendored
607
gaseous-server/Classes/Collections.cs
Normal file
@@ -0,0 +1,607 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -129,7 +129,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
// file is a zip and less than 1 GiB
|
// file is a zip and less than 1 GiB
|
||||||
// extract the zip file and search the contents
|
// extract the zip file and search the contents
|
||||||
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "Temp", Path.GetRandomFileName());
|
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, Path.GetRandomFileName());
|
||||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||||
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);
|
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);
|
||||||
|
|
||||||
|
@@ -6,12 +6,19 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
public class Roms
|
public class Roms
|
||||||
{
|
{
|
||||||
public static List<GameRomItem> GetRoms(long GameId)
|
public static List<GameRomItem> GetRoms(long GameId, long PlatformId = -1)
|
||||||
{
|
{
|
||||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`";
|
string sql = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", GameId);
|
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);
|
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (romDT.Rows.Count > 0)
|
if (romDT.Rows.Count > 0)
|
||||||
|
@@ -25,13 +25,16 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
|
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
|
||||||
{
|
{
|
||||||
if (TaskType == qi.ItemType)
|
if (qi.AllowManualStart == true)
|
||||||
{
|
{
|
||||||
if (ForceRun == true)
|
if (TaskType == qi.ItemType)
|
||||||
{
|
{
|
||||||
qi.ForceExecute();
|
if (ForceRun == true)
|
||||||
|
{
|
||||||
|
qi.ForceExecute();
|
||||||
|
}
|
||||||
|
return qi;
|
||||||
}
|
}
|
||||||
return qi;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
191
gaseous-server/Controllers/CollectionsController.cs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,28 +1,28 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using gaseous_server.Classes.Metadata;
|
using gaseous_server.Classes.Metadata;
|
||||||
using gaseous_tools;
|
using gaseous_tools;
|
||||||
using IGDB.Models;
|
using IGDB.Models;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.CodeAnalysis.Scripting;
|
using Microsoft.CodeAnalysis.Scripting;
|
||||||
using Org.BouncyCastle.Asn1.X509;
|
using Org.BouncyCastle.Asn1.X509;
|
||||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||||
|
|
||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class GamesController : ControllerBase
|
public class GamesController : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||||
public ActionResult Game(
|
public ActionResult Game(
|
||||||
string name = "",
|
string name = "",
|
||||||
string platform = "",
|
string platform = "",
|
||||||
@@ -33,6 +33,21 @@ namespace gaseous_server.Controllers
|
|||||||
int minrating = -1,
|
int minrating = -1,
|
||||||
int maxrating = -1,
|
int maxrating = -1,
|
||||||
bool sortdescending = false)
|
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)
|
||||||
{
|
{
|
||||||
string whereClause = "";
|
string whereClause = "";
|
||||||
string havingClause = "";
|
string havingClause = "";
|
||||||
@@ -201,14 +216,14 @@ namespace gaseous_server.Controllers
|
|||||||
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
|
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(RetVal);
|
return RetVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}")]
|
[Route("{GameId}")]
|
||||||
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "5Minute")]
|
[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult Game(long GameId, bool forceRefresh = false)
|
public ActionResult Game(long GameId, bool forceRefresh = false)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -228,13 +243,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/alternativename")]
|
[Route("{GameId}/alternativename")]
|
||||||
[ProducesResponseType(typeof(List<AlternativeName>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<AlternativeName>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameAlternativeNames(long GameId)
|
public ActionResult GameAlternativeNames(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -259,13 +274,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/agerating")]
|
[Route("{GameId}/agerating")]
|
||||||
[ProducesResponseType(typeof(List<AgeRatings.GameAgeRating>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<AgeRatings.GameAgeRating>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameAgeClassification(long GameId)
|
public ActionResult GameAgeClassification(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -290,12 +305,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/agerating/{RatingId}/image")]
|
[Route("{GameId}/agerating/{RatingId}/image")]
|
||||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameAgeClassification(long GameId, long RatingId)
|
public ActionResult GameAgeClassification(long GameId, long RatingId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -369,13 +384,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/artwork")]
|
[Route("{GameId}/artwork")]
|
||||||
[ProducesResponseType(typeof(List<Artwork>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Artwork>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameArtwork(long GameId)
|
public ActionResult GameArtwork(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -398,13 +413,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/artwork/{ArtworkId}")]
|
[Route("{GameId}/artwork/{ArtworkId}")]
|
||||||
[ProducesResponseType(typeof(Artwork), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Artwork), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameArtwork(long GameId, long ArtworkId)
|
public ActionResult GameArtwork(long GameId, long ArtworkId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -432,12 +447,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/artwork/{ArtworkId}/image")]
|
[Route("{GameId}/artwork/{ArtworkId}/image")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCoverImage(long GameId, long ArtworkId)
|
public ActionResult GameCoverImage(long GameId, long ArtworkId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -486,13 +501,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/cover")]
|
[Route("{GameId}/cover")]
|
||||||
[ProducesResponseType(typeof(Cover), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Cover), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameCover(long GameId)
|
public ActionResult GameCover(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -519,12 +534,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/cover/image")]
|
[Route("{GameId}/cover/image")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCoverImage(long GameId)
|
public ActionResult GameCoverImage(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -558,13 +573,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/genre")]
|
[Route("{GameId}/genre")]
|
||||||
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameGenre(long GameId)
|
public ActionResult GameGenre(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -594,13 +609,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/companies")]
|
[Route("{GameId}/companies")]
|
||||||
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameInvolvedCompanies(long GameId)
|
public ActionResult GameInvolvedCompanies(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -637,13 +652,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/companies/{CompanyId}")]
|
[Route("{GameId}/companies/{CompanyId}")]
|
||||||
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameInvolvedCompanies(long GameId, long CompanyId)
|
public ActionResult GameInvolvedCompanies(long GameId, long CompanyId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -678,12 +693,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/companies/{CompanyId}/image")]
|
[Route("{GameId}/companies/{CompanyId}/image")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCompanyImage(long GameId, long CompanyId)
|
public ActionResult GameCompanyImage(long GameId, long CompanyId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -721,13 +736,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/roms")]
|
[Route("{GameId}/roms")]
|
||||||
[ProducesResponseType(typeof(List<Classes.Roms.GameRomItem>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Classes.Roms.GameRomItem>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult GameRom(long GameId)
|
public ActionResult GameRom(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -742,13 +757,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/roms/{RomId}")]
|
[Route("{GameId}/roms/{RomId}")]
|
||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult GameRom(long GameId, long RomId)
|
public ActionResult GameRom(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -769,12 +784,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPatch]
|
[HttpPatch]
|
||||||
[Route("{GameId}/roms/{RomId}")]
|
[Route("{GameId}/roms/{RomId}")]
|
||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomRename(long GameId, long RomId, long NewPlatformId, long NewGameId)
|
public ActionResult GameRomRename(long GameId, long RomId, long NewPlatformId, long NewGameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -796,12 +811,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
[Route("{GameId}/roms/{RomId}")]
|
[Route("{GameId}/roms/{RomId}")]
|
||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomDelete(long GameId, long RomId)
|
public ActionResult GameRomDelete(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -823,13 +838,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[HttpHead]
|
[HttpHead]
|
||||||
[Route("{GameId}/roms/{RomId}/file")]
|
[Route("{GameId}/roms/{RomId}/file")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomFile(long GameId, long RomId)
|
public ActionResult GameRomFile(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -858,13 +873,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[HttpHead]
|
[HttpHead]
|
||||||
[Route("{GameId}/roms/{RomId}/{FileName}")]
|
[Route("{GameId}/roms/{RomId}/{FileName}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomFile(long GameId, long RomId, string FileName)
|
public ActionResult GameRomFile(long GameId, long RomId, string FileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -893,12 +908,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("search")]
|
[Route("search")]
|
||||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameSearch(long RomId = 0, string SearchString = "")
|
public ActionResult GameSearch(long RomId = 0, string SearchString = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -930,13 +945,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/screenshots")]
|
[Route("{GameId}/screenshots")]
|
||||||
[ProducesResponseType(typeof(List<Screenshot>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Screenshot>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameScreenshot(long GameId)
|
public ActionResult GameScreenshot(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -959,13 +974,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/screenshots/{ScreenshotId}")]
|
[Route("{GameId}/screenshots/{ScreenshotId}")]
|
||||||
[ProducesResponseType(typeof(Screenshot), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Screenshot), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameScreenshot(long GameId, long ScreenshotId)
|
public ActionResult GameScreenshot(long GameId, long ScreenshotId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -991,12 +1006,12 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/screenshots/{ScreenshotId}/image")]
|
[Route("{GameId}/screenshots/{ScreenshotId}/image")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameScreenshotImage(long GameId, long ScreenshotId)
|
public ActionResult GameScreenshotImage(long GameId, long ScreenshotId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1033,13 +1048,13 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("{GameId}/videos")]
|
[Route("{GameId}/videos")]
|
||||||
[ProducesResponseType(typeof(List<GameVideo>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<GameVideo>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameVideo(long GameId)
|
public ActionResult GameVideo(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1062,6 +1077,6 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,20 +9,22 @@ namespace gaseous_server
|
|||||||
|
|
||||||
public class QueueItem
|
public class QueueItem
|
||||||
{
|
{
|
||||||
public QueueItem(QueueItemType ItemType, int ExecutionInterval)
|
public QueueItem(QueueItemType ItemType, int ExecutionInterval, bool AllowManualStart = true)
|
||||||
{
|
{
|
||||||
_ItemType = ItemType;
|
_ItemType = ItemType;
|
||||||
_ItemState = QueueItemState.NeverStarted;
|
_ItemState = QueueItemState.NeverStarted;
|
||||||
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
|
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
|
||||||
_Interval = ExecutionInterval;
|
_Interval = ExecutionInterval;
|
||||||
|
_AllowManualStart = AllowManualStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks)
|
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks, bool AllowManualStart = true)
|
||||||
{
|
{
|
||||||
_ItemType = ItemType;
|
_ItemType = ItemType;
|
||||||
_ItemState = QueueItemState.NeverStarted;
|
_ItemState = QueueItemState.NeverStarted;
|
||||||
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
|
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval);
|
||||||
_Interval = ExecutionInterval;
|
_Interval = ExecutionInterval;
|
||||||
|
_AllowManualStart = AllowManualStart;
|
||||||
_Blocks = Blocks;
|
_Blocks = Blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ namespace gaseous_server
|
|||||||
private string _LastResult = "";
|
private string _LastResult = "";
|
||||||
private string? _LastError = null;
|
private string? _LastError = null;
|
||||||
private bool _ForceExecute = false;
|
private bool _ForceExecute = false;
|
||||||
|
private bool _AllowManualStart = true;
|
||||||
private List<QueueItemType> _Blocks = new List<QueueItemType>();
|
private List<QueueItemType> _Blocks = new List<QueueItemType>();
|
||||||
|
|
||||||
public QueueItemType ItemType => _ItemType;
|
public QueueItemType ItemType => _ItemType;
|
||||||
@@ -50,6 +53,7 @@ namespace gaseous_server
|
|||||||
public string LastResult => _LastResult;
|
public string LastResult => _LastResult;
|
||||||
public string? LastError => _LastError;
|
public string? LastError => _LastError;
|
||||||
public bool Force => _ForceExecute;
|
public bool Force => _ForceExecute;
|
||||||
|
public bool AllowManualStart => _AllowManualStart;
|
||||||
public List<QueueItemType> Blocks => _Blocks;
|
public List<QueueItemType> Blocks => _Blocks;
|
||||||
|
|
||||||
public void Execute()
|
public void Execute()
|
||||||
@@ -96,6 +100,10 @@ namespace gaseous_server
|
|||||||
Classes.ImportGame.LibraryScan();
|
Classes.ImportGame.LibraryScan();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QueueItemType.CollectionCompiler:
|
||||||
|
Logging.Log(Logging.LogType.Information, "Timered Event", "Starting Collection Compiler");
|
||||||
|
Classes.Collections.CompileCollections();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -125,7 +133,8 @@ namespace gaseous_server
|
|||||||
TitleIngestor,
|
TitleIngestor,
|
||||||
MetadataRefresh,
|
MetadataRefresh,
|
||||||
OrganiseLibrary,
|
OrganiseLibrary,
|
||||||
LibraryScan
|
LibraryScan,
|
||||||
|
CollectionCompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum QueueItemState
|
public enum QueueItemState
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Reflection;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using gaseous_server;
|
using gaseous_server;
|
||||||
using gaseous_tools;
|
using gaseous_tools;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server");
|
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server");
|
||||||
|
|
||||||
@@ -83,7 +85,31 @@ builder.Services.Configure<FormOptions>(options =>
|
|||||||
|
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
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.AddHostedService<TimedHostedService>();
|
builder.Services.AddHostedService<TimedHostedService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
@@ -145,6 +171,7 @@ ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
|||||||
ProcessQueue.QueueItemType.OrganiseLibrary
|
ProcessQueue.QueueItemType.OrganiseLibrary
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.CollectionCompiler, 5, false));
|
||||||
|
|
||||||
// start the app
|
// start the app
|
||||||
app.Run();
|
app.Run();
|
||||||
|
@@ -87,7 +87,15 @@
|
|||||||
],
|
],
|
||||||
"WebEmulator": {
|
"WebEmulator": {
|
||||||
"Type": "EmulatorJS",
|
"Type": "EmulatorJS",
|
||||||
"Core": "segaMD"
|
"Core": "segaMD",
|
||||||
|
"Bios": [
|
||||||
|
{
|
||||||
|
"hash": "45e298905a08f9cfb38fd504cd6dbc84",
|
||||||
|
"description": "MegaDrive TMSS startup ROM",
|
||||||
|
"filename": "bios_MD.bin",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -98,7 +106,9 @@
|
|||||||
"N64"
|
"N64"
|
||||||
],
|
],
|
||||||
"KnownFileExtensions": [
|
"KnownFileExtensions": [
|
||||||
".Z64"
|
".Z64",
|
||||||
|
".V64",
|
||||||
|
".N64"
|
||||||
],
|
],
|
||||||
"WebEmulator": {
|
"WebEmulator": {
|
||||||
"Type": "EmulatorJS",
|
"Type": "EmulatorJS",
|
||||||
@@ -110,20 +120,32 @@
|
|||||||
"IGDBName": "Nintendo Entertainment System",
|
"IGDBName": "Nintendo Entertainment System",
|
||||||
"AlternateNames": [
|
"AlternateNames": [
|
||||||
"Nintendo Entertainment System",
|
"Nintendo Entertainment System",
|
||||||
"NES"
|
"NES",
|
||||||
|
"Nintendo Famicom & Entertainment System"
|
||||||
],
|
],
|
||||||
"KnownFileExtensions": [
|
"KnownFileExtensions": [
|
||||||
".NES",
|
".NES",
|
||||||
".FDS",
|
".NEZ",
|
||||||
".FIG",
|
".UNF",
|
||||||
".MGD",
|
".UNIF"
|
||||||
".SFC",
|
|
||||||
".SMC",
|
|
||||||
".SWC"
|
|
||||||
],
|
],
|
||||||
"WebEmulator": {
|
"WebEmulator": {
|
||||||
"Type": "EmulatorJS",
|
"Type": "EmulatorJS",
|
||||||
"Core": "nes"
|
"Core": "nes",
|
||||||
|
"Bios": [
|
||||||
|
{
|
||||||
|
"hash": "ca30b50f880eb660a320674ed365ef7a",
|
||||||
|
"description": "Family Computer Disk System BIOS - Required for Famicom Disk System emulation",
|
||||||
|
"filename": "disksys.rom",
|
||||||
|
"region": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hash": "7f98d77d7a094ad7d069b74bd553ec98",
|
||||||
|
"description": "Game Genie add-on cartridge - Required for Game Genei Add-on emulation (Only supported on the fceumm core)",
|
||||||
|
"filename": "gamegenie.nes",
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -135,7 +157,10 @@
|
|||||||
"Super Nintendo",
|
"Super Nintendo",
|
||||||
"SNES"
|
"SNES"
|
||||||
],
|
],
|
||||||
"KnownFileExtensions": [],
|
"KnownFileExtensions": [
|
||||||
|
".SFC",
|
||||||
|
".SMC"
|
||||||
|
],
|
||||||
"WebEmulator": {
|
"WebEmulator": {
|
||||||
"Type": "EmulatorJS",
|
"Type": "EmulatorJS",
|
||||||
"Core": "snes"
|
"Core": "snes"
|
||||||
|
@@ -14,9 +14,9 @@
|
|||||||
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
|
<DocumentationFile>bin\Debug\net7.0\gaseous-server.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.8" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.9" />
|
||||||
<PackageReference Include="IGDB" Version="2.3.2" />
|
<PackageReference Include="IGDB" Version="2.3.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -88,24 +88,21 @@
|
|||||||
<Folder Include="Classes\" />
|
<Folder Include="Classes\" />
|
||||||
<Folder Include="Classes\SignatureIngestors\" />
|
<Folder Include="Classes\SignatureIngestors\" />
|
||||||
<Folder Include="Support\" />
|
<Folder Include="Support\" />
|
||||||
<Folder Include="wwwroot\" />
|
|
||||||
<Folder Include="Classes\Metadata\" />
|
<Folder Include="Classes\Metadata\" />
|
||||||
<Folder Include="Assets\" />
|
<Folder Include="Assets\" />
|
||||||
<Folder Include="Assets\Ratings\" />
|
<Folder Include="Assets\Ratings\" />
|
||||||
<Folder Include="Assets\Ratings\ESRB\" />
|
<Folder Include="Assets\Ratings\ESRB\" />
|
||||||
<Folder Include="Assets\Ratings\ACB\" />
|
<Folder Include="Assets\Ratings\ACB\" />
|
||||||
<Folder Include="Assets\Ratings\PEGI\" />
|
<Folder Include="Assets\Ratings\PEGI\" />
|
||||||
<Folder Include="wwwroot\scripts\" />
|
|
||||||
<Folder Include="wwwroot\images\" />
|
|
||||||
<Folder Include="wwwroot\styles\" />
|
|
||||||
<Folder Include="wwwroot\pages\" />
|
|
||||||
<Folder Include="Assets\Ratings\CERO\" />
|
<Folder Include="Assets\Ratings\CERO\" />
|
||||||
<Folder Include="Assets\Ratings\USK\" />
|
<Folder Include="Assets\Ratings\USK\" />
|
||||||
<Folder Include="Assets\Ratings\GRAC\" />
|
<Folder Include="Assets\Ratings\GRAC\" />
|
||||||
<Folder Include="Assets\Ratings\CLASS_IND\" />
|
<Folder Include="Assets\Ratings\CLASS_IND\" />
|
||||||
<Folder Include="wwwroot\fonts\" />
|
</ItemGroup>
|
||||||
<Folder Include="wwwroot\pages\dialogs\" />
|
<ItemGroup>
|
||||||
<Folder Include="wwwroot\pages\settings\" />
|
<None Include="wwwroot\**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
|
<ProjectReference Include="..\gaseous-tools\gaseous-tools.csproj">
|
||||||
@@ -118,13 +115,6 @@
|
|||||||
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
|
<GlobalPropertiesToRemove></GlobalPropertiesToRemove>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Content Remove="Support\PlatformMap.json" />
|
|
||||||
<Content Remove="wwwroot\pages\settings\" />
|
|
||||||
<Content Remove="wwwroot\scripts\jquery.lazy.plugins.min.js" />
|
|
||||||
<Content Remove="wwwroot\scripts\jquery.lazy.min.js" />
|
|
||||||
<Content Remove="wwwroot\pages\dialogs\romsdelete.html" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
|
<EmbeddedResource Include="Support\PlatformMap.json" Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'">
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
BIN
gaseous-server/wwwroot/images/CollectionsWallpaper.jpg
Normal file
After Width: | Height: | Size: 408 KiB |
11
gaseous-server/wwwroot/images/IGDB_logo.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 4.1 KiB |
BIN
gaseous-server/wwwroot/images/TOSEC_logo.gif
Normal file
After Width: | Height: | Size: 1.4 KiB |
4
gaseous-server/wwwroot/images/collections.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 1.6 KiB |
3
gaseous-server/wwwroot/images/delete.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 946 B |
2
gaseous-server/wwwroot/images/download.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 752 B |
5
gaseous-server/wwwroot/images/edit.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
gaseous-server/wwwroot/images/gamebg1.jpg
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
gaseous-server/wwwroot/images/gamebg2.jpg
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
gaseous-server/wwwroot/images/gamebg3.jpg
Normal file
After Width: | Height: | Size: 262 KiB |
12
gaseous-server/wwwroot/images/library.svg
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
gaseous-server/wwwroot/images/librarybg.jpg
Normal file
After Width: | Height: | Size: 218 KiB |
4
gaseous-server/wwwroot/images/refresh.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 20 KiB |
@@ -25,15 +25,29 @@
|
|||||||
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
||||||
</div>
|
</div>
|
||||||
<div id="banner_header">
|
<div id="banner_header">
|
||||||
<div id="banner_header_label">Gaseous Games</div>
|
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';" class="banner_button">
|
||||||
</div>
|
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" class="banner_button_image" />
|
||||||
<div id="banner_upload" onclick="showDialog('upload');">
|
<span id="banner_system_label">Settings</span>
|
||||||
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" />
|
</div>
|
||||||
<span id="banner_upload_label">Upload Games</span>
|
|
||||||
</div>
|
<div id="banner_upload" onclick="showDialog('upload');" class="banner_button">
|
||||||
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';">
|
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" class="banner_button_image" />
|
||||||
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" />
|
<span id="banner_upload_label">Upload</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>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
||||||
|
@@ -23,5 +23,8 @@
|
|||||||
EJS_DEBUG_XX = false;
|
EJS_DEBUG_XX = false;
|
||||||
|
|
||||||
EJS_startOnLoaded = false;
|
EJS_startOnLoaded = false;
|
||||||
|
|
||||||
|
EJS_backgroundImage = emuBackground;
|
||||||
|
EJS_backgroundBlur = true;
|
||||||
</script>
|
</script>
|
||||||
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
80
gaseous-server/wwwroot/pages/collections.html
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<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>
|
27
gaseous-server/wwwroot/pages/dialogs/collectiondelete.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<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>
|
494
gaseous-server/wwwroot/pages/dialogs/collectionedit.html
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
<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>
|
@@ -12,6 +12,7 @@
|
|||||||
var artworksPosition = 0;
|
var artworksPosition = 0;
|
||||||
|
|
||||||
var emuBios = '';
|
var emuBios = '';
|
||||||
|
var emuBackground = '';
|
||||||
|
|
||||||
ajaxCall('/api/v1/Games/' + gameId, 'GET', function (result) {
|
ajaxCall('/api/v1/Games/' + gameId, 'GET', function (result) {
|
||||||
gameData = result;
|
gameData = result;
|
||||||
@@ -28,6 +29,10 @@
|
|||||||
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);');
|
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) {
|
ajaxCall('/api/v1/Bios/' + platformId, 'GET', function (result) {
|
||||||
|
@@ -2,11 +2,26 @@
|
|||||||
<div id="bgImage_Opacity"></div>
|
<div id="bgImage_Opacity"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- The Modal -->
|
||||||
|
<div id="myModalProgress" class="modal">
|
||||||
|
|
||||||
|
<!-- Modal content -->
|
||||||
|
<div class="modal-content-sub">
|
||||||
|
<div id="modal-content-sub-progress">
|
||||||
|
<h1>In Progress...</h1>
|
||||||
|
<progress style="width: 100%;"></progress>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="gamepage">
|
<div id="gamepage">
|
||||||
<div id="gametitle">
|
<div id="gametitle">
|
||||||
<div id="gametitle_criticrating">
|
<div id="gametitle_criticrating">
|
||||||
<span id="gametitle_criticrating_value"></span>
|
<div>
|
||||||
<span id="gametitle_criticrating_label"></span>
|
<span id="gametitle_criticrating_value"></span>
|
||||||
|
<span id="gametitle_criticrating_label"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 id="gametitle_label"></h1>
|
<h1 id="gametitle_label"></h1>
|
||||||
|
|
||||||
@@ -65,9 +80,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var gameId = getQueryString('id', 'int');
|
var gameId = getQueryString('id', 'int');
|
||||||
var gameData;
|
var gameData;
|
||||||
@@ -91,7 +105,7 @@
|
|||||||
|
|
||||||
if (gameData.totalRatingCount) {
|
if (gameData.totalRatingCount) {
|
||||||
var criticscorelabel = document.getElementById('gametitle_criticrating_label');
|
var criticscorelabel = document.getElementById('gametitle_criticrating_label');
|
||||||
criticscorelabel.innerHTML = "based on <br />" + gameData.totalRatingCount + " votes"
|
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>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +135,7 @@
|
|||||||
} else {
|
} else {
|
||||||
gameSummaryLabel.innerHTML = result.storyline;
|
gameSummaryLabel.innerHTML = result.storyline;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameSummaryLabel.offsetHeight < gameSummaryLabel.scrollHeight ||
|
if (gameSummaryLabel.offsetHeight < gameSummaryLabel.scrollHeight ||
|
||||||
gameSummaryLabel.offsetWidth < gameSummaryLabel.scrollWidth) {
|
gameSummaryLabel.offsetWidth < gameSummaryLabel.scrollWidth) {
|
||||||
// your element has overflow and truncated
|
// your element has overflow and truncated
|
||||||
@@ -141,9 +155,12 @@
|
|||||||
artworksPosition = startPos;
|
artworksPosition = startPos;
|
||||||
rotateBackground();
|
rotateBackground();
|
||||||
} else {
|
} else {
|
||||||
|
var bg = document.getElementById('bgImage');
|
||||||
if (result.cover) {
|
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);');
|
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);');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +174,7 @@
|
|||||||
ajaxCall('/api/v1/games/' + gameId + '/companies', 'GET', function (result) {
|
ajaxCall('/api/v1/games/' + gameId + '/companies', 'GET', function (result) {
|
||||||
var lstDevelopers = [];
|
var lstDevelopers = [];
|
||||||
var lstPublishers = [];
|
var lstPublishers = [];
|
||||||
|
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
var companyLabel = document.createElement('span');
|
var companyLabel = document.createElement('span');
|
||||||
companyLabel.className = 'gamegenrelabel';
|
companyLabel.className = 'gamegenrelabel';
|
||||||
@@ -248,7 +265,7 @@
|
|||||||
var gameScreenshots = document.getElementById('gamescreenshots');
|
var gameScreenshots = document.getElementById('gamescreenshots');
|
||||||
if (result.screenshots || result.videos) {
|
if (result.screenshots || result.videos) {
|
||||||
var gameScreenshots_Main = document.getElementById('gamescreenshots_main');
|
var gameScreenshots_Main = document.getElementById('gamescreenshots_main');
|
||||||
|
|
||||||
// load static screenshots
|
// load static screenshots
|
||||||
var gameScreenshots_Gallery = document.getElementById('gamescreenshots_gallery_panel');
|
var gameScreenshots_Gallery = document.getElementById('gamescreenshots_gallery_panel');
|
||||||
var imageIndex = 0;
|
var imageIndex = 0;
|
||||||
@@ -312,6 +329,8 @@
|
|||||||
gameScreenshots_vGallery.appendChild(itemsArr[i]);
|
gameScreenshots_vGallery.appendChild(itemsArr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectScreenshot(0);
|
||||||
|
}, function(error) {
|
||||||
selectScreenshot(0);
|
selectScreenshot(0);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -361,7 +380,7 @@
|
|||||||
|
|
||||||
var newRow = [
|
var newRow = [
|
||||||
['<input type="checkbox" name="rom_checkbox" data-romid="' + result[i].id + '" />', 'rom_checkbox_box_hidden', 'rom_edit_checkbox'],
|
['<input type="checkbox" name="rom_checkbox" data-romid="' + result[i].id + '" />', 'rom_checkbox_box_hidden', 'rom_edit_checkbox'],
|
||||||
'<a href="/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/' + encodeURIComponent(result[i].name) +'" class="romlink">' + result[i].name + '</a>',
|
'<a href="/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/' + encodeURIComponent(result[i].name) + '" class="romlink">' + result[i].name + '</a>',
|
||||||
formatBytes(result[i].size, 2),
|
formatBytes(result[i].size, 2),
|
||||||
result[i].romTypeMedia,
|
result[i].romTypeMedia,
|
||||||
result[i].mediaLabel,
|
result[i].mediaLabel,
|
||||||
@@ -450,7 +469,7 @@
|
|||||||
var gameScreenshots_Items = document.getElementsByName('gamescreenshots_gallery_item');
|
var gameScreenshots_Items = document.getElementsByName('gamescreenshots_gallery_item');
|
||||||
|
|
||||||
selectedScreenshot = selectedScreenshot - 1;
|
selectedScreenshot = selectedScreenshot - 1;
|
||||||
|
|
||||||
if (selectedScreenshot < 0) {
|
if (selectedScreenshot < 0) {
|
||||||
selectedScreenshot = gameScreenshots_Items.length - 1;
|
selectedScreenshot = gameScreenshots_Items.length - 1;
|
||||||
}
|
}
|
||||||
@@ -562,19 +581,34 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
var remapCallCounter = 0;
|
var remapCallCounter = 0;
|
||||||
|
var remapCallCounterMax = 0;
|
||||||
|
|
||||||
function remapTitles() {
|
function remapTitles() {
|
||||||
var fixplatform = $('#rom_edit_fixplatform').select2('data');
|
var fixplatform = $('#rom_edit_fixplatform').select2('data');
|
||||||
var fixgame = $('#rom_edit_fixgame').select2('data');
|
var fixgame = $('#rom_edit_fixgame').select2('data');
|
||||||
|
|
||||||
if (fixplatform[0] && fixgame[0]) {
|
if (fixplatform[0] && fixgame[0]) {
|
||||||
var rom_checks = document.getElementsByName('rom_checkbox');
|
var rom_checks = document.getElementsByName('rom_checkbox');
|
||||||
|
|
||||||
for (var i = 0; i < rom_checks.length; i++) {
|
for (var i = 0; i < rom_checks.length; i++) {
|
||||||
if (rom_checks[i].checked == true) {
|
if (rom_checks[i].checked == true) {
|
||||||
var romId = rom_checks[i].getAttribute('data-romid');
|
remapCallCounterMax += 1;
|
||||||
remapCallCounter += 1;
|
}
|
||||||
ajaxCall('/api/v1/Games/' + gameId + '/roms/' + romId + '?NewPlatformId=' + fixplatform[0].id + '&NewGameId=' + fixgame[0].id, 'PATCH', function (result) {
|
}
|
||||||
remapTitlesCallback();
|
|
||||||
});
|
if (remapCallCounterMax > 0) {
|
||||||
|
showProgress();
|
||||||
|
|
||||||
|
for (var i = 0; i < rom_checks.length; i++) {
|
||||||
|
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) {
|
||||||
|
remapTitlesCallback();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,9 +616,12 @@
|
|||||||
|
|
||||||
function remapTitlesCallback() {
|
function remapTitlesCallback() {
|
||||||
remapCallCounter = remapCallCounter - 1;
|
remapCallCounter = remapCallCounter - 1;
|
||||||
|
|
||||||
if (remapCallCounter <= 0) {
|
if (remapCallCounter <= 0) {
|
||||||
|
closeProgress();
|
||||||
loadRoms(true);
|
loadRoms(true);
|
||||||
remapCallCounter = 0;
|
remapCallCounter = 0;
|
||||||
|
remapCallCounterMax = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,4 +651,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showProgress() {
|
||||||
|
// Get the modal
|
||||||
|
var submodal = document.getElementById("myModalProgress");
|
||||||
|
|
||||||
|
// When the user clicks on the button, open the modal
|
||||||
|
submodal.style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeProgress() {
|
||||||
|
// Get the modal
|
||||||
|
var submodal = document.getElementById("myModalProgress");
|
||||||
|
|
||||||
|
submodal.style.display = "none";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@@ -1,4 +1,8 @@
|
|||||||
<div id="games_home">
|
<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_filter"></div>
|
<div id="games_filter"></div>
|
||||||
<div id="games_library"></div>
|
<div id="games_library"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<h1 id="gametitle_label">About Gaseous</h1>
|
<h1 id="gametitle_label">About Gaseous</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table>
|
<table style="width: 100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Home Page</th>
|
<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>
|
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
|
||||||
@@ -11,4 +11,31 @@
|
|||||||
<th>Bugs and Feature Requests</th>
|
<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>
|
<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>
|
||||||
|
<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>
|
</table>
|
@@ -51,6 +51,9 @@
|
|||||||
case 'LibraryScan':
|
case 'LibraryScan':
|
||||||
itemTypeName = "Library scan";
|
itemTypeName = "Library scan";
|
||||||
break;
|
break;
|
||||||
|
case 'CollectionCompiler':
|
||||||
|
itemTypeName = "Compress collections";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
itemTypeName = result[i].itemType;
|
itemTypeName = result[i].itemType;
|
||||||
break;
|
break;
|
||||||
@@ -78,7 +81,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var startButton = '';
|
var startButton = '';
|
||||||
if (result[i].itemState != "Running") {
|
if (result[i].allowManualStart == true && result[i].itemState != "Running") {
|
||||||
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
|
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
function ajaxCall(endpoint, method, successFunction) {
|
function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|
||||||
// Our sample url to make request
|
// Our sample url to make request
|
||||||
@@ -8,17 +8,27 @@
|
|||||||
// Type of Request
|
// Type of Request
|
||||||
type: method,
|
type: method,
|
||||||
|
|
||||||
|
// data to send to the server
|
||||||
|
data: body,
|
||||||
|
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json',
|
||||||
|
|
||||||
// Function to call when to
|
// Function to call when to
|
||||||
// request is ok
|
// request is ok
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
var x = JSON.stringify(data);
|
//var x = JSON.stringify(data);
|
||||||
console.log(x);
|
//console.log(x);
|
||||||
successFunction(data);
|
successFunction(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
error: function (error) {
|
error: function (error) {
|
||||||
console.log(`Error ${error}`);
|
console.log(`Error ${JSON.stringify(error)}`);
|
||||||
|
|
||||||
|
if (errorFunction) {
|
||||||
|
errorFunction(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -96,6 +106,18 @@ function showDialog(dialogPage, variables) {
|
|||||||
$('#modal-content').load('/pages/dialogs/' + dialogPage + '.html');
|
$('#modal-content').load('/pages/dialogs/' + dialogPage + '.html');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
var subModalVariables;
|
var subModalVariables;
|
||||||
|
|
||||||
function showSubDialog(dialogPage, variables) {
|
function showSubDialog(dialogPage, variables) {
|
||||||
@@ -121,7 +143,7 @@ function showSubDialog(dialogPage, variables) {
|
|||||||
subModalVariables = null;
|
subModalVariables = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
subModalVariables = modalVariables;
|
subModalVariables = variables;
|
||||||
|
|
||||||
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html');
|
$('#modal-content-sub').load('/pages/dialogs/' + dialogPage + '.html');
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,9 @@ 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;
|
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 */
|
/* The Close Button */
|
||||||
.close {
|
.close {
|
||||||
@@ -109,11 +112,10 @@ h3 {
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#banner_upload {
|
.banner_button {
|
||||||
background-color: white;
|
background-color: transparent;
|
||||||
position: fixed;
|
float: right;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
right: 41px;
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -121,44 +123,24 @@ h3 {
|
|||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
margin: 0px;
|
margin: 0px 0px 0px 0px;
|
||||||
display: flex;
|
display: flex;
|
||||||
color: black;
|
color: white;
|
||||||
|
border-left-color: black;
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-left-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#banner_upload:hover {
|
.banner_button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: lightgrey;
|
background-color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
#banner_cog {
|
.banner_button_image {
|
||||||
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;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
filter: invert(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#banner_header {
|
#banner_header {
|
||||||
@@ -171,12 +153,11 @@ h3 {
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#banner_header_label {
|
#banner_header_label {
|
||||||
font-family: Commodore64;
|
font-family: Commodore64;
|
||||||
display: inline;
|
display: inline-block;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
@@ -184,6 +165,10 @@ h3 {
|
|||||||
color: #7c70da;
|
color: #7c70da;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#banner_header_label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
margin-top: 35px;
|
margin-top: 35px;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
@@ -327,6 +312,11 @@ input[id='filter_panel_userrating_max'] {
|
|||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game_tile_image_small {
|
||||||
|
max-width: 100px;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
#bgImage {
|
#bgImage {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: -30px;
|
top: -30px;
|
||||||
@@ -640,6 +630,11 @@ div[name="properties_toc_item"]:hover {
|
|||||||
margin-top: 20px;
|
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--below,
|
||||||
.select2-container--open .select2-dropdown--above {
|
.select2-container--open .select2-dropdown--above {
|
||||||
background: #2b2b2b;
|
background: #2b2b2b;
|
||||||
@@ -649,6 +644,29 @@ div[name="properties_toc_item"]:hover {
|
|||||||
border: 1px solid #2b2b2b;
|
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 {
|
.dropdown-div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -812,4 +830,51 @@ button:disabled {
|
|||||||
#gametitle_criticrating_label {
|
#gametitle_criticrating_label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rom_edit_progressbar {
|
||||||
|
width: 100%;
|
||||||
|
height: 10px;
|
||||||
|
background-color: lightgray;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rom_edit_progressbar_progress {
|
||||||
|
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;;
|
||||||
}
|
}
|
@@ -13,7 +13,7 @@ namespace gaseous_tools
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static public object ReturnValueIfNull(object? ObjectToCheck, object IfNullValue)
|
static public object ReturnValueIfNull(object? ObjectToCheck, object IfNullValue)
|
||||||
{
|
{
|
||||||
if (ObjectToCheck == null)
|
if (ObjectToCheck == null || ObjectToCheck == System.DBNull.Value)
|
||||||
{
|
{
|
||||||
return IfNullValue;
|
return IfNullValue;
|
||||||
} else
|
} else
|
||||||
|
@@ -359,6 +359,22 @@ 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)
|
public string LibraryMetadataDirectory_Platform(Platform platform)
|
||||||
{
|
{
|
||||||
string MetadataPath = Path.Combine(LibraryMetadataDirectory, "Platforms", platform.Slug);
|
string MetadataPath = Path.Combine(LibraryMetadataDirectory, "Platforms", platform.Slug);
|
||||||
@@ -404,6 +420,8 @@ namespace gaseous_tools
|
|||||||
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
|
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
|
||||||
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
|
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
|
||||||
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
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)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
|
||||||
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }
|
if (!Directory.Exists(LibrarySignatureImportDirectory_TOSEC)) { Directory.CreateDirectory(LibrarySignatureImportDirectory_TOSEC); }
|
||||||
}
|
}
|
||||||
|
@@ -62,4 +62,25 @@ CREATE TABLE `Theme` (
|
|||||||
`dateAdded` datetime DEFAULT NULL,
|
`dateAdded` datetime DEFAULT NULL,
|
||||||
`lastUpdated` datetime DEFAULT NULL,
|
`lastUpdated` datetime DEFAULT NULL,
|
||||||
PRIMARY KEY (`Id`)
|
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 ;
|
||||||
|
BIN
screenshots/Emulator.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 3.9 MiB |
Before Width: | Height: | Size: 6.6 MiB After Width: | Height: | Size: 7.4 MiB |