Monogame Custom Importer/Processor not being detected by Content Manager - c#

Pretty much what it says in the title.
I've built a second .dll file which contains my Content Importer/Processor and added that .dll file in my 'References' section for my Content Manager for my project, but nothing. The Manager doesn't detect my custom importer/processor. No idea what's going on and I wasn't able to find anyone else having an issue like this, so I was hoping someone more experienced could help me out here!
I am using Json.NET for the Json Deserialization by the way.
Thank you in advence :)
MapJson Code:
public class MapJson
{
[JsonProperty("name")]
public String Name = "";
[JsonProperty("width")]
public Int32 MapWidth = 0;
[JsonProperty("height")]
public Int32 MapHeight = 0;
}
Importer Code:
[ContentImporter(".amap", DefaultProcessor = "MapProcessor", DisplayName = "Map Importer - Engine")]
public class MapImporter : ContentImporter<MapJson>
{
public override MapJsonImport(string filename, ContentImporterContext context)
{
string json = new FileHandle(filename).ReadAll();
MapJson data = JsonConvert.DeserializeObject<MapJson>(json);
return data;
}
}
Processor Code:
[ContentProcessor(DisplayName = "Map Processor - Engine")]
public class MapProcessor : ContentProcessor<MapJson, MapJson>
{
public override MapJson Process(MapJson input, ContentProcessorContext context)
{
return input;
}
}
Writer Code:
[ContentTypeWriter]
public class MapWriter : ContentTypeWriter<MapJson>
{
protected override void Write(ContentWriter writer, MapJson value)
{
writer.Write(value.Name);
writer.Write(value.MapWidth);
writer.Write(value.MapHeight);
}
}
Reader Code:
public class MapReader : ContentTypeReader<Map>
{
protected override Map Read(ContentReader reader, Map existingInstance)
{
MapJson data = new MapJson();
data.Name = reader.ReadString();
data.MapWidth = reader.ReadInt32();
data.MapHeight = reader.ReadInt32();
// this constructor just sets my 'Map' class's Name, MapWidth and MapHeight variables
return new Map(data);
}
}

Well uhh this is embarrassing...
The solution was to first build the game project, then to actually re-build the content importer/processor project, and then to link it with the content manager!
I feel so stupid haha

Related

Unexpected binary element 255 when serializing

I'm using Unity 2017 and wish to serialize save game data like so:
public void Save(Statistics data)
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath
+ "/playerInfo.dat");
bf.Serialize(file, data);
file.Close();
}
The LevelData class is marked Serializable and contains only strings and ints. The class that implements IPersistentData meets those requirements too.
I did look for the problem and found that I should set an environment variable in my Awake method that I did, but that didn't solve anything. I'm using Windows 10 as operating system to develop on but the game will be made for Android.
When attempting to save, I always get this exception
SerializationException: Unexpected binary element: 255
System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info)
Any sort of advice is welcome to get around the issue.
EDIT
Updating after trying the hints of Programmer:
The class I wish to serialize:
[Serializable]
public class Statistics
{
public int LastPlayedLevel;
public Statistics()
{
MusicVolume = 1f;
SFXVolume = 1f;
LevelDatas = new List<LevelData>();
LastPlayedLevel = 1;
}
public float MusicVolume;
public float SFXVolume;
public List<LevelData> LevelDatas;
}
And the LevelData:
[Serializable]
public class LevelData
{
public LevelData(int levelNumber,string name)
{
this.LevelNumber = levelNumber;
this.Name = name;
this.BestPercent = 0;
this.DeathCount = 0;
}
public int LevelNumber;
public string Name;
public int BestPercent;
public uint DeathCount;
}

How to take screenshot in android/iOS mobile testing - C#?

How can I take screenshots for different steps performing in execution of an automated test for android/iOS mobile in C# language?
There appear to be numerous suggestions on how to do this.
This is one places code in OnCreateView():
public static Android.Content.Context Context { get; private set; }
public override View OnCreateView(View parent, string name, Context context, IAttributeSet attrs)
{
MainActivityContext = context;
return base.OnCreateView(parent, name, context, attrs);
}`
Then, I wrote a service implemenatation in which I take a screen capture, by using the static Context of the MainActivity, like this :
`public class SnapshotService : ISnapshotService
{
public void Capture()
{
var screenshotPath =
Android.OS.Environment.GetExternalStoragePublicDirectory("Pictures").AbsolutePath +
Java.IO.File.Separator +
"screenshot.png";
var rootView = ((Android.App.Activity)MainActivity.Context).Window.DecorView.RootView;
using (var screenshot = Android.Graphics.Bitmap.CreateBitmap(
rootView.Width,
rootView.Height,
Android.Graphics.Bitmap.Config.Argb8888))
{
var canvas = new Android.Graphics.Canvas(screenshot);
rootView.Draw(canvas);
using (var screenshotOutputStream = new System.IO.FileStream(
screenshotPath,
System.IO.FileMode.Create))
{
screenshot.Compress(Android.Graphics.Bitmap.CompressFormat.Png, 90, screenshotOutputStream);
screenshotOutputStream.Flush();
screenshotOutputStream.Close();
}
}
}
}`
C#
You can use this piece of code:
ScenarioContext.Current.Get<IApp>("Application").Screenshot(ScenarioStepContext.Current.StepInfo.Text);

Empty serialized XML file

i get an empty xmlfile after serializing an object. I'm using Monodevelop and Unity 4. I searched for such a long time mostly in this community, but i only found difficult problems with even more difficult answers :) I think mine is so simple, please help me. (I am new to c#)
The serialized object is this:
[System.Serializable]
public class information {
private string data1;
private string data2;
private string data3;
public void Data1(string text)
{
data1 = text;
}
public string GetData1 ()
{
return data1;
}
public void Data2(string text)
{
data2 = text;
}
public string GetData2 ()
{
return data2;
}
public void Data3(string text)
{
data3 = text;
}
}
the serializing class is this, here might be the problem:
public class SaveXml {
public void SaveData(object obj, string filename)
{
XmlSerializer sr = new XmlSerializer(obj.GetType());
TextWriter writer = new StreamWriter(filename);
sr.Serialize(writer, obj);
writer.Close();
}
public string Load()
{
if(File.Exists("accdata.xml"))
{
XmlSerializer xs = new XmlSerializer(typeof(information));
FileStream read = new FileStream("accdata.xml",FileMode.Open, FileAccess.Read, FileShare.Read);
information info = (information)xs.Deserialize(read);
return info.GetData1();
}
else
{
return "file does not exist";
}
}
And the serializing and the serialized object get called by a menu that has this 2 buttons:
if(GUI.Button(new Rect(10,50,300,100),"Save"))
{
SaveXml saver = new SaveXml();
information infol = new information();
infol.Data1("textone");
infol.Data2("texttwo");
infol.Data3( "textthree");
saver.SaveData(infol, "accdata.xml");
}
if(GUI.Button(new Rect(500,50,300,100),"Load"))
{
SaveXml saver1 = new SaveXml();
text = saver1.Load();
}
so the variable text that is declared in the class menu, should be "textone", after i clicked the Save Button and the LoadButton. The Savebutton creates a file that is empty.
The Deserialization seems to work but of course there is no String in the data1 variable in Information so the variable in the menu called text is empty too. I get no errors and i can work with the object after serialization.
So why doesnt my serialization work? Please help me. I excuse for my bad english and mistakes, i am new to stackoverflow.
Xml serializer serializes public fields/properties not methods. Change your methods to properties. For ex,
public string Data2
{
set { data2 = value; }
get { return data2; }
}
So your information class can be
public class Information
{
public string Data1 { get; set; }
public string Data2 { get; set; }
public string Data3 { get; set; }
}
BTW: you don't need this Serializable attribute. It is only used by BinaryFormatter
I'm not sure but from what i see you don't have any public fields... Take a look here
And also, why don't you just use auto getter/setter ?
According to this MSDN support article, using XmlSerializer the way you have performs only "shallow" serialization - it only serializes public fields/properties. To serialize private data requires "deep" serialization which appears to be a whole other animal.

How do I use my own debugger visualiser to edit variables runtime?

I'm writing my own debugger visualiser. All works great to show up to visualiser with the data.
Now I add the code for more clearness:
public class MyVisualiserObjectSource : VisualizerObjectSource
{
public override void GetData(object target, Stream outgoingData)
{
string data= target as string;
var writer = new StreamWriter(outgoingData);
writer.Write(data);
writer.Flush();
}
}
public class MyVirtualizer : DialogDebuggerVisualizer
{
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
var streamReader = new StreamReader(objectProvider.GetData());
string data = streamReader.ReadToEnd();
using (var form = new MyVirtualizerForm(data))
{
windowService.ShowDialog(form);
}
}
}
The string here is passed to the visualizer and show my own form. It works.
But now I want to pass back the modified data from the form to the variable.
How do I do that?
Edit:
I found out that I need to override the TransferData method in VisualizerObjectSource. But in the MSDN is no detail information about how I implement this correctly.
Can someone help me please?
Edit 2:
I looked with IL-Spy what TransferData method does. It throws an exception.
So I override the method. But it is still not working. In the incomingData is the modified string from the Form. But I do not get back this value into the variable :(
public class StringVisualiserObjectSource : VisualizerObjectSource
{
public override void GetData(object target, Stream outgoingData)
{
var data = target as string;
var writer = new StreamWriter(outgoingData);
writer.Write(data);
writer.Flush();
}
public override void TransferData(object target, Stream incomingData, Stream outgoingData)
{
incomingData.CopyTo(outgoingData);
}
}
You just need to add a public property to your form that contains the data you wish to "pass back". For example, if your form contains a textbox called MyDataTextBox, you need to create a public property on your form like:
public MyVirtualizerForm : System.Windows.Form
{
public string MyData
{
get{ return MyDataTextBox.Text;}
}
}
You can then get access to the text of the textbox when the form is closed by doing the following:
Edited - Passing the data back to the variable
This assumes that the data you are getting back from the form is a string.
using (var form = new MyVirtualizerForm(data))
{
windowService.ShowDialog(form);
var formData = form.MyData;
using (MemoryStream returnStream =
new MemoryStream(ASCIIEncoding.Default.GetBytes(formData)))
{
objectProvider.TransferData(returnStream);
}
}
Is this what you want to achieve? Also, you may find the following link useful as reference: http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.debuggervisualizers.ivisualizerobjectprovider.transferdata.aspx

How to pass custom data to deserialization function

I'm doing some C# IO work and I want to import/export data from a few classes.
After looking for a while, it seems serialization is pretty close to what I want.
However, there is a problem. I have a XML file that describes members of a certain class(which I will refer as ValueWithId), which are aggregated in a class which I will call CollectionOfValuesWithId for the purposes of this question.
ValueWithId is a class that contains a string member called ShortName, which is unique. There is only one ShortName per ValueWithId and all ValueWithId have a non-null ShortName. CollectionOfValuesWithId contains a function to find the ValueWithId with a given ShortName.
When serializing, I do NOT want to store ValueWithId nor CollectionOfValuesWithId in the output file. Instead, I just want to store the ShortName in the file.
So far, so good. I just need to use SerializationInfo.AddValue("ValueWithId", MyValueWIthId.ShortName).
The problem comes with deserialization. Some googling suggests that to read data from a file one would do this:
public SomeClassThatUsesValueWithId(SerializationInfo info, StreamingContext ctxt)
{
string name = (string)info.GetValue("ValueWithId", typeof(string));
}
However, the string is not enough to recover the ValueWithId instance. I also need the CollectionOfValuesWithId. I want something like this:
public SomeClassThatUsesValueWithId(SerializationInfo info,
StreamingContext ctxt, CollectionOfValuesWithId extraParameter)
In other words, I need to pass extra data to the deserialization constructor. Does anyone know any way to do this or any alternatives?
I figured it out. The important class to do this is StreamingContext.
This class conveniently has a property named Context(which can be set in the constructor parameter additional.
From MSDN:
additional
Type: System.Object
Any additional information to be associated with the
StreamingContext. This information is available to any object that
implements ISerializable or any serialization surrogate. Most users do
not need to set this parameter.
So here is some sample code regarding how to do this(tested on Mono, but I think it should work on Windows):
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class ValueWithId
{
public string ShortName;
public string ActualValue;
public ValueWithId(string shortName, string actualValue)
{
ShortName = shortName;
ActualValue = actualValue;
}
public override string ToString()
{
return ShortName + "->" + ActualValue;
}
}
public class CollectionOfValuesWithId
{
private IList<ValueWithId> Values = new List<ValueWithId>();
public void AddValue(ValueWithId val)
{
Values.Add(val);
}
public ValueWithId GetValueFromId(string id)
{
foreach (var value in Values)
if (value.ShortName == id)
return value;
return null;
}
}
[Serializable]
public class SomeClassThatUsesValueWithId : ISerializable
{
public ValueWithId Val;
public SomeClassThatUsesValueWithId(ValueWithId val)
{
Val = val;
}
public SomeClassThatUsesValueWithId(SerializationInfo info, StreamingContext ctxt)
{
string valId = (string)info.GetString("Val");
CollectionOfValuesWithId col = ctxt.Context as CollectionOfValuesWithId;
if (col != null)
Val = col.GetValueFromId(valId);
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
//Store Val.ShortName instead of Val because we don't want to store the entire object
info.AddValue("Val", Val.ShortName);
}
public override string ToString()
{
return "Content="+Val;
}
}
class MainClass
{
public static void Main(string[] args)
{
CollectionOfValuesWithId col = new CollectionOfValuesWithId();
col.AddValue(new ValueWithId("foo", "bar"));
SomeClassThatUsesValueWithId sc = new SomeClassThatUsesValueWithId(col.GetValueFromId("foo"));
BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File, col));
using (var stream = new FileStream("foo", FileMode.Create))
{
bf.Serialize(stream, sc);
}
col.GetValueFromId("foo").ActualValue = "new value";
using (var stream2 = new FileStream("foo", FileMode.Open))
{
Console.WriteLine(bf.Deserialize(stream2));
}
}
}
The output I get is:
Content=foo->new value
Which is exactly what I wanted.

Categories