How do I tell the save device to listen to a specific controller when it sends Guide messages?

Nov 7, 2009 at 5:22 PM
Edited Nov 7, 2009 at 5:44 PM

Firstly, I'd like to say its a great library and a fantastic tool for anyone wanting to save data in their XNA game, which is a non-trivial piece of work.

I have a question though: I'm using a SharedSaveDevice, and the scenario I'm testing is when I have an MU, and I launch my game from the dashboard with controller one.  Then I pull the MU and a the guide message appears, saying "you have pulled your MU, would you like to reselect a storage device?".  Now the issue is, that I can only respond to that dialog using controller one, but I can also play the game with controller two (from the game's main menu any controller can be used, which then becomes in the active player in the game).

How do I tell the SharedSaveDevice to switch to controller two, or any other controller, when the SharedSaveDevice issues those Guide messages?


(edited for clarity)

Nov 7, 2009 at 5:43 PM


There is an event in the SaveDevice called DeviceDisconnected. You want to subscribe to that event which will allow you to customize behavior when a device is disconnected. Your event handler will look something like this:

// somewhere after you create the device
mySaveDevice.DeviceDisconnected += saveDevice_DeviceDisconnected;

// then have this method
private void saveDevice_DeviceDisconnected(object sender, SaveDeviceEventArgs eventArgs)
   eventArgs.PlayerToPrompt = // something, assign whatever player index you want

That will let you assign which player index controls the prompt whenever a device is disconnected. That way if player two is the active controller, you can assign PlayerIndex.Two to that property. The device will then use the player index you've given it for the prompt.

Hope that helps!

Nov 7, 2009 at 5:59 PM
Edited Nov 7, 2009 at 6:10 PM

Thanks SimReality, I'll give that a try.

I still have a gap in my conceptual understanding of these events. I already subscribe to a couple of the other events, so I have methods firing after .DeviceSelected or .DeviceSelectorCancelled. So I have code like this:

_sharedSaveDevice.DeviceSelected += (s, e) => OnSharedSaveDevice_DeviceSelected(s, e);

So I follow that ok I think. What I'm not following is how the code you've posted above could send the .PlayerToPrompt back the shared save device.

1) player pulls MU
2) SaveDevice raises the .DeviceDisconnected event, all subscribers to that event get their methods called
3) the method saveDevice_DeviceDisconnected() gets called
4) the code inside saveDevice_DeviceDisconnected runs, and eventArgs.PlayerToPrompt is set to the player of my choice.

What I'm not getting is how that information about PlayerToPrompt gets back to the SaveDevice object? I don't see where I'm pushing that info back into the save device.

Thanks if you can clarify this for me!

Nov 7, 2009 at 6:03 PM

The trick is inside the SaveDevice. The SaveDeviceEventArg type is a class so when it gives it to your method, you're using the same object it stores. So, in psuedo code, the way the class works is:

// set a default value
args.PlayerToPrompt = PlayerIndex.One;

// fire the event
DeviceDisconnected(this, args);

// use the final PlayerToPrompt

By handing you the same object it is holding on to, you can edit that object before the SaveDevice uses it to prompt the user. 

Nov 7, 2009 at 6:14 PM

Hah, that's a clever technique! 

Thanks very much SimReality, that is a neat thing to be aware of.

Mar 25, 2010 at 2:58 PM

For those interested, here's the exact code I added to make this work.  My code was very similar to the example load/save code from Nick/SimReality:


(In side the setup/load function for the storage device)

sharedSaveDevice.DeviceSelectorCanceled += (s, e) => SetControllerIndex(s, e);

sharedSaveDevice.DeviceDisconnected += (s, e) => SetControllerIndex(s, e);


(Nearby new function)

public void SetControllerIndex(object sender, SaveDeviceEventArgs eventArgs)


   eventArgs.PlayerToPrompt = (PlayerIndex)input.Controllers[0].ControllerIndex;  // Everything after (PlayerIndex) is where I store the 1st player's controller index