I'm working on a server-based multiplayer game written in C#. The server and the client shares code and each object has the same int ID. I want to make the networking to be light as possible, by sending only the changed data.
The game has classes, which have numerous fields/properties, and they often change.
I'm seeking a way to detect when these values change and send these values to the client side.
Basically, this algorithm:
Flag object when it's changed
With the changed objects at network Tick:
Compare each property with their previous state
Send only the changed values
Store old values
Receive them on the client side
Instantiate the same type of object, or find it by ID
Set the new values
Of course, .NET Reflection may be eable to solve this problem, but iterating throuh 1000 object and their properties in each Tick, would be a bottleneck in performance.
I can send the basic types (int, float, vector), and maintain connection. My questions are these:
What's the best approach to send an object's Class and instantiate it?
How should I detect property change and how to serialise properties so I can find their "pair" on the client when receiving.
You can create something like this:
class Mob {
private int _health;
public int Health
{
get { return _health; }
set { _health = value; DirtyFlags |= MobDirtyFlags.Health
}
}
this means a lot of code for each property
Or you can have some custom dictionary and every change in that dictionary would be tracked, so
mob.Properties["Health"] = 10; would track that you changed something.
This is how Mooege (Diablo 3 emulator) does this.
First approach can be rewritten with aspects (probably some custom code that will generate all that code that is written above at runtime via Reflection.Emit or something similar).
Or if you know what will all your entities look like, you can generate classes for them from some templates (using something like T4)
as for serialization, this is good enough:
(key: int, value: object)
where key would be some enum like ActorProperties { Health, Strength, ...}
Related
public abstract class Unit
{
public abstract List<Move> allowedMoves{get;}
}
public class Javelineer : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.Impale, Move.JavelinThrow, Move.ShieldBlock};
}
public class Dragon : Unit
{
public List<Move> allowedMoves =>
new List<Move> {Move.BreatheFire, Move.Swipe, Move.Bite, Move.Devour, Move.TailBash};
}
The X:
Given the above code, if and how can I retrieve the allowed moves of a given unit without necessarily instantiating a new object?
I know I can retrieve the property with this code:
typeof(Javelineer).GetProperty("allowedMoves")
But if and how can I retrieve the definition of this property?
The Y:
The client (web browser) must send the game server the player's unit. This includes the unit's type and moves this unit is able to perform (4 out of all available; similarily to Pokemon).
While the validation (of course) is performed on the server, the browser still needs to get a list of available unit types and allowed moves.
In order not to duplicate code, I would like to avoid hard-coding this data in Javascript.
Having read some excellent SO questions & answers I think I can retrieve all available units with code similar to this:
Assembly.GetExecutingAssembly().GetTypes().Where(
type => type.BaseType == typeof(Unit)
).Select(type => type.Name).ToList()
I'd call this code on server startup, cache the result and send the cached result to every connecting client, because I have feeling this code is likely expensive to call.
But how can I retrieve the list of allowed moves?
You have a couple of options, but TL;DR: Construct the object instance and read the property.
In any case, here are some options, creative minds might be able to find a couple more even.
Construct the instance, read the property.
This is your best option code-wise because it will be easy to understand, maintain, bugfix.
Rewrite the code to allow for easy detection of the values using reflection
One way to do this would be to use attributes, tagging the property or object with the legal moves. However, to avoid having the bug that the attributes does one thing, the code another, you might have to change the code to use the attributes as well, which would be a performance hit.
Additionally, reading those attributes would likely construct many more objects than your original object.
Use mono.cecil or some other IL-inspection library to decode the code of the property getter and finding the construction of that list, extracting the values being added to the list. You would essentially either have to dumb down the code of that property to be on par with what you have right now (and never allow it to become more complex) or basically simulate execution of code.
This is like constructing a flotilla of space warships with enough firepower to demolish a local starsystem, just to kill an ant.
Bottom line, construct the object instance, read the property.
I'm writing a C# application that does some things with baseball statistics. I'm getting the data from an XML web service. I want to completely separate the presentation-business-data layers. In that vain I have created a service class to interact with the web service and to create objects from the data, a set of business classes (i.e. player, team, league), and the objects needed for my presentation layer.
I don't want to load the statistics into the player class because there are more than 200 statistics, and I'm not going to need them every time I instantiate the player class. For each statistic I need its abbreviation, description, XML attribute name, and value.
Question: What C# data-structures or method could be used to present more than two properties and allow several of them to be static across all instances of the datatype and allow at least one to be writable at run-time?
I started to create a "statistic" class like this:
public class BaseballStatistic
{
public string Abbreviation;
public string Description;
public string XmlAttributeName;
public string Value;
public BaseballStatistic(string abbreviation, string description, string xmlAttributeName)
{
Abbreviation = abbreviation;
Description = description;
XmlAttributeName = xmlAttributeName;
}
}
The problem with this is that I'll never need to change the abbreviation, description, or XML attribute name at run-time.
If I only needed the abbreviation and value, I'd use a Dictionary or some other Key/Value pair.
I started to create a statistic class with abbreviation, description, XML attribute name, and value members. But the only one of those that will ever change at runtime is the value - so this didn't feel like the right answer. (Imagine 500 players, each with an array of statistic objects, and those object are the exact same for all players except for the value.)
I considered creating a multidimensional array, but with so many constant values, it seems wasteful to load such a thing at run time.
I feel like I should know this.
I should add this: because there are so many different statistics that I can use, it would be great if I could find a solution that would expose them to Intellisense. For example:
Statistic g = Stats.GamesPlayed
It sounds like you need one class for "a statistic" - and then a Dictionary<PlayerStat, int> (or whatever the value would be).
The PlayerStat class would know about the abbreviation, description and XML attribute name - and I'd suggest that you probably create a Dictionary<string, PlayerStat> statically to map from abbreviation to statistic, and another one to map from XML attribute to abbreviation.
You may not even need the Dictionary<PlayerStat, int> in your Player class... you could always add an indexer or method which looked things up lazily. (Be careful with this, however - you may find that loading many things lazily will be more expensive than loading everything in one go. You may want to break the statistics into categories, and load all the stats for a single category when you load one of them. Basically, if there are clumps of stats that are usually used together...)
Before I switched to iOS development via Monotouch I played around a bit with ObjectiveC. Ever since one thing has been on my mind "Key Value Coding" (KVC). I have never understood what it is good for and what the magic behind it is.
For my understanding it is just a collections of names and values, like .NET's NameValueCollection: Instead of setting anObject.Address = "An address Value" you would write anObject.Properties["Address"] = "An address value".
Great. So what? Because this appears to be too easy to me I'm sure that can't be it.
Or is it because .NET has reflection and therefore has no need for something like Key-Value-Coding? I can grab the type of "anObject" and use reflection to loop all of its properties and look for the one called "Address" and then use reflection to set the value.
Is that maybe the analogy of KVC?
I'm hoping there is somebody out there who's a pro in ObjC and C#/.NET who can explain to me what the benefits are and how it would translate into .NET.
Please don't just point me to Apple's documentation. I know all that. I'm trying to find out if something has been missing in my coding-life so far by not knowing KVC? Or have I maybe been using something similar in .NET not being aware that it would translate into KVC if I was using ObjC?
From somebody who uses both every day for probably 3 years now:
As you figured out, there's nothing amazingly complex in KVC that can't be done with dictionaries and NameValueCollections in C#.
The big difference is that KVC is built in the language. An object in Obj-C IS a NameValueCollection. You don't have to change the way you develop (from classes and properties to dictionaries) to use it. You can create your object with the properties you want, and then later on call a valueForKey:#"name", and everything still works.
Now you can say: "yeah cool, but I can do that with reflection!". Sure you can, but just as before, you'll have to change the way you develop again, not counting the fact that reflection is a lot slower in general.
Another cool feature of KVC it it allows you to use KVO, which basically allows you to register to receive notifications about changes in any object without having to write a single line of code in those objects. So, in any object in your application, you can call "addObserver:forKeyPath:", and receive a callback if anybody else in your application changes that property. This is really useful for live apps, like iOS apps.
Again, you can implement KVO in C# (MVVM frameworks for example do this all the time), but you have to write extra code for that. In Obj-C, it's built in the language.
I blogged about this in the context of MonoMac, the peer project to MonoTouch but used for building Mac applications:
http://tirania.org/monomac/archive/2010/Dec-07.html
Key-Value Coding is a set of practices that allow applications to access object properties using strings. This is similar to Binding Expressions in Silverlight. In both cases the purpose is to allow tooling that does not directly have access to your native code to access properties from your program.
In particular, this is useful because some APIs can take advantage of this. For example CoreAnimation can animate properties given their "path" to the object. For example, you can do:
var animateX = CAKeyFrameAnimation.FromKeyPath ("position.x");
pos.Values = new NSNumber [] { 0, 10, 60 };
layer.AddAnimation (animateX, "move");
The "position.x" in this case references the layer's position, and within that position it's X component.
The blog post above goes into more detail about how you can actually expose your own objects to participate in this protocol (registering your own properties to make them visible to the Key-Value-Coding system).
Kenneth, another one of the MonoMac developers blogged about this extensively here:
http://cocoa-mono.org/archives/153/kvc-kvo-and-cocoa-bindings-oh-my-part-1/
In particular he deals with the similarities with Reflection and he shows you how to use [Export] to turn your C# code into KVC compliant code as well.
If you access a property like this
anObject.Address = "An address Value"
The code will be very "static". It will always access Address
You can create a more dynamic code like this
void SetProperty (string propertyName, string value)
{
anObject.Properties[propertyName] = value;
}
You would do this if you do not know at compile time which property will be accessed.
In c# you would typically use a Dictionary<TKey,TValue> for storing key/value pairs. Automatically accessing properties via KVC as in Objective-C is not supported in c#. You would either declare the property as
public Dictionary<string,string> Properties { get; private set; }
and instantiate it in the class constructor with
Properties = new Dictionary<string,string>();
then you could access it like this
anObject.Properties[propertyName] = value;
Or you would have to use Reflection to access the property
Type type = anObject.GetType();
// Or Type type = typeof(TypeOfAnObject);
PropertyInfo prop = type.GetProperty(propertyName);
prop.SetValue(anObject, propertyValue, null);
However, this is not very efficient.
I have some serverside data that I need replicating (pushed in real-time) from a server app to around 100 wpf clients. My problem is when a given Order object changes it typically only changes a 1 or 2 fields so I only want to send those changes over the wire Not the whole object – thus decreasing the wire payload, processing time etc as the whole Order object has around 50 fields.
The data is a Dictionary of Order objects keyed on OrderId. I use protobuf-net to seralise the data and send over the wire to the wpf clients.
Has anyone dealt with this patterm/problem before? Or have any ideas on who to achieve this?
Thanks a lot.
Create a simple proxy using Castle.DynamicProxy which saves the name of all properties that have been changed.
protobuf-net supports a number of patterns to aid this type of scenario, the simplest being (to share the pattern used by System.ComponentModel):
[ProtoMember(1)]
public string Foo { get;set; }
public bool ShouldSerializeFoo() { /* return true if Foo is "dirty" */ }
This assumes you have some mechanism for tracking the changes yourself (for hooking into the ShouldSerialize* method); protobuf-net doesn't do change tracking itself. If you don't currently have any change tracking, you might be able to use something from this answer: Comparing 2 objects and retrieve a list of fields with different values
I got a MarshalByRefObject named "DefaultMeasurement", which contains a List of IPoint-objects.
public class DefaultMeasurement : MarshalByRefObject, IMeasurement
{
private List<IPoint> iPoints;
public this[int aIndex]
{
get { return iPoints[aIndex];}
}
}
[Serializable]
public class DefaultPoint : IPoint, ISerializable
{
public int Value {get;set;}
}
When first retrieving the DefaultMeasurement object from the server all the points get serialized and during all subsequent calls to DefaultMeasurement.Points I get the list that was correct upon startup of my client. But in the meantime the state of at least one object in that list might have changed and I don't get that current state, although in the server that state gets updated.
How do I force an update of that list?
further clarification:
- it will work once I do DefaultPoint : MarshalByRefObject, but that is not an option as it negatively affects performance
- by 'update' I mean changes to existing objects on the server, no adding / removing on the list itself
- I might have up to 80k DefaultPoint objects
Since you don't want the Point itself to be MarshalByRef (as that introduces a LOT of traffic if you have a substantial number of points), what I would recommend is that you have explicit methods that synchronize point values. After you've made a significant number of changes on the server, you call the SynchronizePoints() method, which includes new values for all of the points. Now the client-side proxy has an updated state. Better yet, remove the state from the object in the first place (since it's not really a direct reflection of server state) and instead use client-side objects that are instantiated as needed when gathering points from the server.
You would have to implement a callback that notifies the client of changes on the server.
The notify could pass id of the objects that have changed or the client could ask for a list of changed objects.