Last time I mentioned I had to handle exceptions from the free-threaded ProxyModel. Now I do. All of the callback members (NewMessage, UserListChanged, MapChanged, Redraw, ExpectingPrerequisites, StepStatuses, TimeChanged and CurrentStep) now catch exceptions within the whatever Task they launch, and call an internal member called MarkException with whatever exception is caught.
MarkException updates an _Exceptions list (which only holds the DateTime.Now value and the exception.Message of all exceptions) for the ProxyModel, and also calls an ObserveException Action delegate (if assigned) to pass the full exception info.
I probably need to examine some of the exceptions and make decisions about tearing down the ProxyModel, or the actual communication proxies, but otherwise, I do not seem to get the same bad crashes on authentication failures.
I also cobbled together a WCF customBinding that uses tcpTransport without any channel privacy, but uses clear-text passwords. Not ideal, but suitable for LAN host testing without having to get testers mucking about with certificates.
I have also had some issues with the Grasp/Probe action when I aim the actor at another actor (I had previously tested on doors, walls and empty space without problems). I get some exceptions on the host, and eventually (if I keep trying) the client stops responding as well. I’ll try to isolate this before further cleaning up the host and client for ClickOnce packaging.
Awhile back I converted most of the client framework to be much more MVVM-ish. Part of this turned over proxy management to a ProxyModel class. In so doing, the mechanisms for getting the server’s user list and latest text-chat messages for the user were converted to functions designed to work in a free-threaded manner (in response to callbacks from the server).
Since all the communication between the server and the client is now handled without the WPF dispatcher thread getting involved (and better, the Login Dialog uses a call to the ProxyModel that invokes UserList and GetMessages through a TaskFactory.StartNew), it has come to my attention that I am not observing exceptions thrown from within the confines of the task-scheduler created threads.
What used to pop-up a “friendly” Ikosa exception dialog on a failed login attempt now simply crashes the client process as the when the task is garbage collected, the thrown (unobserved) exceptions are AppDomain poison. This has become my next “must-fix”…
Opportunistic attacks are now working fairly well. I’ve managed to trigger them off on movement from a threatened cube and by trying to use a ranged weapon in a threatened cube. Also tested: not being able to make an opportunistic attack if the target has cover, and only being able to attack when wielding a weapon that can make such an attack. Haven’t played with reach weapons yet.
I also discovered (and fixed) a problem with some of the attack handlers, in that I had a handler chain defined for a base class (AttackData) that prevented the chains for more specific attack types (MeleeAttackData, ReachAttackData and RangedAttackData) from activating. I ended up changing the interaction handler chain matching algorithm to work with exact type matches, rather than IsAssignableFrom(). Had to also make sure I wasn’t orphaning any use cases.
Lastly (and I still have to fix this), I discovered that a target standing on a low step could trigger a Cover alteration, resulting in a +4 to Armor Rating for the target. This is because the cubic region’s lower corners are blocked by the solid material of the cell. I’m going to look into using adjusted coordinates for determining extents for a target (rather than blindly using the cube corners) based on the IPhysical properties and intra-locator positioning (including Offsets)…and I’m going to put some stuff in to account for low barriers (2′ high or less) by trying some alternate point testing under “certain” conditions.
In order to really test delaying on one’s turn, I had to add another character to the setting. Red Dude, Blue Dude, and now Green (I forgot to include the last name of Dude). I need to run three clients to test them out. Eventually I’ll make a multi-character client for TB2.
Anyhow…I did find that although I had most of the code to manage the delay list and remove actors from it when they act, I hadn’t added anything to put them into the list when they delay for the first time.
So, I sorted that all out now; and exposed some client-state refresh issues.
Therefore: next up…better signalling from the host to the clients when the delay step is activated. When the DelayTickStep is the current step, the game clock doesn’t tick unless the delaying actor decides to act. Therefore, one of the normal update signals (time-tick) isn’t sent to the clients, like it is during a LocalTickStep or LocalTimeStep.
I also need some better visual cues in the client that they can or cannot act, based on who has the focused budget.
While I’m at it, I might as well get some character models with different colors. I have some…but they’re not dimensioned to work with the auto-scaling features of the creature sizer; yet I should be able to throw a Scale3DTransform around them in the XAML.
Opportunistic inquiry is on target now. I also found that I was sending the inquiry to the original actor, instead of the one that could opportunistically attack.
As far as the missing initiative roll goes, I haven’t been able to duplicate it. Perhaps I noticed it incorrectly…I’ll keep an eye on it.
Next big test: Ending a turn without using a turn (that is, delaying).
Expedition #3 taught me that in LINQ, you don’t get IEnumerable<???> sequences that evaluate to null. They will always have a value, even if they are empty due to where clauses. Seems pretty obvious, but apparently not to me when I originally wrote the code for opportunistic strike zone geometry culling. Should be fixed now. So expedition #4 will both confirm this, and try to isolate the problems with the missing iniative roll.
Fired up the host and enabled both red and blue dudes. (Literally “Red Dude” and “Blue Dude“).
Fired up a client, logged in as Red user playing as Red Dude. I immediately rolled initiative and sent the prerequisites to the host so I could move the window to get back to the client icon on the desktop.
Then I fired up another client and logged in as Blue user. For some reason, I didn’t get prompted for an initiative roll on blue. Just another thing to hunt down. Initiative startup step is probably reporting CanDoStep as true on any prerequisite being ready instead of all prerequisites being ready.
Anyway, expedition #3 is about exploring the phantom opportunistic attack inquiry. Breakpoint is in place.