Adds back support for presenting CheatsViewController from Pause Menu
This commit is contained in:
parent
8c3d072a5f
commit
a5c50b41bc
@ -7,7 +7,7 @@
|
|||||||
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
<attribute name="identifier" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="modifiedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="modifiedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="type" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="type" attributeType="String" syncable="YES"/>
|
||||||
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="cheats" inverseEntity="Game" syncable="YES"/>
|
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="cheats" inverseEntity="Game" syncable="YES"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit d819614e5fe422aa4975f70e3d4f1d2dc97b9c24
|
Subproject commit 7149d73128c0f5c95b3e58990f9d185cf33277df
|
||||||
@ -19,6 +19,7 @@
|
|||||||
BF27CC8E1BC9FEA200A20D89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF6BB2451BB73FE800CCF94A /* Assets.xcassets */; };
|
BF27CC8E1BC9FEA200A20D89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF6BB2451BB73FE800CCF94A /* Assets.xcassets */; };
|
||||||
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */; };
|
BF27CC971BCC890700A20D89 /* GamesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */; };
|
||||||
BF2B98E61C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */; };
|
BF2B98E61C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */; };
|
||||||
|
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF31878A1D489AAA00BD020D /* CheatValidator.swift */; };
|
||||||
BF34FA071CF0F510006624C7 /* EditCheatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */; };
|
BF34FA071CF0F510006624C7 /* EditCheatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */; };
|
||||||
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34FA101CF1899D006624C7 /* CheatTextView.swift */; };
|
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF34FA101CF1899D006624C7 /* CheatTextView.swift */; };
|
||||||
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF353FF11C5D7FB000C1184C /* PauseViewController.swift */; };
|
||||||
@ -102,6 +103,7 @@
|
|||||||
BF27CC941BCB7B7A00A20D89 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
|
BF27CC941BCB7B7A00A20D89 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesCollectionViewController.swift; sourceTree = "<group>"; };
|
BF27CC961BCC890700A20D89 /* GamesCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesCollectionViewController.swift; sourceTree = "<group>"; };
|
||||||
BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesCollectionHeaderView.swift; path = "Pause Menu/Save States/SaveStatesCollectionHeaderView.swift"; sourceTree = "<group>"; };
|
BF2B98E51C97E32F00F6D57D /* SaveStatesCollectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesCollectionHeaderView.swift; path = "Pause Menu/Save States/SaveStatesCollectionHeaderView.swift"; sourceTree = "<group>"; };
|
||||||
|
BF31878A1D489AAA00BD020D /* CheatValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheatValidator.swift; path = "Pause Menu/Cheats/CheatValidator.swift"; sourceTree = "<group>"; };
|
||||||
BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EditCheatViewController.swift; path = "Pause Menu/Cheats/EditCheatViewController.swift"; sourceTree = "<group>"; };
|
BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EditCheatViewController.swift; path = "Pause Menu/Cheats/EditCheatViewController.swift"; sourceTree = "<group>"; };
|
||||||
BF34FA101CF1899D006624C7 /* CheatTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheatTextView.swift; path = "Pause Menu/Cheats/CheatTextView.swift"; sourceTree = "<group>"; };
|
BF34FA101CF1899D006624C7 /* CheatTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheatTextView.swift; path = "Pause Menu/Cheats/CheatTextView.swift"; sourceTree = "<group>"; };
|
||||||
BF353FF11C5D7FB000C1184C /* PauseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseViewController.swift; path = "Pause Menu/PauseViewController.swift"; sourceTree = "<group>"; };
|
BF353FF11C5D7FB000C1184C /* PauseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseViewController.swift; path = "Pause Menu/PauseViewController.swift"; sourceTree = "<group>"; };
|
||||||
@ -320,6 +322,7 @@
|
|||||||
BFC9B7381CEFCD34008629BB /* CheatsViewController.swift */,
|
BFC9B7381CEFCD34008629BB /* CheatsViewController.swift */,
|
||||||
BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */,
|
BF34FA061CF0F510006624C7 /* EditCheatViewController.swift */,
|
||||||
BF34FA101CF1899D006624C7 /* CheatTextView.swift */,
|
BF34FA101CF1899D006624C7 /* CheatTextView.swift */,
|
||||||
|
BF31878A1D489AAA00BD020D /* CheatValidator.swift */,
|
||||||
);
|
);
|
||||||
name = Cheats;
|
name = Cheats;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -542,6 +545,7 @@
|
|||||||
BF7AE8241C2E984300B1B5BC /* GridCollectionViewLayout.swift in Sources */,
|
BF7AE8241C2E984300B1B5BC /* GridCollectionViewLayout.swift in Sources */,
|
||||||
BF1FB1861C5EE643007E2494 /* SaveState.swift in Sources */,
|
BF1FB1861C5EE643007E2494 /* SaveState.swift in Sources */,
|
||||||
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
|
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
|
||||||
|
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */,
|
||||||
BFB141181BE46934004FBF46 /* GameCollectionViewDataSource.swift in Sources */,
|
BFB141181BE46934004FBF46 /* GameCollectionViewDataSource.swift in Sources */,
|
||||||
BFA2315C1CED10BE0011E35A /* Action.swift in Sources */,
|
BFA2315C1CED10BE0011E35A /* Action.swift in Sources */,
|
||||||
BFAA1FF41B8AD7F900495943 /* ControllersSettingsViewController.swift in Sources */,
|
BFAA1FF41B8AD7F900495943 /* ControllersSettingsViewController.swift in Sources */,
|
||||||
|
|||||||
@ -10,13 +10,20 @@ import UIKit
|
|||||||
|
|
||||||
import DeltaCore
|
import DeltaCore
|
||||||
|
|
||||||
|
private var kvoContext = 0
|
||||||
|
|
||||||
class GameViewController: DeltaCore.GameViewController
|
class GameViewController: DeltaCore.GameViewController
|
||||||
{
|
{
|
||||||
/// Assumed to be Delta.Game instance
|
/// Assumed to be Delta.Game instance
|
||||||
override var game: GameProtocol? {
|
override var game: GameProtocol? {
|
||||||
|
willSet {
|
||||||
|
self.emulatorCore?.removeObserver(self, forKeyPath: #keyPath(EmulatorCore.state), context: &kvoContext)
|
||||||
|
}
|
||||||
didSet {
|
didSet {
|
||||||
guard let emulatorCore = self.emulatorCore else { return }
|
guard let emulatorCore = self.emulatorCore else { return }
|
||||||
self.preferredContentSize = emulatorCore.preferredRenderingSize
|
self.preferredContentSize = emulatorCore.preferredRenderingSize
|
||||||
|
|
||||||
|
emulatorCore.addObserver(self, forKeyPath: #keyPath(EmulatorCore.state), options: [.old], context: &kvoContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +58,11 @@ class GameViewController: DeltaCore.GameViewController
|
|||||||
NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.updateControllers), name: .externalControllerDidDisconnect, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.updateControllers), name: .externalControllerDidDisconnect, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit
|
||||||
|
{
|
||||||
|
self.emulatorCore?.removeObserver(self, forKeyPath: #keyPath(EmulatorCore.state), context: &kvoContext)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: GameControllerReceiver -
|
// MARK: GameControllerReceiver -
|
||||||
override func gameController(_ gameController: GameController, didActivate input: Input)
|
override func gameController(_ gameController: GameController, didActivate input: Input)
|
||||||
{
|
{
|
||||||
@ -116,6 +128,7 @@ extension GameViewController
|
|||||||
pauseViewController.pauseText = (self.game as? Game)?.name ?? NSLocalizedString("Delta", comment: "")
|
pauseViewController.pauseText = (self.game as? Game)?.name ?? NSLocalizedString("Delta", comment: "")
|
||||||
pauseViewController.emulatorCore = self.emulatorCore
|
pauseViewController.emulatorCore = self.emulatorCore
|
||||||
pauseViewController.saveStatesViewControllerDelegate = self
|
pauseViewController.saveStatesViewControllerDelegate = self
|
||||||
|
pauseViewController.cheatsViewControllerDelegate = self
|
||||||
self.pauseViewController = pauseViewController
|
self.pauseViewController = pauseViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +148,20 @@ extension GameViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - KVO -
|
||||||
|
/// KVO
|
||||||
|
override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey : AnyObject]?, context: UnsafeMutablePointer<Void>?)
|
||||||
|
{
|
||||||
|
guard context == &kvoContext else { return super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) }
|
||||||
|
|
||||||
|
guard let rawValue = change?[.oldKey] as? Int, let previousState = EmulatorCore.State(rawValue: rawValue) else { return }
|
||||||
|
|
||||||
|
if previousState == .stopped
|
||||||
|
{
|
||||||
|
self.updateCheats()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: Controllers -
|
//MARK: Controllers -
|
||||||
@ -244,10 +271,81 @@ extension GameViewController: SaveStatesViewControllerDelegate
|
|||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.updateCheats()
|
||||||
|
|
||||||
self.pauseViewController?.dismiss()
|
self.pauseViewController?.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - Cheats
|
||||||
|
/// Cheats
|
||||||
|
extension GameViewController: CheatsViewControllerDelegate
|
||||||
|
{
|
||||||
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, activateCheat cheat: Cheat)
|
||||||
|
{
|
||||||
|
self.activate(cheat)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, deactivateCheat cheat: Cheat)
|
||||||
|
{
|
||||||
|
self.emulatorCore?.deactivate(cheat)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func activate(_ cheat: Cheat)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try self.emulatorCore?.activate(cheat)
|
||||||
|
}
|
||||||
|
catch EmulatorCore.CheatError.invalid
|
||||||
|
{
|
||||||
|
print("Invalid cheat:", cheat.name, cheat.code)
|
||||||
|
}
|
||||||
|
catch let error as NSError
|
||||||
|
{
|
||||||
|
print("Unknown Cheat Error:", error, cheat.name, cheat.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateCheats()
|
||||||
|
{
|
||||||
|
guard let game = self.game as? Game else { return }
|
||||||
|
|
||||||
|
let running = (self.emulatorCore?.state == .running)
|
||||||
|
|
||||||
|
if running
|
||||||
|
{
|
||||||
|
// Core MUST be paused when activating cheats, or else race conditions could crash the core
|
||||||
|
self.pauseEmulation()
|
||||||
|
}
|
||||||
|
|
||||||
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
|
backgroundContext.performAndWait {
|
||||||
|
|
||||||
|
let predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
||||||
|
|
||||||
|
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
|
||||||
|
for cheat in cheats
|
||||||
|
{
|
||||||
|
if cheat.enabled
|
||||||
|
{
|
||||||
|
self.activate(cheat)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.emulatorCore?.deactivate(cheat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if running
|
||||||
|
{
|
||||||
|
self.resumeEmulation()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: GameViewControllerDelegate -
|
//MARK: GameViewControllerDelegate -
|
||||||
/// GameViewControllerDelegate
|
/// GameViewControllerDelegate
|
||||||
extension GameViewController: GameViewControllerDelegate
|
extension GameViewController: GameViewControllerDelegate
|
||||||
|
|||||||
59
Delta/Pause Menu/Cheats/CheatValidator.swift
Normal file
59
Delta/Pause Menu/Cheats/CheatValidator.swift
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// CheatValidator.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 7/27/16.
|
||||||
|
// Copyright © 2016 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
|
||||||
|
extension CheatValidator
|
||||||
|
{
|
||||||
|
enum Error: ErrorProtocol
|
||||||
|
{
|
||||||
|
case invalidCode
|
||||||
|
case invalidName
|
||||||
|
case duplicateName
|
||||||
|
case duplicateCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CheatValidator
|
||||||
|
{
|
||||||
|
let format: CheatFormat
|
||||||
|
let managedObjectContext: NSManagedObjectContext
|
||||||
|
|
||||||
|
func validate(_ cheat: Cheat) throws
|
||||||
|
{
|
||||||
|
guard let name = cheat.name else { throw Error.invalidName }
|
||||||
|
|
||||||
|
let code = cheat.code
|
||||||
|
|
||||||
|
// Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code
|
||||||
|
let predicate = Predicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name)
|
||||||
|
|
||||||
|
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self)
|
||||||
|
for cheat in cheats
|
||||||
|
{
|
||||||
|
if cheat.name == name
|
||||||
|
{
|
||||||
|
throw Error.duplicateName
|
||||||
|
}
|
||||||
|
else if cheat.code == code
|
||||||
|
{
|
||||||
|
throw Error.duplicateCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove newline characters (code should already be formatted)
|
||||||
|
let sanitizedCode = (cheat.code as NSString).replacingOccurrences(of: "\n", with: "")
|
||||||
|
|
||||||
|
if sanitizedCode.characters.count % self.format.format.characters.count != 0
|
||||||
|
{
|
||||||
|
throw Error.invalidCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,19 +15,20 @@ import Roxas
|
|||||||
|
|
||||||
protocol CheatsViewControllerDelegate: class
|
protocol CheatsViewControllerDelegate: class
|
||||||
{
|
{
|
||||||
func cheatsViewControllerActiveEmulatorCore(_ saveStatesViewController: CheatsViewController) -> EmulatorCore
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, activateCheat cheat: Cheat)
|
||||||
func cheatsViewController(_ cheatsViewController: CheatsViewController, didActivateCheat cheat: Cheat) throws
|
func cheatsViewController(_ cheatsViewController: CheatsViewController, deactivateCheat cheat: Cheat)
|
||||||
func cheatsViewController(_ cheatsViewController: CheatsViewController, didDeactivateCheat cheat: Cheat)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheatsViewController: UITableViewController
|
class CheatsViewController: UITableViewController
|
||||||
{
|
{
|
||||||
weak var delegate: CheatsViewControllerDelegate! {
|
var game: Game! {
|
||||||
didSet {
|
didSet {
|
||||||
self.updateFetchedResultsController()
|
self.updateFetchedResultsController()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weak var delegate: CheatsViewControllerDelegate?
|
||||||
|
|
||||||
private var backgroundView: RSTBackgroundView!
|
private var backgroundView: RSTBackgroundView!
|
||||||
|
|
||||||
private var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>!
|
private var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>!
|
||||||
@ -83,11 +84,9 @@ private extension CheatsViewController
|
|||||||
{
|
{
|
||||||
func updateFetchedResultsController()
|
func updateFetchedResultsController()
|
||||||
{
|
{
|
||||||
let game = self.delegate.cheatsViewControllerActiveEmulatorCore(self).game as! Game
|
|
||||||
|
|
||||||
let fetchRequest = Cheat.rst_fetchRequest()
|
let fetchRequest = Cheat.rst_fetchRequest()
|
||||||
fetchRequest.returnsObjectsAsFaults = false
|
fetchRequest.returnsObjectsAsFaults = false
|
||||||
fetchRequest.predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
fetchRequest.predicate = Predicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.game)
|
||||||
fetchRequest.sortDescriptors = [SortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
|
fetchRequest.sortDescriptors = [SortDescriptor(key: Cheat.Attributes.name.rawValue, ascending: true)]
|
||||||
|
|
||||||
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.sharedManager.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
|
||||||
@ -121,7 +120,7 @@ private extension CheatsViewController
|
|||||||
|
|
||||||
func deleteCheat(_ cheat: Cheat)
|
func deleteCheat(_ cheat: Cheat)
|
||||||
{
|
{
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
self.delegate?.cheatsViewController(self, deactivateCheat: cheat)
|
||||||
|
|
||||||
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
let backgroundContext = DatabaseManager.sharedManager.backgroundManagedObjectContext()
|
||||||
backgroundContext.perform {
|
backgroundContext.perform {
|
||||||
@ -148,9 +147,8 @@ private extension CheatsViewController
|
|||||||
{
|
{
|
||||||
let editCheatViewController = self.storyboard!.instantiateViewController(withIdentifier: "editCheatViewController") as! EditCheatViewController
|
let editCheatViewController = self.storyboard!.instantiateViewController(withIdentifier: "editCheatViewController") as! EditCheatViewController
|
||||||
editCheatViewController.delegate = self
|
editCheatViewController.delegate = self
|
||||||
editCheatViewController.supportedCheatFormats = self.delegate.cheatsViewControllerActiveEmulatorCore(self).configuration.supportedCheatFormats
|
|
||||||
editCheatViewController.cheat = cheat
|
editCheatViewController.cheat = cheat
|
||||||
editCheatViewController.game = self.delegate.cheatsViewControllerActiveEmulatorCore(self).game as! Game
|
editCheatViewController.game = self.game
|
||||||
|
|
||||||
return editCheatViewController
|
return editCheatViewController
|
||||||
}
|
}
|
||||||
@ -193,25 +191,13 @@ extension CheatsViewController
|
|||||||
|
|
||||||
if temporaryCheat.enabled
|
if temporaryCheat.enabled
|
||||||
{
|
{
|
||||||
do
|
self.delegate?.cheatsViewController(self, activateCheat: temporaryCheat)
|
||||||
{
|
|
||||||
try self.delegate.cheatsViewController(self, didActivateCheat: temporaryCheat)
|
|
||||||
}
|
|
||||||
catch EmulatorCore.CheatError.invalid
|
|
||||||
{
|
|
||||||
print("Invalid cheat:", cheat.name, cheat.code)
|
|
||||||
}
|
|
||||||
catch let error as NSError
|
|
||||||
{
|
|
||||||
print("Unknown Cheat Error:", error, cheat.name, cheat.code)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: temporaryCheat)
|
self.delegate?.cheatsViewController(self, deactivateCheat: temporaryCheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
backgroundContext.saveWithErrorLogging()
|
backgroundContext.saveWithErrorLogging()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,9 +252,9 @@ extension CheatsViewController: UIViewControllerPreviewingDelegate
|
|||||||
//MARK: - <EditCheatViewControllerDelegate> -
|
//MARK: - <EditCheatViewControllerDelegate> -
|
||||||
extension CheatsViewController: EditCheatViewControllerDelegate
|
extension CheatsViewController: EditCheatViewControllerDelegate
|
||||||
{
|
{
|
||||||
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?)
|
||||||
{
|
{
|
||||||
try self.delegate.cheatsViewController(self, didActivateCheat: cheat)
|
self.delegate?.cheatsViewController(self, activateCheat: cheat)
|
||||||
|
|
||||||
if let previousCheat = previousCheat
|
if let previousCheat = previousCheat
|
||||||
{
|
{
|
||||||
@ -278,14 +264,14 @@ extension CheatsViewController: EditCheatViewControllerDelegate
|
|||||||
|
|
||||||
guard previousCheat.code != code else { return }
|
guard previousCheat.code != code else { return }
|
||||||
|
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: previousCheat)
|
self.delegate?.cheatsViewController(self, deactivateCheat: previousCheat)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
||||||
{
|
{
|
||||||
self.delegate.cheatsViewController(self, didDeactivateCheat: cheat)
|
self.delegate?.cheatsViewController(self, deactivateCheat: cheat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,19 +14,12 @@ import Roxas
|
|||||||
|
|
||||||
protocol EditCheatViewControllerDelegate: class
|
protocol EditCheatViewControllerDelegate: class
|
||||||
{
|
{
|
||||||
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?) throws
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, activateCheat cheat: Cheat, previousCheat: Cheat?)
|
||||||
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
func editCheatViewController(_ editCheatViewController: EditCheatViewController, deactivateCheat cheat: Cheat)
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension EditCheatViewController
|
private extension EditCheatViewController
|
||||||
{
|
{
|
||||||
enum ValidationError: ErrorProtocol
|
|
||||||
{
|
|
||||||
case invalidCode
|
|
||||||
case duplicateName
|
|
||||||
case duplicateCode
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Section: Int
|
enum Section: Int
|
||||||
{
|
{
|
||||||
case name
|
case name
|
||||||
@ -37,11 +30,18 @@ private extension EditCheatViewController
|
|||||||
|
|
||||||
class EditCheatViewController: UITableViewController
|
class EditCheatViewController: UITableViewController
|
||||||
{
|
{
|
||||||
weak var delegate: EditCheatViewControllerDelegate?
|
var game: Game! {
|
||||||
|
didSet {
|
||||||
|
let deltaCore = Delta.core(for: self.game.type)!
|
||||||
|
self.supportedCheatFormats = deltaCore.emulatorConfiguration.supportedCheatFormats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var cheat: Cheat?
|
var cheat: Cheat?
|
||||||
var game: Game!
|
|
||||||
var supportedCheatFormats: [CheatFormat]!
|
weak var delegate: EditCheatViewControllerDelegate?
|
||||||
|
|
||||||
|
private var supportedCheatFormats: [CheatFormat]!
|
||||||
|
|
||||||
private var selectedCheatFormat: CheatFormat {
|
private var selectedCheatFormat: CheatFormat {
|
||||||
let cheatFormat = self.supportedCheatFormats[self.typeSegmentedControl.selectedSegmentIndex]
|
let cheatFormat = self.supportedCheatFormats[self.typeSegmentedControl.selectedSegmentIndex]
|
||||||
@ -271,63 +271,51 @@ private extension EditCheatViewController
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
try self.validateCheat(self.mutableCheat)
|
try self.validateCheat(self.mutableCheat)
|
||||||
|
|
||||||
|
self.delegate?.editCheatViewController(self, activateCheat: self.mutableCheat, previousCheat: self.cheat)
|
||||||
|
|
||||||
self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
|
self.mutableCheat.managedObjectContext?.saveWithErrorLogging()
|
||||||
self.performSegue(withIdentifier: "unwindEditCheatSegue", sender: sender)
|
self.performSegue(withIdentifier: "unwindEditCheatSegue", sender: sender)
|
||||||
}
|
}
|
||||||
catch ValidationError.invalidCode
|
catch CheatValidator.Error.invalidCode
|
||||||
{
|
{
|
||||||
self.presentErrorAlert(title: NSLocalizedString("Invalid Code", comment: ""), message: NSLocalizedString("Please make sure you typed the cheat code in correctly and try again.", comment: "")) {
|
self.presentErrorAlert(title: NSLocalizedString("Invalid Code", comment: ""), message: NSLocalizedString("Please make sure you typed the cheat code in correctly and try again.", comment: "")) {
|
||||||
self.codeTextView.becomeFirstResponder()
|
self.codeTextView.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ValidationError.duplicateCode
|
catch CheatValidator.Error.invalidName
|
||||||
|
{
|
||||||
|
self.presentErrorAlert(title: NSLocalizedString("Invalid Name", comment: ""), message: NSLocalizedString("Please rename this cheat and try again.", comment: "")) {
|
||||||
|
self.codeTextView.becomeFirstResponder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch CheatValidator.Error.duplicateCode
|
||||||
{
|
{
|
||||||
self.presentErrorAlert(title: NSLocalizedString("Duplicate Code", comment: ""), message: NSLocalizedString("A cheat already exists with this code. Please type in a different code and try again.", comment: "")) {
|
self.presentErrorAlert(title: NSLocalizedString("Duplicate Code", comment: ""), message: NSLocalizedString("A cheat already exists with this code. Please type in a different code and try again.", comment: "")) {
|
||||||
self.codeTextView.becomeFirstResponder()
|
self.codeTextView.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch ValidationError.duplicateName
|
catch CheatValidator.Error.duplicateName
|
||||||
{
|
{
|
||||||
self.presentErrorAlert(title: NSLocalizedString("Duplicate Name", comment: ""), message: NSLocalizedString("A cheat already exists with this name. Please rename this cheat and try again.", comment: "")) {
|
self.presentErrorAlert(title: NSLocalizedString("Duplicate Name", comment: ""), message: NSLocalizedString("A cheat already exists with this name. Please rename this cheat and try again.", comment: "")) {
|
||||||
self.nameTextField.becomeFirstResponder()
|
self.nameTextField.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch let error as NSError
|
catch
|
||||||
{
|
{
|
||||||
print(error)
|
print(error)
|
||||||
|
|
||||||
|
self.presentErrorAlert(title: NSLocalizedString("Unknown Error", comment: ""), message: NSLocalizedString("An error occured. Please make sure you typed the cheat code in correctly and try again.", comment: "")) {
|
||||||
|
self.codeTextView.becomeFirstResponder()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCheat(_ cheat: Cheat) throws
|
func validateCheat(_ cheat: Cheat) throws
|
||||||
{
|
{
|
||||||
let name = cheat.name!
|
let validator = CheatValidator(format: self.selectedCheatFormat, managedObjectContext: self.managedObjectContext)
|
||||||
let code = cheat.code
|
try validator.validate(cheat)
|
||||||
|
|
||||||
// Find all cheats that are for the same game, don't have the same identifier as the current cheat, but have either the same name or code
|
|
||||||
let predicate = Predicate(format: "%K == %@ AND %K != %@ AND (%K == %@ OR %K == %@)", Cheat.Attributes.game.rawValue, cheat.game, Cheat.Attributes.identifier.rawValue, cheat.identifier, Cheat.Attributes.code.rawValue, code, Cheat.Attributes.name.rawValue, name)
|
|
||||||
|
|
||||||
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: self.managedObjectContext, type: Cheat.self)
|
|
||||||
for cheat in cheats
|
|
||||||
{
|
|
||||||
if cheat.name == name
|
|
||||||
{
|
|
||||||
throw ValidationError.duplicateName
|
|
||||||
}
|
|
||||||
else if cheat.code == code
|
|
||||||
{
|
|
||||||
throw ValidationError.duplicateCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try self.delegate?.editCheatViewController(self, activateCheat: cheat, previousCheat: self.cheat)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
throw ValidationError.invalidCode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func textFieldDidEndEditing(_ sender: UITextField)
|
@IBAction func textFieldDidEndEditing(_ sender: UITextField)
|
||||||
|
|||||||
@ -32,10 +32,12 @@ class PauseViewController: UIViewController, PauseInfoProviding
|
|||||||
/// PauseInfoProviding
|
/// PauseInfoProviding
|
||||||
var pauseText: String?
|
var pauseText: String?
|
||||||
|
|
||||||
|
/// Cheats
|
||||||
|
weak var cheatsViewControllerDelegate: CheatsViewControllerDelegate?
|
||||||
|
|
||||||
/// Save States
|
/// Save States
|
||||||
weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
|
weak var saveStatesViewControllerDelegate: SaveStatesViewControllerDelegate?
|
||||||
|
|
||||||
// Hopefully this can be removed once SE-0116 is implemented
|
|
||||||
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.loading
|
private var saveStatesViewControllerMode = SaveStatesViewController.Mode.loading
|
||||||
|
|
||||||
private var pauseNavigationController: UINavigationController!
|
private var pauseNavigationController: UINavigationController!
|
||||||
@ -105,6 +107,11 @@ extension PauseViewController
|
|||||||
saveStatesViewController.emulatorCore = self.emulatorCore
|
saveStatesViewController.emulatorCore = self.emulatorCore
|
||||||
saveStatesViewController.mode = self.saveStatesViewControllerMode
|
saveStatesViewController.mode = self.saveStatesViewControllerMode
|
||||||
|
|
||||||
|
case "cheats":
|
||||||
|
let cheatsViewController = segue.destinationViewController as! CheatsViewController
|
||||||
|
cheatsViewController.delegate = self.cheatsViewControllerDelegate
|
||||||
|
cheatsViewController.game = self.emulatorCore?.game as? Game
|
||||||
|
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +157,10 @@ private extension PauseViewController
|
|||||||
self.performSegue(withIdentifier: "saveStates", sender: self)
|
self.performSegue(withIdentifier: "saveStates", sender: self)
|
||||||
})
|
})
|
||||||
|
|
||||||
self.cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { _ in })
|
self.cheatCodesItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Cheat Codes", comment: ""), action: { [unowned self] _ in
|
||||||
|
self.performSegue(withIdentifier: "cheats", sender: self)
|
||||||
|
})
|
||||||
|
|
||||||
self.sustainButtonsItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Sustain Buttons", comment: ""), action: { _ in })
|
self.sustainButtonsItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Sustain Buttons", comment: ""), action: { _ in })
|
||||||
self.fastForwardItem = PauseItem(image: UIImage(named: "FastForward")!, text: NSLocalizedString("Fast Forward", comment: ""), action: { _ in })
|
self.fastForwardItem = PauseItem(image: UIImage(named: "FastForward")!, text: NSLocalizedString("Fast Forward", comment: ""), action: { _ in })
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user