• entries
    359
  • comments
    237
  • views
    188451

Progress Report

Sign in to follow this  
Telastyn

70 views

So word is in that the interviews last week are no-goes. One ran into bureaucratic malaise and they're not hiring anyone. The other was a poor fit (what the hell do I know about assembly lines?) and they've two other candidates likely better suited for the job.

On a slightly related note, I spent the past 12 hours banging my head against C# reflection. It might be one of ignorance or design block, but I couldn't get this scenario working:

In the game, most objects have properties which define game values. Changing a property triggers a series of events, starting with a local instance event, triggering 'containing' events up to a master event which triggers whenever an instance of that property changes state. It's common on the server side for all of those 'master' events to have a listener which relays the state change to clients that can see the object in question.

So, the plan was to use C# Attributes. Game visible properties would be tagged with an attribute which houses the network message ID, and the Fog of War level at which the property is visible (For example, a tile's resources suddenly vanish. An empire with a unit in the tile will see that change, an empire which only explored the tile ages ago would not). Reflection could then be used to auto-generate the network message sending and recieving stuff.

So looking up the attributes, easy. Finding the delegate fields representing the events, easy. Generating an object to do the message sending, easy. Identifying the types in the delegate, or setting anything to the delegate fields, or getting the generated object to convert into a delegate? 12 hours of misery.

The closest I got was setting the delegate to a dynamically generated Generic class with an implicit conversion operator. Unfortunately, the generated generic class wouldn't convert nicely (since it's technically a different type than the actual Generic class' operator expects?) despite the fact that I could explicitly assign the class to the Reflected field.

I think that recieving and other Fog stuff can be fully automated, but I've not tried it quite yet. For now I'm going to semi-manually enter the message listeners. The name and fog will still be drawn from Attributes, but I'll need to enter the actual registration for each new property.


For those curious, here's a snippet of what the attribute addition looks like in code:

[GameProperty("UnitLocation", Knowledge.Level.Seen)]
public Tile Location {
get {
return (tile);
}
set {
if (tile != value) {
Tile tmp = tile;
tmp.Remove(this);
tile = value;
tile.Add(this);
LocationChange(this, tmp, tile);
}
}
}



I also did a little bit of testing last night on the event structure and Fog discovery events, which work much better than their previous incarnations. And I ended up reading through a good portion of the C# specs hunting for generics tidbits that might explain why things weren't working. Now I just need to find job opportunities that aren't doing QA work on PoS GPS recievers in semi-trucks...
Sign in to follow this  


2 Comments


Recommended Comments

Guest Anonymous Poster

Posted

Hi,

This may help or strike up some thought:

Take a look at System.ComponentModel.Design Namespace in the .NET Framework. It sort of indirectly relates to the automatic event invocation your looking for. This is how the Property Grid in VisualStudio.NET works.

VS doesn't actually change any properties directly when you change it's value in the property grid. It uses the associated PropertDescriptor's (which it gets from the TypeDescriptor.GetProperties() method) SetValue method which fires off the component changing/change events of the "component change service" and uses reflection to set the value (PropertyInfo.SetValue).

The event args for the change service events include the object changed, the property changed and the old and new values (See IComponentChangeService.ComponentChanged).

You could use all the services/object already created for you in the Framework under said namespace. i.e DesignSurfaceManager, DesignSurface, IComponentChangeService, ISelectionService, etc. The requirement is that your objects would have to implement IComponent or inherit from Component. There's a bit of development and setup time for this.

...or mimic the pattern. You could create your own component change service (IComponentChangeService-like), your own TypeDescriptor.GetProperties-like method that returned your own PropertyDescriptor-like objects (for only properties adorned with the "GamePropertyAttribute" probably).

So, to set it all up, create the component change service and subscribe to all the events once. (In those event handlers is where you could put your automatic network message creation.) Any object that needs to change a property, get a property descriptor for said property from a GetProperties method and call the SetValue. Within SetValue, it fires off the change events and sets the property using reflection.

...or something like that. The performance of reflection should probably be taken into consideration.

Good luck!



Share this comment


Link to comment
Hrm, that's interesting.

It's pretty much what I was doing, only the final SetValue on the change event was impossible as I couldn't generate the proper delegate (I imagine Com stuff has a fixed generic event?) or get a generated object to convert into the delegate type.

Anyways, thanks for the tip AP, I'll look into that.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now